Regressão linear do TensorFlow com faceta e termo de interação
Neste tutorial, você aprenderá como verificar os dados e prepará-los para criar uma tarefa simples de regressão linear.
Este tutorial está dividido em duas partes:
- Procure interação
- Teste o modelo
De acordo com o relatório tutorial anterior, você usou o conjunto de dados de Boston para estimar o preço médio de uma casa. O conjunto de dados de Boston tem um tamanho pequeno, com apenas 506 observações. Este conjunto de dados é considerado uma referência para testar novos algoritmos de regressão linear.
O conjunto de dados é composto por:
Variável | Descrição |
---|---|
zn | A proporção de terrenos residenciais zoneados para lotes com mais de 25,000 pés quadrados. |
indus | A proporção de acres comerciais não varejistas por cidade. |
nox | concentração de óxidos nítricos |
rm | número médio de quartos por habitação |
idade | a proporção de unidades ocupadas pelos proprietários construídas antes de 1940 |
dis | distâncias ponderadas para cinco centros de emprego de Boston |
imposto | taxa de imposto sobre a propriedade de valor total por dólares 10,000 |
ptratio | a proporção aluno-professor por cidade |
medv | O valor médio das casas ocupadas pelos proprietários em milhares de dólares |
criminoso | taxa de criminalidade per capita por cidade |
chas | Variável fictícia Charles River (1 se limita o rio; 0 caso contrário) |
B | a proporção de negros pela cidade |
Neste tutorial, estimaremos o preço mediano usando um regressor linear, mas o foco está em um processo específico de aprendizado de máquina: "preparação de dados."
Um modelo generaliza o padrão nos dados. Para capturar esse padrão, você precisa primeiro encontrá-lo. Uma boa prática é realizar uma análise de dados antes de executar qualquer algoritmo de aprendizado de máquina.
Escolher os recursos certos faz toda a diferença no sucesso do seu modelo. Imagine que você tenta estimar o salário de um povo, se não incluir o gênero como covariável, você acaba com uma estimativa ruim.
Outra forma de melhorar o modelo é observar a correlação entre a variável independente. Voltando ao exemplo, você pode pensar na educação como um excelente candidato para prever o salário, mas também a ocupação. É justo dizer que a profissão depende do nível de escolaridade, nomeadamente o ensino superior conduz frequentemente a uma melhor profissão. Se generalizarmos esta ideia, podemos dizer que a correlação entre a variável dependente e uma variável explicativa pode ser ampliada por mais uma variável explicativa.
Para captar o efeito limitado da educação sobre a ocupação, podemos utilizar um termo de interação.
Se você olhar para a equação salarial, ela se tornará:
If é positivo, então implica que um nível adicional de educação produz um aumento maior no valor mediano de uma casa para um nível de ocupação elevado. Em outras palavras, há um efeito de interação entre educação e ocupação.
Neste tutorial, tentaremos ver quais variáveis podem ser boas candidatas para termos de interação. Testaremos se adicionar esse tipo de informação leva a uma melhor previsão de preços.
Estatísticas resumidas
Existem algumas etapas que você pode seguir antes de prosseguir para o modelo. Conforme mencionado anteriormente, o modelo é uma generalização dos dados. A melhor prática é entender os dados e fazer uma previsão. Se você não conhece seus dados, você tem poucas chances de melhorar seu modelo.
Como primeira etapa, carregue os dados como um dataframe do pandas e crie um conjunto de treinamento e um conjunto de testes.
Dicas: Para este tutorial, você precisa ter o matplotlit e o seaborn instalados em Python. Você pode instalar Python pacote em tempo real com Jupyter. Você Não deveria fazer isso
!conda install -- yes matplotlib
mas a
import sys !{sys.executable} -m pip install matplotlib # Already installed !{sys.executable} -m pip install seaborn
Observe que esta etapa não é necessária se você tiver o matplotlib e o seaborn instalados.
Matplotlib é a biblioteca para criar um gráfico em Python. Seaborn é uma biblioteca de visualização estatística construída sobre matplotlib. Oferece terrenos atraentes e bonitos.
O código abaixo importa as bibliotecas necessárias.
import pandas as pd from sklearn import datasets import tensorflow as tf from sklearn.datasets import load_boston import numpy as np
A biblioteca sklearn inclui o conjunto de dados de Boston. Você pode chamar sua API para importar os dados.
boston = load_boston() df = pd.DataFrame(boston.data)
Os nomes do recurso são armazenados no objeto feature_names em um array.
boston.feature_names
saída
array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')
Você pode renomear as colunas.
df.columns = boston.feature_names df['PRICE'] = boston.target df.head(2)
Você converte a variável CHAS como uma variável de string e a rotula com sim se CHAS = 1 e não se CHAS = 0
df['CHAS'] = df['CHAS'].map({1:'yes', 0:'no'}) df['CHAS'].head(5) 0 no 1 no 2 no 3 no 4 no Name: CHAS, dtype: object
Com pandas, é simples dividir o conjunto de dados. Você divide aleatoriamente o conjunto de dados com 80% de conjunto de treinamento e 20% de conjunto de teste. Pandas tem uma função de custo integrada para dividir uma amostra de quadro de dados.
O primeiro parâmetro frac é um valor de 0 a 1. Você o define como 0.8 para selecionar aleatoriamente 80% do quadro de dados.
Random_state permite que o mesmo dataframe seja retornado para todos.
### Create train/test set df_train=df.sample(frac=0.8,random_state=200) df_test=df.drop(df_train.index)
Você pode obter a forma dos dados. Deveria ser:
- Conjunto de trem: 506*0.8 = 405
- Conjunto de teste: 506*0.2 = 101
print(df_train.shape, df_test.shape)
saída
(405, 14) (101, 14)
df_test.head(5)
saída
CRIME | ZN | INDUS | CHAS | NOX | RM | Idade | DIS | RAD | IMPOSTO | PTRAÇÃO | B | LSTAT | PREÇO | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | não | 0.538 | 6.575 | 65.2 | 4.0900 | 1.0 | 296.0 | 15.3 | 396.90 | 4.98 | 24.0 |
1 | 0.02731 | 0.0 | 7.07 | não | 0.469 | 6.421 | 78.9 | 4.9671 | 2.0 | 242.0 | 17.8 | 396.90 | 9.14 | 21.6 |
3 | 0.03237 | 0.0 | 2.18 | não | 0.458 | 6.998 | 45.8 | 6.0622 | 3.0 | 222.0 | 18.7 | 394.63 | 2.94 | 33.4 |
6 | 0.08829 | 12.5 | 7.87 | não | 0.524 | 6.012 | 66.6 | 5.5605 | 5.0 | 311.0 | 15.2 | 395.60 | 12.43 | 22.9 |
7 | 0.14455 | 12.5 | 7.87 | não | 0.524 | 6.172 | 96.1 | 5.9505 | 5.0 | 311.0 | 15.2 | 396.90 | 19.15 | 27.1 |
Os dados são confusos; muitas vezes é desequilibrado e repleto de valores atípicos que prejudicam a análise e o treinamento de aprendizado de máquina.
A primeira etapa para limpar o conjunto de dados é entender onde ele precisa de limpeza. Limpar um conjunto de dados pode ser complicado, especialmente de qualquer maneira generalizável
A equipe de pesquisa do Google desenvolveu uma ferramenta para este trabalho chamada Facetas que ajudam a visualizar os dados e dividi-los de todas as maneiras. Este é um bom ponto de partida para compreender como o conjunto de dados é organizado.
As facetas permitem que você descubra onde os dados não parecem exatamente como você está pensando.
Exceto pelo aplicativo da web, o Google facilita a incorporação do kit de ferramentas em um Jupyter notebook.
Existem duas partes nas Facetas:
- Visão geral das facetas
- Aprofundamento das facetas
Visão geral das facetas
Visão geral de facetas fornece uma visão geral do conjunto de dados. A visão geral das facetas divide as colunas dos dados em linhas de informações importantes, mostrando
- a porcentagem de observação perdida
- valores mínimo e máximo
- estatísticas como média, mediana e desvio padrão.
- Ele também adiciona uma coluna que mostra a porcentagem de valores zero, o que é útil quando a maioria dos valores é zero.
- É possível ver essas distribuições no conjunto de dados de teste, bem como no conjunto de treinamento para cada recurso. Isso significa que você pode verificar se o teste tem uma distribuição semelhante aos dados de treinamento.
Este é pelo menos o mínimo a ser feito antes de qualquer tarefa de aprendizado de máquina. Com esta ferramenta você não perde esta etapa crucial e destaca algumas anormalidades.
Aprofundamento das facetas
Facets Deep Dive é uma ferramenta interessante. Ele permite ter alguma clareza em seu conjunto de dados e ampliar totalmente para ver um dado individual. Isso significa que você pode facetar os dados por linha e coluna em qualquer um dos recursos do conjunto de dados.
Usaremos essas duas ferramentas com o conjunto de dados de Boston.
Note: você não pode usar Visão geral de facetas e Aprofundamento de facetas ao mesmo tempo. Você precisa limpar o notebook primeiro para trocar a ferramenta.
Instalar faceta
Você pode usar o aplicativo da web Facet para a maior parte da análise. Neste tutorial, você verá como usá-lo dentro de um Jupyter Caderno.
Primeiro de tudo, você precisa instalar o nbextensions. Isso é feito com este código. Você copia e cola o seguinte código no terminal da sua máquina.
pip install jupyter_contrib_nbextensions
Em seguida, você precisa clonar os repositórios no seu computador. Você tem duas opções:
Opção 1) Copie e cole este código no terminal (Recomendado)
Se você não possui o Git instalado em sua máquina, acesse esta URL https://git-scm.com/download/win e siga as instruções. Quando terminar, você pode usar o comando git no terminal para usuário Mac ou prompt do Anaconda para Windows usuário
git clone https://github.com/PAIR-code/facets
Opção 2) Acesse https://github.com/PAIR-code/facets e baixe os repositórios.
Se você escolher a primeira opção, o arquivo vai parar no seu arquivo de download. Você pode permitir o download do arquivo ou arrastá-lo para outro caminho.
Você pode verificar onde o Facets está armazenado com esta linha de comando:
echo `pwd`/`ls facets`
Agora que localizou o Facets, você precisa instalá-lo em Jupyter Caderno. Você precisa definir o diretório de trabalho para o caminho onde as facetas estão localizadas.
Seu diretório de trabalho atual e a localização do zip do Facets devem ser os mesmos.
Você precisa apontar o diretório de trabalho para o Facet:
cd facets
Para instalar facetas em Jupyter, você tem duas opções. Se você instalou Jupyter com Conda para todos os usuários, copie este código:
pode usar jupyter nbextension install facets-dist/
jupyter nbextension install facets-dist/
Caso contrário, use:
jupyter nbextension install facets-dist/ --user
Tudo bem, está tudo pronto. Vamos abrir a visão geral do faceta.
Visão geral
Visão geral usa um Python script para calcular as estatísticas. Você precisa importar o script chamado generic_feature_statistics_generator para Jupyter. Não se preocupe; o script está localizado nos arquivos de facetas.
Você precisa localizar seu caminho. Isso é feito facilmente. Você abre facetas, abre o arquivo facets_overview e depois python. Copie o caminho
Depois disso, volte para Jupyter, e escreva o seguinte código. Altere o caminho '/Users/Thomas/facets/facets_overview/python' para seu caminho.
# Add the facets overview python code to the python path# Add t import sys sys.path.append('/Users/Thomas/facets/facets_overview/python')
Você pode importar o script com o código abaixo.
from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator
No Windows, o mesmo código se torna
import sys sys.path.append(r"C:\Users\Admin\Anaconda3\facets-master\facets_overview\python") from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator
Para calcular as estatísticas do recurso, você precisa usar a função GenericFeatureStatisticsGenerator(), e você usa o objeto ProtoFromDataFrames. Você pode passar o quadro de dados em um dicionário. Por exemplo, se quisermos criar uma estatística resumida para o conjunto de trens, podemos armazenar a informação em um dicionário e usá-la no objeto `ProtoFromDataFrames“
-
'name': 'train', 'table': df_train
Nome é o nome da tabela exibida e você usa o nome da tabela que deseja calcular o resumo. No seu exemplo, a tabela que contém os dados é df_train
# Calculate the feature statistics proto from the datasets and stringify it for use in facets overview import base64 gfsg = GenericFeatureStatisticsGenerator() proto = gfsg.ProtoFromDataFrames([{'name': 'train', 'table': df_train}, {'name': 'test', 'table': df_test}]) #proto = gfsg.ProtoFromDataFrames([{'name': 'train', 'table': df_train}]) protostr = base64.b64encode(proto.SerializeToString()).decode("utf-8")
Por último, basta copiar e colar o código abaixo. O código vem diretamente do GitHub. Você deve ser capaz de ver isto:
# Display the facets overview visualization for this data# Displ from IPython.core.display import display, HTML HTML_TEMPLATE = """<link rel="import" href="/pt/nbextensions/facets-dist/facets-jupyter.html" > <facets-overview id="elem"></facets-overview> <script> document.querySelector("#elem").protoInput = "{protostr}"; </script>""" html = HTML_TEMPLATE.format(protostr=protostr) display(HTML(html))
Gráfico
Depois de verificar os dados e sua distribuição, você pode traçar uma matriz de correlação. A matriz de correlação calcula o coeficiente de Pearson. Este coeficiente está ligado entre -1 e 1, sendo que um valor positivo indica uma correlação positiva e um valor negativo uma correlação negativa.
Você está interessado em ver quais variáveis podem ser boas candidatas para termos de interação.
## Choose important feature and further check with Dive %matplotlib inline import matplotlib.pyplot as plt import seaborn as sns sns.set(style="ticks") # Compute the correlation matrix corr = df.corr('pearson') # Generate a mask for the upper triangle mask = np.zeros_like(corr, dtype=np.bool) mask[np.triu_indices_from(mask)] = True # Set up the matplotlib figure f, ax = plt.subplots(figsize=(11, 9)) # Generate a custom diverging colormap cmap = sns.diverging_palette(220, 10, as_cmap=True) # Draw the heatmap with the mask and correct aspect ratio sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,annot=True, square=True, linewidths=.5, cbar_kws={"shrink": .5})
saída
<matplotlib.axes._subplots.AxesSubplot at 0x1a184d6518>
png
Da matriz, você pode ver:
- LSTAT
- RM
Estão fortemente correlacionados com PRICE. Outra característica interessante é a forte correlação positiva entre NOX e INDUS, o que significa que essas duas variáveis se movem na mesma direção. Além disso, também estão correlacionados com o PREÇO. DIS também está altamente correlacionado com IND e NOX.
Você tem uma primeira dica de que IND e NOX podem ser bons candidatos para o termo de interceptação e DIS também pode ser interessante focar.
Você pode ir um pouco mais fundo traçando uma grade de pares. Ilustrará mais detalhadamente o mapa de correlação que você traçou antes.
A grade de pares que somos composta da seguinte forma:
- Parte superior: gráfico de dispersão com linha ajustada
- Diagonal: gráfico de densidade do kernel
- Parte inferior: gráfico de densidade multivariada do kernel
Você escolhe o foco em quatro variáveis independentes. A escolha corresponde às variáveis com forte correlação com PREÇO
- INDUS
- NOX
- RM
- LSTAT
além disso, o PREÇO.
Note que o erro padrão é adicionado por padrão ao gráfico de dispersão.
attributes = ["PRICE", "INDUS", "NOX", "RM", "LSTAT"] g = sns.PairGrid(df[attributes]) g = g.map_upper(sns.regplot, color="g") g = g.map_lower(sns.kdeplot,cmap="Reds", shade=True, shade_lowest=False) g = g.map_diag(sns.kdeplot)
saída
Vamos começar pela parte superior:
- O preço está negativamente correlacionado com INDUS, NOX e LSTAT; correlacionado positivamente com RM.
- Há uma ligeira não linearidade com LSTAT e PRICE
- Existe como uma linha reta quando o preço é igual a 50. A partir da descrição do conjunto de dados, PRICE foi truncado no valor de 50
Diagonal
- NOX parece ter dois clusters, um em torno de 0.5 e outro em torno de 0.85.
Para saber mais sobre isso, você pode dar uma olhada na parte inferior. A Densidade Multivariada do Kernel é interessante no sentido de que colore onde está a maioria dos pontos. A diferença com o gráfico de dispersão desenha uma densidade de probabilidade, mesmo que não haja nenhum ponto no conjunto de dados para uma determinada coordenada. Quando a cor é mais forte, indica uma alta concentração de pontos ao redor desta área.
Se você verificar a densidade multivariada para INDUS e NOX, poderá ver a correlação positiva e os dois clusters. Quando a participação da indústria é superior a 18, a concentração de óxidos nítricos fica acima de 0.6.
Você pode pensar em adicionar uma interação entre INDUS e NOX na relação linear.
Por fim, você pode usar a segunda ferramenta criada pelo Google, Facets Deep Dive. A interface está dividida em quatro seções principais. A área central no centro é uma exibição ampliada dos dados. Na parte superior do painel, há um menu suspenso onde você pode alterar a organização dos dados para controlar facetação, posicionamento e cor. À direita, há uma visão detalhada de uma linha específica de dados. Isso significa que você pode clicar em qualquer ponto de dados na visualização central para ver os detalhes sobre esse ponto de dados específico.
Durante a etapa de visualização dos dados, você está interessado em procurar a correlação de pares entre a variável independente no preço da casa. No entanto, envolve pelo menos três variáveis, e os gráficos 3D são complicados de trabalhar.
Uma maneira de resolver esse problema é criar uma variável categórica. Ou seja, podemos criar um gráfico 2D da cor do ponto. Você pode dividir a variável PREÇO em quatro categorias, sendo cada categoria um quartil (ou seja, 0.25, 0.5, 0.75). Você chama essa nova variável de Q_PRICE.
## Check non linearity with important features df['Q_PRICE'] = pd.qcut(df['PRICE'], 4, labels=["Lowest", "Low", "Upper", "upper_plus"]) ## Show non linearity between RM and LSTAT ax = sns.lmplot(x="DIS", y="INDUS", hue="Q_PRICE", data=df, fit_reg = False,palette="Set3")
Aprofundamento das facetas
Para abrir o Deep Dive, você precisa transformar os dados em um formato json. Pandas como objeto para isso. Você pode usar to_json após o conjunto de dados Pandas.
A primeira linha de código trata do tamanho do conjunto de dados.
df['Q_PRICE'] = pd.qcut(df['PRICE'], 4, labels=["Lowest", "Low", "Upper", "upper_plus"]) sprite_size = 32 if len(df.index)>50000 else 64 jsonstr = df.to_json(orient='records')
O código abaixo vem do Google GitHub. Depois de executar o código, você poderá ver isto:
# Display thde Dive visualization for this data from IPython.core.display import display, HTML # Create Facets template HTML_TEMPLATE = """<link rel="import" href="/pt/nbextensions/facets-dist/facets-jupyter.html"> <facets-dive sprite-image-width="{sprite_size}" sprite-image-height="{sprite_size}" id="elem" height="600"></facets-dive> <script> document.querySelector("#elem").data = {jsonstr}; </script>""" # Load the json dataset and the sprite_size into the template html = HTML_TEMPLATE.format(jsonstr=jsonstr, sprite_size=sprite_size) # Display the template display(HTML(html))
Você está interessado em ver se existe uma conexão entre a taxa da indústria, a concentração de óxidos, a distância até o centro de empregos e o preço da casa.
Para isso, primeiro você divide os dados por faixa e cor do setor com o quartil de preço:
- Selecione facetar X e escolha INDUS.
- Selecione Exibir e escolha DIS. Ele irá colorir os pontos com o quartil do preço da casa
aqui, cores mais escuras significam que a distância até o primeiro centro de empregos é grande.
Até agora, mostra novamente o que você sabe, taxa mais baixa da indústria, preço mais alto. Agora você pode ver a divisão por INDUX, por NOX.
- Selecione facetar Y e escolha NOX.
Agora você pode ver que as casas distantes do primeiro centro de emprego têm a menor participação na indústria e, portanto, a menor concentração de óxidos. Se você optar por exibir o tipo com Q_PRICE e ampliar o canto inferior esquerdo, poderá ver que tipo de preço é.
Você tem outra dica de que a interação entre IND, NOX e DIS pode ser bons candidatos para melhorar o modelo.
TensorFlow
Nesta seção, você estimará o classificador linear com a API de estimadores do TensorFlow. Você procederá da seguinte forma:
- Prepare os dados
- Estimar um modelo de benchmark: sem interação
- Estimar um modelo com interação
Lembre-se de que o objetivo do aprendizado de máquina é minimizar o erro. Nesse caso, vencerá o modelo com o menor erro quadrático médio. O estimador do TensorFlow calcula automaticamente essa métrica.
Dados de preparação
Na maioria dos casos, você precisa transformar seus dados. É por isso que a Visão Geral das Facetas é fascinante. Pela estatística resumida, você viu que há valores discrepantes. Esses valores afetam as estimativas porque não se parecem com a população que você está analisando. Os valores discrepantes geralmente distorcem os resultados. Por exemplo, um valor discrepante positivo tende a superestimar o coeficiente.
Uma boa solução para resolver esse problema é padronizar a variável. Padronização significa um desvio padrão de um e média de zero. O processo de padronização envolve duas etapas. Em primeiro lugar, subtrai o valor médio da variável. Em segundo lugar, divide pelo desvio padrão para que a distribuição tenha um desvio padrão unitário.
A biblioteca sklearn é útil para padronizar variáveis. Você pode usar o pré-processamento do módulo com a escala do objeto para essa finalidade.
Você pode usar a função abaixo para dimensionar um conjunto de dados. Observe que você não dimensiona a coluna do rótulo e as variáveis categóricas.
from sklearn import preprocessing def standardize_data(df): X_scaled = preprocessing.scale(df[['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT']]) X_scaled_df = pd.DataFrame(X_scaled, columns = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT']) df_scale = pd.concat([X_scaled_df, df['CHAS'], df['PRICE']],axis=1, join='inner') return df_scale
Você pode usar a função para construir o conjunto de treinamento/teste dimensionado.
df_train_scale = standardize_data(df_train) df_test_scale = standardize_data(df_test)
Regressão básica:Benchmark
Primeiro de tudo, você treina e testa um modelo sem interação. O objetivo é ver a métrica de desempenho do modelo.
A forma de treinar o modelo é exatamente como no tutorial API de alto nível. Você usará o estimador LinearRegressor do TensorFlow.
Como lembrete, você precisa escolher:
- os recursos para colocar no modelo
- transformar os recursos
- construir o regressor linear
- construir a função input_fn
- treine o modelo
- testar o modelo
Você usa todas as variáveis do conjunto de dados para treinar o modelo. No total, existem variáveis contínuas de nível e uma variável categórica
## Add features to the bucket: ### Define continuous list CONTI_FEATURES = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'] CATE_FEATURES = ['CHAS']
Você converte os recursos em uma coluna numérica ou coluna categórica
continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES] #categorical_features = tf.feature_column.categorical_column_with_hash_bucket(CATE_FEATURES, hash_bucket_size=1000) categorical_features = [tf.feature_column.categorical_column_with_vocabulary_list('CHAS', ['yes','no'])]
Você cria o modelo com o linearRegressor. Você armazena o modelo na pasta train_Boston
model = tf.estimator.LinearRegressor( model_dir="train_Boston", feature_columns=categorical_features + continuous_features)
saída
INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'train_Boston', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a19e76ac8>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
Cada coluna nos dados de treinamento ou teste é convertida em um Tensor com a função get_input_fn
FEATURES = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS'] LABEL= 'PRICE' def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k: data_set[k].values for k in FEATURES}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle)
Você estima o modelo nos dados do trem.
model.train(input_fn=get_input_fn(df_train_scale, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)
saída
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Saving checkpoints for 1 into train_Boston/model.ckpt. INFO:tensorflow:loss = 56417.703, step = 1 INFO:tensorflow:global_step/sec: 144.457 INFO:tensorflow:loss = 76982.734, step = 101 (0.697 sec) INFO:tensorflow:global_step/sec: 258.392 INFO:tensorflow:loss = 21246.334, step = 201 (0.383 sec) INFO:tensorflow:global_step/sec: 227.998 INFO:tensorflow:loss = 30534.78, step = 301 (0.439 sec) INFO:tensorflow:global_step/sec: 210.739 INFO:tensorflow:loss = 36794.5, step = 401 (0.477 sec) INFO:tensorflow:global_step/sec: 234.237 INFO:tensorflow:loss = 8562.981, step = 501 (0.425 sec) INFO:tensorflow:global_step/sec: 238.1 INFO:tensorflow:loss = 34465.08, step = 601 (0.420 sec) INFO:tensorflow:global_step/sec: 237.934 INFO:tensorflow:loss = 12241.709, step = 701 (0.420 sec) INFO:tensorflow:global_step/sec: 220.687 INFO:tensorflow:loss = 11019.228, step = 801 (0.453 sec) INFO:tensorflow:global_step/sec: 232.702 INFO:tensorflow:loss = 24049.678, step = 901 (0.432 sec) INFO:tensorflow:Saving checkpoints for 1000 into train_Boston/model.ckpt. INFO:tensorflow:Loss for final step: 23228.568. <tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a19e76320>
Por fim, você estima o desempenho do modelo no conjunto de testes
model.evaluate(input_fn=get_input_fn(df_test_scale, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)
saída
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-05-29-02:40:43 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train_Boston/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Finished evaluation at 2018-05-29-02:40:43 INFO:tensorflow:Saving dict for global step 1000: average_loss = 86.89361, global_step = 1000, loss = 1650.9785 {'average_loss': 86.89361, 'global_step': 1000, 'loss': 1650.9785}
A perda do modelo é 1650. Esta é a métrica a ser superada na próxima seção
Melhorar o modelo: termo de interação
Durante a primeira parte do tutorial, você viu uma relação interessante entre as variáveis. As diferentes técnicas de visualização revelaram que INDUS e NOS estão interligadas e voltam a ampliar o efeito no preço. Não só a interação entre INDUS e NOS afeta o preço, mas também este efeito é mais forte quando interage com DIS.
É hora de generalizar essa ideia e ver se você pode melhorar o modelo previsto.
Você precisa adicionar duas novas colunas a cada conjunto de dados: treinar + testar. Para isso, você cria uma função para calcular o termo de interação e outra para calcular o termo de interação tripla. Cada função produz uma única coluna. Depois que as novas variáveis forem criadas, você poderá concatená-las ao conjunto de dados de treinamento e ao conjunto de dados de teste.
Primeiro de tudo, é necessário criar uma nova variável para a interação entre INDUS e NOX.
A função abaixo retorna dois dataframes, train e test, com a interação entre var_1 e var_2, no seu caso INDUS e NOX.
def interaction_term(var_1, var_2, name): t_train = df_train_scale[var_1]*df_train_scale[var_2] train = t_train.rename(name) t_test = df_test_scale[var_1]*df_test_scale[var_2] test = t_test.rename(name) return train, test
Você armazena as duas novas colunas
interation_ind_ns_train, interation_ind_ns_test= interaction_term('INDUS', 'NOX', 'INDUS_NOS') interation_ind_ns_train.shape (325,)
Em segundo lugar, você cria uma segunda função para calcular o termo de interação tripla.
def triple_interaction_term(var_1, var_2,var_3, name): t_train = df_train_scale[var_1]*df_train_scale[var_2]*df_train_scale[var_3] train = t_train.rename(name) t_test = df_test_scale[var_1]*df_test_scale[var_2]*df_test_scale[var_3] test = t_test.rename(name) return train, test interation_ind_ns_dis_train, interation_ind_ns_dis_test= triple_interaction_term('INDUS', 'NOX', 'DIS','INDUS_NOS_DIS')
Agora que você tem todas as colunas necessárias, pode adicioná-las ao conjunto de dados de treinamento e teste. Você nomeia esses dois novos dataframes:
- df_train_new
- df_test_new
df_train_new = pd.concat([df_train_scale, interation_ind_ns_train, interation_ind_ns_dis_train], axis=1, join='inner') df_test_new = pd.concat([df_test_scale, interation_ind_ns_test, interation_ind_ns_dis_test], axis=1, join='inner') df_train_new.head(5)
saída
É isso; você pode estimar o novo modelo com os termos de interação e ver como está a métrica de desempenho.
CONTI_FEATURES_NEW = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT', 'INDUS_NOS', 'INDUS_NOS_DIS'] ### Define categorical list continuous_features_new = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES_NEW] model = tf.estimator.LinearRegressor( model_dir="train_Boston_1", feature_columns= categorical_features + continuous_features_new)
saída
INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'train_Boston_1', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a1a5d5860>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
CÓDIGO
FEATURES = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT','INDUS_NOS', 'INDUS_NOS_DIS','CHAS'] LABEL= 'PRICE' def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k: data_set[k].values for k in FEATURES}), y = pd.Series(data_set[LABEL].values), batch_size=n_batch, num_epochs=num_epochs, shuffle=shuffle)
model.train(input_fn=get_input_fn(df_train_new, num_epochs=None, n_batch = 128, shuffle=False), steps=1000)
saída
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Saving checkpoints for 1 into train_Boston_1/model.ckpt. INFO:tensorflow:loss = 56417.703, step = 1 INFO:tensorflow:global_step/sec: 124.844 INFO:tensorflow:loss = 65522.3, step = 101 (0.803 sec) INFO:tensorflow:global_step/sec: 182.704 INFO:tensorflow:loss = 15384.148, step = 201 (0.549 sec) INFO:tensorflow:global_step/sec: 208.189 INFO:tensorflow:loss = 22020.305, step = 301 (0.482 sec) INFO:tensorflow:global_step/sec: 213.855 INFO:tensorflow:loss = 28208.812, step = 401 (0.468 sec) INFO:tensorflow:global_step/sec: 209.758 INFO:tensorflow:loss = 7606.877, step = 501 (0.473 sec) INFO:tensorflow:global_step/sec: 196.618 INFO:tensorflow:loss = 26679.76, step = 601 (0.514 sec) INFO:tensorflow:global_step/sec: 196.472 INFO:tensorflow:loss = 11377.163, step = 701 (0.504 sec) INFO:tensorflow:global_step/sec: 172.82 INFO:tensorflow:loss = 8592.07, step = 801 (0.578 sec) INFO:tensorflow:global_step/sec: 168.916 INFO:tensorflow:loss = 19878.56, step = 901 (0.592 sec) INFO:tensorflow:Saving checkpoints for 1000 into train_Boston_1/model.ckpt. INFO:tensorflow:Loss for final step: 19598.387. <tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a1a5d5e10>
model.evaluate(input_fn=get_input_fn(df_test_new, num_epochs=1, n_batch = 128, shuffle=False), steps=1000)
saída
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-05-29-02:41:14 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train_Boston_1/model.ckpt-1000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Finished evaluation at 2018-05-29-02:41:14 INFO:tensorflow:Saving dict for global step 1000: average_loss = 79.78876, global_step = 1000, loss = 1515.9863 {'average_loss': 79.78876, 'global_step': 1000, 'loss': 1515.9863}
A nova perda é 1515. Apenas adicionando duas novas variáveis, você conseguiu diminuir a perda. Isso significa que você pode fazer uma previsão melhor do que com o modelo de benchmark.