Tutorial de regressão linear com TensorFlow [exemplos]

⚡ Resumo Inteligente

A regressão linear no TensorFlow modela a relação entre características numéricas e um valor alvo contínuo. Este tutorial treina um preditor de preços de imóveis em Boston de três maneiras diferentes, usando Pandas, NumPy e os pipelines de entrada nativos do TensorFlow com o estimador LinearRegressor.

  • 🔘 Formulário do modelo: Uma regressão linear ajusta-se a y = bias + weight × x, sendo estendida com mais covariáveis ​​para problemas multivariados.
  • ☑️ Ciclo de treinamento: O método do gradiente descendente ajusta os pesos a cada iteração até que o Erro Quadrático Médio pare de diminuir.
  • API do Estimador: O LinearRegressor precisa apenas de colunas de recursos, um diretório de modelos e uma função de entrada.
  • 🧪 Três oleodutos: Os conjuntos de dados Pandas, NumPy e TensorFlow nativo alimentam o mesmo modelo e retornam previsões idênticas.
  • 🛠️ Exemplo resolvido: Nove características de Boston preveem o valor mediano das casas e atingem uma perda de teste de 3215.
  • ⚠️ Versão da realidade: Os estimadores foram descontinuados no TensorFlow 2.12 e removidos na versão 2.16, portanto, novos trabalhos devem ser migrados para o Keras.

Regressão Linear com TensorFlow

O que é regressão linear?

Regressão linear A regressão linear é uma abordagem estatística para modelar relações entre duas variáveis. Essa modelagem é feita entre uma resposta escalar e uma ou mais variáveis ​​explicativas. A relação com uma única variável explicativa é chamada de regressão linear simples, e com mais de uma variável explicativa é chamada de regressão linear múltipla.

O TensorFlow fornece ferramentas para ter controle total dos cálculos. Isso é feito com a API de baixo nível. Além disso, o TensorFlow está equipado com uma vasta gama de APIs para realizar muitas aprendizado de máquina algoritmos. Esta é a API de alto nível, e o TensorFlow os chama de estimadores.

  • API de baixo nívelConstruir a arquitetura e a otimização do modelo do zero é algo complicado para um iniciante.
  • API de alto nívelDefina o algoritmo. É fácil de usar. O TensorFlow fornece um conjunto de ferramentas chamado estimador para construir, treinar, avaliar e fazer uma previsão.

Neste tutorial, você usará o estimadores apenasOs cálculos são mais rápidos e fáceis de implementar. A primeira parte explica como usar o otimizador de descida de gradiente para treinar uma regressão linear no TensorFlow. Na segunda parte, você usará o conjunto de dados de Boston para prever o preço de uma casa usando um estimador do TensorFlow.

Baixe o conjunto de dados de Boston

Como treinar um modelo de regressão linear

Antes de começarmos a treinar o modelo, vamos dar uma olhada no que é, de fato, uma regressão linear.

Imagine que você tem duas variáveis, x e y, e sua tarefa é prever o valor de y sabendo o valor de x. Se você plotar os dados, poderá ver uma relação positiva entre sua variável independente, x, e sua variável dependente, y, como mostra o gráfico de dispersão abaixo.

Gráfico de dispersão de x em função de y mostrando uma relação linear positiva.

Você pode observar que se x=1, y será aproximadamente igual a 6, e se x=2, y será em torno de 8.5.

Este método não é muito preciso e está sujeito a erros, especialmente com um conjunto de dados que contém centenas de milhares de pontos.

Uma regressão linear é avaliada com uma equação. A variável y é explicada por uma ou mais covariáveis. No seu exemplo, há apenas uma variável dependente. Se você tiver que escrever esta equação, será:

Equação de regressão linear simples com um viés, um peso e um termo de erro.

Com:

  • Símbolo do coeficiente de viés é o viés. Ou seja, se x=0, y=Valor do coeficiente de viés quando x é igual a zero
  • Símbolo do coeficiente de ponderação associado a x é o peso associado a x
  • Símbolo do termo de erro residual é o resíduo, ou o erro do modelo. Inclui o que o modelo não consegue aprender com os dados.

Imagine que você ajusta o modelo e encontra a seguinte solução para:

  • Coeficiente de viés ajustado igual a 3.8 = 3.8
  • Coeficiente de ponderação ajustado igual a 2.78 = 2.78

Você pode substituir esses números na equação e ela se tornará:

y = 3.8 + 2.78x

Agora você tem uma maneira melhor de encontrar os valores de y. Ou seja, você pode substituir x por qualquer valor que desejar para prever y. Na imagem abaixo, substituímos x na equação por todos os valores do conjunto de dados e plotamos o resultado.

Linha de regressão ajustada, desenhada em vermelho, passando pelos pontos de dados plotados.

A linha vermelha representa o valor ajustado, ou seja, os valores de y para cada valor de x. Você não precisa ver o valor de x para prever y; para cada x existe um valor correspondente à linha vermelha. Você também pode fazer previsões para valores de x maiores que 2.

Se você quiser estender a regressão linear para mais covariáveis, pode fazê-lo adicionando mais variáveis ​​ao modelo. A diferença entre a análise tradicional e a regressão linear é que a regressão linear analisa como y reagirá a cada variável x considerada independentemente.

Vejamos um exemplo. Imagine que você queira prever as vendas de uma sorveteria. O conjunto de dados contém diversas informações, como o clima (chuvoso, ensolarado, nublado) e informações sobre os clientes (salário, sexo, estado civil).

A análise tradicional tenta prever a venda, por exemplo, calculando a média de cada variável e tentando estimar a venda para diferentes cenários. Isso leva a previsões imprecisas e restringe a análise ao cenário escolhido.

Se você usar regressão linear, poderá escrever esta equação:

Equação de regressão linear múltipla combinando diversas covariáveis ​​ponderadas

O algoritmo encontrará a melhor solução para os pesos; isso significa que ele tentará minimizar o custo, que é a diferença entre a linha ajustada e os pontos de dados.

Como o algoritmo funciona

O diagrama abaixo resume o ciclo que o algoritmo repete: escolher os pesos, prever y, medir o erro e corrigir os pesos.

Fluxograma do ciclo de treinamento de regressão linear, desde pesos aleatórios até erros minimizados.

O algoritmo escolherá um número aleatório para cada Coeficiente de viés inicializado aleatoriamente e Coeficiente de peso inicializado aleatoriamente e substitua o valor de x para obter o valor previsto de y. Se o conjunto de dados tiver 100 observações, o algoritmo calcula 100 valores previstos.

Podemos calcular o erro, notado Termo de erro do modelo usado no cálculo da perda, do modelo, que é a diferença entre o valor previsto e o valor real. Um erro positivo significa que o modelo subestima a previsão de y, e um erro negativo significa que o modelo superestima a previsão de y.

Objetivo de minimização do erro quadrático escrito em notação matemática.

Seu objetivo é minimizar o quadrado do erro. O algoritmo calcula a média do quadrado do erro. Esta etapa é chamada de minimização do erro. Para regressão linear, esta é a Erro quadrado médio, também chamado de MSE. Matematicamente, é:

Fórmula do Erro Quadrático Médio escrita em notação matricial

Onde:

  • Símbolo do vetor de peso usado na fórmula do MSE são os pesos, então Notação de valor previsto usada na fórmula do MSE refere-se ao valor previsto
  • y são os valores reais
  • m é o número de observações.

Observe que Notação de matriz de peso transposta significa que usa a transposta das matrizes. O Notação de somatório e média usada na fórmula do MSE é a notação matemática da média.

O objetivo é encontrar o melhor Símbolo de peso ideal que minimiza o erro quadrático médio (MSE). que minimiza o MSE.

Se o erro médio for grande, significa que o modelo tem um desempenho ruim e os pesos não foram escolhidos corretamente. Para corrigir os pesos, é necessário usar um otimizador. O otimizador tradicional é chamado Gradiente descendente.

O método do gradiente descendente calcula a derivada e diminui ou aumenta o peso. Se a derivada for positiva, o peso é diminuído. Se a derivada for negativa, o peso é aumentado. O modelo atualiza os pesos e recalcula o erro. Esse processo se repete até que o erro não mude mais. Cada iteração é chamada de passagem. iteraçãoAlém disso, os gradientes são multiplicados por uma taxa de aprendizagem, que indica a velocidade do aprendizado.

Se a taxa de aprendizado for muito baixa, o algoritmo levará muito tempo para convergir, pois exigirá muito mais iterações. Se a taxa de aprendizado for muito alta, o algoritmo poderá nunca convergir. A curva de perda abaixo representa o erro em função do número de iterações para este conjunto de dados.

Curva de perda mostrando o erro diminuindo e estabilizando após cerca de vinte iterações.

Como pode ser visto na imagem acima, o modelo repete o processo cerca de 20 vezes antes de encontrar um valor estável para os pesos, atingindo assim o menor erro.

Note que o erro não é igual a zero, mas se estabiliza em torno de 5. Isso significa que o modelo apresenta um erro típico de 5. Se você deseja reduzir o erro, precisa adicionar mais informações ao modelo, como mais variáveis, ou usar estimadores diferentes.

Você se lembra da primeira equação:

Equação final de regressão linear ajustada com os pesos resolvidos

Os pesos finais são 3.8 e 2.78. O vídeo abaixo mostra como o método do gradiente descendente otimiza a função de perda para encontrar esses pesos.

Como treinar uma regressão linear com TensorFlow

Agora que você entende melhor o que está acontecendo nos bastidores, está pronto para usar a API do estimador fornecida pelo TensorFlow para treinar sua primeira regressão linear usando o TensorFlow.

Nota de versão: O fluxo de trabalho do estimador mostrado abaixo foi escrito para o TensorFlow 1.x e as primeiras versões do 2.x. O TensorFlow marcou o tf.estimator e tf.feature_column As APIs foram totalmente descontinuadas na versão 2.12 e os Estimadores foram removidos na versão 2.16. Em uma instalação atual, execute este código dentro de um TensorFlow 1.15 ou 2.x-with-tf.compat.v1 ambiente, ou portá-lo para Keras, onde tf.keras.layers.Dense(1) Além disso, as camadas de pré-processamento substituem o LinearRegressor e as colunas de características. Os conceitos — características, rótulos, lotes, épocas, MSE e descida de gradiente — permanecem inalterados.

Você utilizará o conjunto de dados Boston, que inclui as seguintes variáveis.

Variável Descrição
criminoso taxa de criminalidade per capita por cidade
zn proporção de terrenos residenciais zoneados para lotes com mais de 25,000 pés quadrados.
indus proporção de hectares comerciais não varejistas por cidade.
nox concentração de óxidos nítricos
rm número médio de quartos por habitação
idade 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 proporção aluno-professor por cidade
medv Valor médio das casas ocupadas pelos proprietários em milhares de dólares

Você criará três conjuntos de dados diferentes:

conjunto de dados objetivo forma
Formação Treine o modelo e obtenha os pesos 400, 10
Avaliação Avalie o desempenho do modelo em dados não vistos 100, 10
Prever Use o modelo para prever o valor da casa com base em novos dados 6, 10

O objetivo é utilizar as características do conjunto de dados para prever o valor da casa.

Na segunda parte do tutorial, você aprenderá como usar o TensorFlow com três maneiras diferentes de importar os dados:

  • Com pandas
  • Com NumPy
  • Somente TensorFlow

Note que todas as três opções produzem os mesmos resultados.

Você aprenderá como usar a API de alto nível para construir, treinar e avaliar um modelo de regressão linear do TensorFlow. Se você estivesse usando a API de baixo nível, teria que definir manualmente:

  • Função de perda
  • Otimizador: descida de gradiente
  • Multiplicação da matriz
  • Gráfico e tensor

Isso é tedioso e mais complicado para um iniciante.

Solução Pandas

Você precisa importar as bibliotecas necessárias para treinar o modelo.

import pandas as pd
from sklearn import datasets
import tensorflow as tf
import itertools

Passo 1) Importe os dados com Pandas.

Você define os nomes das colunas e os armazena em COLUMNS. Você pode usar pd.read_csv() para importar os dados.

COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age",
           "dis", "tax", "ptratio", "medv"]

Direcione cada chamada para os arquivos CSV que você baixou anteriormente.

training_set = pd.read_csv("E:/boston_train.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)
test_set = pd.read_csv("E:/boston_test.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)
prediction_set = pd.read_csv("E:/boston_predict.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)

Você pode imprimir a forma dos dados.

print(training_set.shape, test_set.shape, prediction_set.shape)

saída

(400, 10) (100, 10) (6, 10)

Observe que o rótulo, ou seja, o seu valor de y, está incluído no conjunto de dados. Portanto, você precisa definir duas outras listas: uma contendo apenas as características e outra apenas com o nome do rótulo. Essas duas listas informarão ao seu estimador quais são as características no conjunto de dados e qual nome de coluna corresponde ao rótulo.

Isso é feito com o código abaixo.

FEATURES = ["crim", "zn", "indus", "nox", "rm",
                 "age", "dis", "tax", "ptratio"]
LABEL = "medv"

Passo 2) Converta os dados

Você precisa converter as variáveis ​​numéricas para o formato adequado. O TensorFlow fornece um método para converter uma variável contínua: tf.feature_column.numeric_column().

Na etapa anterior, você definiu uma lista de recursos que deseja incluir no modelo. Agora você pode usar essa lista para convertê-los em dados numéricos. Se quiser excluir recursos do seu modelo, fique à vontade para remover uma ou mais variáveis ​​da lista FEATURES antes de construir feature_cols.

Observe que você usará um Python A compreensão de lista com a lista FEATURES cria uma nova lista chamada feature_cols. Isso evita escrever tf.feature_column.numeric_column() nove vezes. A compreensão de lista é uma maneira mais rápida e limpa de criar novas listas.

feature_cols = [tf.feature_column.numeric_column(k) for k in FEATURES]

Passo 3) Defina o estimador

Nesta etapa, você precisa definir o estimador. O TensorFlow fornece seis estimadores predefinidos, três para tarefas de classificação e três para tarefas de regressão do TensorFlow:

  • Regressor
    • DNSRegressor
    • Regressor Linear
    • Regressor Combinado Linear DNN
  • classificar
    • Classificador DNN
    • Classificador Linear
    • Classificador Combinado Linear DNN

Neste tutorial, você usará o Regressor Linear. Para acessar esta função, você precisa usar tf.estimator.

A função precisa de dois argumentos:

  • feature_columns: contém as variáveis ​​a serem incluídas no modelo
  • model_dir: caminho para armazenar o grafo, salvar os parâmetros do modelo e assim por diante.

O TensorFlow criará automaticamente uma pasta chamada `train` em seu diretório de trabalho. Você precisa usar esse caminho para acessar os arquivos de configuração. TensorBoard, conforme mostrado no exemplo de regressão do TensorFlow abaixo.

estimator = tf.estimator.LinearRegressor(
        feature_columns=feature_cols,
        model_dir="train")

saída

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train', '_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 0x1a215dc550>, '_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}

A parte complicada do TensorFlow é a forma de alimentar o modelo. O TensorFlow foi projetado para funcionar com computação paralela e conjuntos de dados muito grandes. Devido à limitação dos recursos da máquina, é impossível alimentar o modelo com todos os dados de uma só vez. Para isso, é necessário alimentar o modelo com um lote de dados a cada vez. Observe que estamos falando de conjuntos de dados enormes, com milhões ou mais registros. Se você não adicionar um lote, acabará com um erro de memória.

Por exemplo, se seus dados contiverem 100 observações e você definir um tamanho de lote de 10, isso significa que o modelo verá 10 observações para cada iteração (10*10).

Quando o modelo tiver processado todos os dados, ele completa uma época. Uma época define quantas vezes você quer que o modelo processe os dados. É melhor definir esse valor como "nenhum" e deixar o modelo realizar um número predefinido de iterações.

Uma segunda informação importante a adicionar é se você deseja embaralhar os dados antes de cada iteração. Durante o treinamento, é crucial embaralhar os dados para que o modelo não aprenda um padrão específico do conjunto de dados. Se o modelo aprender os detalhes do padrão subjacente dos dados, terá dificuldade em generalizar a previsão para dados não vistos. Isso é chamado de sobreajuste (overfitting). O modelo tem um bom desempenho nos dados de treinamento, mas não consegue prever corretamente para dados não vistos.

O TensorFlow facilita a execução dessas duas etapas. Quando os dados chegam ao pipeline, ele sabe quantas observações precisa (lote) e se precisa embaralhar os dados.

Para instruir o TensorFlow sobre como alimentar o modelo, você pode usar a função `pandas_input_fn`. Este objeto precisa de cinco parâmetros:

  • x: dados do recurso
  • y: dados do rótulo
  • tamanho_do_lote: lote. Por padrão 128
  • num_epoch: número de épocas, por padrão 1
  • Embaralhar: embaralhar ou não os dados. Por padrão, Nenhum.

Você precisa alimentar o modelo várias vezes, então define uma função para repetir esse processo. Chame essa função de get_input_fn.

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)

O método usual para avaliar o desempenho de um modelo é:

  • Treine o modelo
  • Avalie o modelo em um conjunto de dados diferente.
  • Fazer uma previsão

O estimador do TensorFlow fornece três funções diferentes para realizar essas três etapas com facilidade.

Passo 4) Treine o modelo

Você pode usar o método `train` do estimador para ajustar o modelo. O estimador `train` precisa de uma função `input_fn` e um número de passos. Você pode usar a função que criou anteriormente para alimentar o modelo. Em seguida, instrua o modelo a iterar 1000 vezes. Observe que você não especifica o número de épocas; deixe o modelo iterar 1000 vezes. Se você definir o número de épocas como 1, o modelo iterará quatro vezes, porque há 400 registros no conjunto de treinamento e o tamanho do lote é 128.

  1. 128 camadas
  2. 128 camadas
  3. 128 camadas
  4. 16 camadas

Portanto, é mais fácil definir o número de épocas como nenhum e definir o número de iterações, como mostrado no exemplo de classificação do TensorFlow abaixo.

estimator.train(input_fn=get_input_fn(training_set,
                                           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/model.ckpt.
INFO:tensorflow:loss = 83729.64, step = 1
INFO:tensorflow:global_step/sec: 238.616
INFO:tensorflow:loss = 13909.657, step = 101 (0.420 sec)
INFO:tensorflow:global_step/sec: 314.293
INFO:tensorflow:loss = 12881.449, step = 201 (0.320 sec)
INFO:tensorflow:global_step/sec: 303.863
INFO:tensorflow:loss = 12391.541, step = 301 (0.327 sec)
INFO:tensorflow:global_step/sec: 308.782
INFO:tensorflow:loss = 12050.5625, step = 401 (0.326 sec)
INFO:tensorflow:global_step/sec: 244.969
INFO:tensorflow:loss = 11766.134, step = 501 (0.407 sec)
INFO:tensorflow:global_step/sec: 155.966
INFO:tensorflow:loss = 11509.922, step = 601 (0.641 sec)
INFO:tensorflow:global_step/sec: 263.256
INFO:tensorflow:loss = 11272.889, step = 701 (0.379 sec)
INFO:tensorflow:global_step/sec: 254.112
INFO:tensorflow:loss = 11051.9795, step = 801 (0.396 sec)
INFO:tensorflow:global_step/sec: 292.405
INFO:tensorflow:loss = 10845.855, step = 901 (0.341 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train/model.ckpt.
INFO:tensorflow:Loss for final step: 5925.9873.

Você pode verificar o TensorBoard com o seguinte comando:

activate hello-tf
# For MacOS
tensorboard --logdir=./train
# For Windows
tensorboard --logdir=train

Passo 5) Avalie seu modelo

Você pode avaliar o ajuste do seu modelo no conjunto de teste com o código abaixo:

ev = estimator.evaluate(
          input_fn=get_input_fn(test_set,
          num_epochs=1,
          n_batch = 128,
          shuffle=False))

saída

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-13-01:43:13
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-13-01:43:13
INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.15896, global_step = 1000, loss = 3215.896

Você pode imprimir a perda com o código abaixo:

loss_score = ev["loss"]
print("Loss: {0:f}".format(loss_score))

saída

Loss: 3215.895996

O modelo apresenta uma perda de 3215. Você pode consultar as estatísticas resumidas para ter uma ideia da magnitude do erro.

training_set['medv'].describe()

saída

count    400.000000
mean      22.625500
std        9.572593
min        5.000000
25%       16.600000
50%       21.400000
75%       25.025000
max       50.000000
Name: medv, dtype: float64

A partir das estatísticas resumidas acima, você sabe que o preço médio de uma casa é de 22 mil, com um preço mínimo de 5 mil e um máximo de 50 mil. Como a perda relatada é o erro quadrático médio, o erro típico nas unidades originais é aproximadamente a raiz quadrada de 32.16, o que equivale a cerca de 5.7 mil dólares.

Passo 6) Faça a previsão

Por fim, você pode usar o método `predict` do TensorFlow para estimar o valor de seis casas em Boston.

y = estimator.predict(
         input_fn=get_input_fn(prediction_set,
         num_epochs=1,
         n_batch = 128,
         shuffle=False))

Para imprimir os valores estimados, você pode usar este código:

predictions = list(p["predictions"] for p in itertools.islice(y, 6))
print("Predictions: {}".format(str(predictions)))

saída

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Predictions: [array([32.297546], dtype=float32), array([18.96125], dtype=float32), array([27.270979], dtype=float32), array([29.299236], dtype=float32), array([16.436684], dtype=float32), array([21.460876], dtype=float32)]

O modelo prevê os seguintes valores:

Casa Predição
1 32.29
2 18.96
3 27.27
4 29.29
5 16.43
6 21.46

Note que não conhecemos o valor real dessas seis casas. No tutorial de aprendizado profundo, você tentará superar o modelo linear.

Solução NumPy

Esta seção explica como treinar o modelo usando um estimador NumPy para alimentar os dados. O método é o mesmo, exceto que você usará o estimador numpy_input_fn.

Leia os mesmos três arquivos CSV, mas mantenha apenas os arrays NumPy brutos com o prefixo .values.

training_set_n = pd.read_csv("E:/boston_train.csv").values
test_set_n = pd.read_csv("E:/boston_test.csv").values
prediction_set_n = pd.read_csv("E:/boston_predict.csv").values

Passo 1) Importar os dados

Primeiramente, você precisa diferenciar as variáveis ​​de atributos dos rótulos. Isso deve ser feito tanto para os dados de treinamento quanto para os dados de avaliação. É mais rápido definir uma função para dividir os dados.

def prepare_data(df):
        X_train = df[:, :-3]
        y_train = df[:,-3]
        return X_train, y_train

Você pode usar a função para separar o rótulo das características dos conjuntos de dados de treinamento e avaliação.

X_train, y_train = prepare_data(training_set_n)
X_test, y_test = prepare_data(test_set_n)

Você precisa excluir a última coluna do conjunto de dados de previsão porque ela contém apenas valores NaN.

x_predict = prediction_set_n[:, :-2]

Confirme o formato da matriz. Observe que o rótulo não deve ter uma segunda dimensão, ou seja, (400,).

print(X_train.shape, y_train.shape, x_predict.shape)

saída

(400, 9) (400,) (6, 9)

Você pode construir as colunas de recursos da seguinte forma:

feature_columns = [      tf.feature_column.numeric_column('x', shape=X_train.shape[1:])]

O estimador é definido como antes: você especifica as colunas de recursos e onde salvar o gráfico.

estimator = tf.estimator.LinearRegressor(
         feature_columns=feature_columns,
         model_dir="train1")

saída

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train1', '_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 0x1a218d8f28>, '_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}

Você pode usar o estimador NumPy para alimentar o modelo com os dados e, em seguida, treiná-lo. Observe que definimos a função `input_fn` previamente para facilitar a leitura.

# Train the estimator
train_input = tf.estimator.inputs.numpy_input_fn(
           x={"x": X_train},
           y=y_train,
           batch_size=128,
           shuffle=False,
           num_epochs=None)
estimator.train(input_fn = train_input,steps=5000)

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 train1/model.ckpt.
INFO:tensorflow:loss = 83729.64, step = 1
INFO:tensorflow:global_step/sec: 490.057
INFO:tensorflow:loss = 13909.656, step = 101 (0.206 sec)
INFO:tensorflow:global_step/sec: 788.986
INFO:tensorflow:loss = 12881.45, step = 201 (0.126 sec)
INFO:tensorflow:global_step/sec: 736.339
INFO:tensorflow:loss = 12391.541, step = 301 (0.136 sec)
INFO:tensorflow:global_step/sec: 383.305
INFO:tensorflow:loss = 12050.561, step = 401 (0.260 sec)
INFO:tensorflow:global_step/sec: 859.832
INFO:tensorflow:loss = 11766.133, step = 501 (0.117 sec)
INFO:tensorflow:global_step/sec: 804.394
INFO:tensorflow:loss = 11509.918, step = 601 (0.125 sec)
INFO:tensorflow:global_step/sec: 753.059
INFO:tensorflow:loss = 11272.891, step = 701 (0.134 sec)
INFO:tensorflow:global_step/sec: 402.165
INFO:tensorflow:loss = 11051.979, step = 801 (0.248 sec)
INFO:tensorflow:global_step/sec: 344.022
INFO:tensorflow:loss = 10845.854, step = 901 (0.288 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train1/model.ckpt.
INFO:tensorflow:Loss for final step: 5925.985.
Out[23]:
<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a1b6ea860>

Você repete o mesmo passo com uma função de entrada diferente para avaliar seu modelo.

eval_input = tf.estimator.inputs.numpy_input_fn(
       x={"x": X_test},
       y=y_test,
       shuffle=False,
       batch_size=128,
       num_epochs=1)
   estimator.evaluate(eval_input,steps=None)

saída

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-13-01:44:00
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-13-01:44:00
INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.158947, global_step = 1000, loss = 3215.8945
Out[24]:
{'average_loss': 32.158947, 'global_step': 1000, 'loss': 3215.8945}

Por fim, você pode calcular a previsão. Ela deve ser semelhante ao resultado do Pandas.

test_input = tf.estimator.inputs.numpy_input_fn(
        x={"x": x_predict},
        batch_size=128,
        num_epochs=1,
        shuffle=False)
        y = estimator.predict(test_input)

predictions = list(p["predictions"] for p in itertools.islice(y, 6))
print("Predictions: {}".format(str(predictions)))

saída

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Predictions: [array([32.297546], dtype=float32), array([18.961248], dtype=float32), array([27.270979], dtype=float32), array([29.299242], dtype=float32), array([16.43668], dtype=float32), array([21.460878], dtype=float32)]

Solução TensorFlow

A última seção é dedicada a um puro TensorFlow solução. Este método é um pouco mais complicado que os outros dois.

Observe que se você usar um Jupyter cadernoPara executar esta sessão, você precisa reiniciar e limpar o kernel.

O TensorFlow criou uma ótima ferramenta para passar os dados para o pipeline. Nesta seção, você criará a função `input_fn` por conta própria.

Passo 1) Defina o caminho e o formato dos dados

Primeiramente, você declara duas variáveis ​​com o caminho dos arquivos CSV. Observe que você tem dois arquivos, um para o conjunto de treinamento e outro para o conjunto de teste.

import tensorflow as tf
df_train = "E:/boston_train.csv"
df_eval = "E:/boston_test.csv"

Em seguida, você precisa definir as colunas que deseja usar do arquivo CSV. Usaremos todas elas. Depois disso, você precisa declarar o tipo de cada variável.

Variáveis ​​de ponto flutuante são definidas por [0.]

COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age",
                "dis", "tax", "ptratio", "medv"]
RECORDS_ALL = [[0.0], [0.0], [0.0], [0.0],[0.0],[0.0],[0.0],[0.0],[0.0],[0.0]]

Passo 2) Defina a função input_fn

A função pode ser dividida em três partes:

  1. Importar os dados
  2. Crie o iterador
  3. Consumir os dados

Abaixo está o código geral para definir a função. O código será explicado posteriormente.

def input_fn(data_file, batch_size, num_epoch = None):
       # Step 1
          def parse_csv(value):
          columns = tf.decode_csv(value, record_defaults= RECORDS_ALL)
          features = dict(zip(COLUMNS, columns))
          #labels = features.pop('median_house_value')
          labels =  features.pop('medv')
          return features, labels

          # Extract lines from input files using the Dataset API.
          dataset = (tf.data.TextLineDataset(data_file) # Read text file
          .skip(1) # Skip header row
          .map(parse_csv))

          dataset = dataset.repeat(num_epoch)
          dataset = dataset.batch(batch_size)
          # Step 3
          iterator = dataset.make_one_shot_iterator()
          features, labels = iterator.get_next()
          return features, labels

Importar os dados

Para um arquivo CSV, o método `dataset` lê uma linha por vez. Para construir o conjunto de dados, você precisa usar o objeto. TextLineConjunto de dados. Seu conjunto de dados possui um cabeçalho, então você precisa usar skip(1) para pular a primeira linha. Neste ponto, você apenas lê os dados e exclui o cabeçalho no pipeline. Para alimentar o modelo, você precisa separar os recursos dos rótulos. O método usado para aplicar qualquer transformação aos dados é map.

Este método chama uma função que você criará para instruir como transformar os dados. Em resumo, você precisa passar os dados para a função. TextLineObjeto de conjunto de dados, excluir o cabeçalho e aplicar uma transformação conforme instruído por uma função.

Code explicação

  • tf.dados.TextLineDataset(data_file): esta linha lê o arquivo CSV
  • .skip(1): ignora o cabeçalho
  • .map(parse_csv)): analisa os registros e os transforma em tensores

Você precisa definir uma função para instruir o objeto de mapa. Você pode chamar essa função de parse_csv.

Esta função analisa o arquivo CSV com o método `tf.decode_csv` e declara as características e o rótulo. As características podem ser declaradas como um dicionário ou uma tupla. Você usa o método de dicionário porque é mais conveniente.

Code explicação

  • tf.decode_csv(value, record_defaults= RECORDS_ALL): o método decode_csv usa a saída do TextLineConjunto de dados para ler o arquivo CSV. `record_defaults` instrui o TensorFlow sobre os tipos de coluna. No TensorFlow 2.x, esse símbolo reside em `tf.io.decode_csv`.
  • dict(zip(COLUMNS, columns)): preenche o dicionário com todas as colunas extracdurante este processamento de dados
  • features.pop('medv'): exclui a variável alvo das variáveis ​​de características e cria uma variável de rótulo.

O conjunto de dados precisa de mais elementos para alimentar os tensores iterativamente. De fato, você precisa adicionar o método `repeat` para permitir que o conjunto de dados continue alimentando o modelo indefinidamente. Se você não adicionar o método, o modelo iterará apenas uma vez e, em seguida, lançará um erro porque não há mais dados sendo inseridos no pipeline.

Depois disso, você pode controlar o tamanho do lote com o método `batch`. Isso significa que você informa ao conjunto de dados a quantidade de dados que deseja passar para o pipeline em cada iteração. Se você definir um tamanho de lote grande, o modelo ficará lento.

Passo 3) Crie o iterador

Agora você está pronto para a segunda etapa: crie um iterador para retornar os elementos do conjunto de dados.

A maneira mais simples de criar um operador é com o método make_one_shot_iterator.

Depois disso, você pode criar os recursos e rótulos do iterador.

Passo 4) Consumir os dados

Você pode verificar o que acontece com a função `input_fn`. É necessário chamar a função em uma sessão para consumir os dados. Tente com um tamanho de lote igual a 1.

Observe que ele imprime as características em um dicionário e o rótulo como uma matriz.

Isso exibirá a primeira linha do arquivo CSV. Você pode tentar executar este código várias vezes com diferentes tamanhos de lote.

next_batch = input_fn(df_train, batch_size = 1, num_epoch = None)
with tf.Session() as sess:
     first_batch  = sess.run(next_batch)
     print(first_batch)

saída

({'crim': array([2.3004], dtype=float32), 'zn': array([0.], dtype=float32), 'indus': array([19.58], dtype=float32), 'nox': array([0.605], dtype=float32), 'rm': array([6.319], dtype=float32), 'age': array([96.1], dtype=float32), 'dis': array([2.1], dtype=float32), 'tax': array([403.], dtype=float32), 'ptratio': array([14.7], dtype=float32)}, array([23.8], dtype=float32))

Passo 5) Defina a coluna de recursos

Você precisa definir as colunas numéricas da seguinte forma:

X1= tf.feature_column.numeric_column('crim')
X2= tf.feature_column.numeric_column('zn')
X3= tf.feature_column.numeric_column('indus')
X4= tf.feature_column.numeric_column('nox')
X5= tf.feature_column.numeric_column('rm')
X6= tf.feature_column.numeric_column('age')
X7= tf.feature_column.numeric_column('dis')
X8= tf.feature_column.numeric_column('tax')
X9= tf.feature_column.numeric_column('ptratio')

Observe que você precisa combinar todas as variáveis ​​em um único bucket.

base_columns = [X1, X2, X3,X4, X5, X6,X7, X8, X9]

Passo 6) Construa o modelo

Você pode treinar o modelo com o estimador LinearRegressor.

model = tf.estimator.LinearRegressor(feature_columns=base_columns, model_dir='train3')

saída

INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'train3', '_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 0x1820a010f0>, '_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}

Você precisa usar um função lambda para permitir que você escreva os argumentos para a função `input_fn`. Se você não usar uma função lambda, não poderá treinar o modelo.

# Train the estimator
model.train(steps =1000,
          input_fn= lambda : input_fn(df_train,batch_size=128, num_epoch = None))

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 train3/model.ckpt.
INFO:tensorflow:loss = 83729.64, step = 1
INFO:tensorflow:global_step/sec: 72.5646
INFO:tensorflow:loss = 13909.657, step = 101 (1.380 sec)
INFO:tensorflow:global_step/sec: 101.355
INFO:tensorflow:loss = 12881.449, step = 201 (0.986 sec)
INFO:tensorflow:global_step/sec: 109.293
INFO:tensorflow:loss = 12391.541, step = 301 (0.915 sec)
INFO:tensorflow:global_step/sec: 102.235
INFO:tensorflow:loss = 12050.5625, step = 401 (0.978 sec)
INFO:tensorflow:global_step/sec: 104.656
INFO:tensorflow:loss = 11766.134, step = 501 (0.956 sec)
INFO:tensorflow:global_step/sec: 106.697
INFO:tensorflow:loss = 11509.922, step = 601 (0.938 sec)
INFO:tensorflow:global_step/sec: 118.454
INFO:tensorflow:loss = 11272.889, step = 701 (0.844 sec)
INFO:tensorflow:global_step/sec: 114.947
INFO:tensorflow:loss = 11051.9795, step = 801 (0.870 sec)
INFO:tensorflow:global_step/sec: 111.484
INFO:tensorflow:loss = 10845.855, step = 901 (0.897 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train3/model.ckpt.
INFO:tensorflow:Loss for final step: 5925.9873.
Out[8]:
<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x18225eb8d0>

Você pode avaliar o ajuste do seu modelo no conjunto de teste com o código abaixo:

results = model.evaluate(steps =None,input_fn=lambda: input_fn(df_eval, batch_size =128, num_epoch = 1))
for key in results:
print("   {}, was: {}".format(key, results[key]))

saída

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-13-02:06:02
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train3/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-13-02:06:02
INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.15896, global_step = 1000, loss = 3215.896
   average_loss, was: 32.158958435058594
   loss, was: 3215.89599609375
   global_step, was: 1000

O último passo é prever o valor do alvo com base nos valores da matriz de características. Você pode escrever um dicionário com os valores que deseja prever. Seu modelo possui nove características, então você precisa fornecer um valor para cada uma delas. O modelo fornecerá uma previsão para cada uma.

No código abaixo, você insere os valores de cada característica contida no arquivo CSV df_predict.

Você precisa escrever uma nova função `input_fn` porque não há rótulos no conjunto de dados. Você pode usar a API `from_tensors` do objeto `Dataset`.

prediction_input = {
          'crim': [0.03359,5.09017,0.12650,0.05515,8.15174,0.24522],
          'zn': [75.0,0.0,25.0,33.0,0.0,0.0],
          'indus': [2.95,18.10,5.13,2.18,18.10,9.90],
          'nox': [0.428,0.713,0.453,0.472,0.700,0.544],
          'rm': [7.024,6.297,6.762,7.236,5.390,5.782],
          'age': [15.8,91.8,43.4,41.1,98.9,71.7],
          'dis': [5.4011,2.3682,7.9809,4.0220,1.7281,4.0317],
          'tax': [252,666,284,222,666,304],
          'ptratio': [18.3,20.2,19.7,18.4,20.2,18.4]
     }
     def test_input_fn():
     dataset = tf.data.Dataset.from_tensors(prediction_input)
     return dataset

     # Predict all our prediction_input
     pred_results = model.predict(input_fn=test_input_fn)

Por fim, imprima as previsões.

for pred in enumerate(pred_results):
print(pred)

saída

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train3/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
(0, {'predictions': array([32.297546], dtype=float32)})
(1, {'predictions': array([18.96125], dtype=float32)})
(2, {'predictions': array([27.270979], dtype=float32)})
(3, {'predictions': array([29.299236], dtype=float32)})
(4, {'predictions': array([16.436684], dtype=float32)})
(5, {'predictions': array([21.460876], dtype=float32)})

INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train3/model.ckpt-5000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. (0, {'predictions': array([35.60663], dtype=float32)}) (1, {'predictions': array([22.298521], dtype=float32)}) (2, {'predictions': array([25.74533], dtype=float32)}) (3, {'predictions': array([35.126694], dtype=float32)}) (4, {'predictions': array([17.94416], dtype=float32)}) (5, {'predictions': array([22.606628], dtype=float32)})

Os três pipelines retornam as mesmas seis previsões, o que confirma que a escolha entre Pandas, NumPy e um conjunto de dados nativo do TensorFlow é uma questão de conveniência, e não de precisão.

Perguntas Frequentes

Não. O TensorFlow marcou os estimadores e as colunas de recursos como totalmente obsoletos na versão 2.12 e os removeu na versão 2.16. Fixe o TensorFlow na versão 1.15 ou 2.15 para executar este código sem alterações, ou reescreva o modelo com camadas Keras, o que a equipe do TensorFlow agora recomenda.

Carregue os arquivos CSV com Pandas, dimensione as nove características com uma camada de Normalização e, em seguida, empilhe uma única unidade Dense(1). Compile com um otimizador e a perda mean_squared_error e, em seguida, chame fit. Uma unidade Dense sem ativação é uma regressão linear.

Comece com um valor em torno de 0.01 e ajuste por fatores de dez. Uma taxa muito pequena precisa de muito mais iterações para convergir, enquanto uma taxa muito grande faz a perda oscilar. Trace a curva de perda e mantenha a maior taxa que ainda apresente uma queda suave.

O scikit-learn removeu a função `load_boston` na versão 1.2 devido a preocupações éticas relacionadas a uma variável racial criada artificialmente. Este tutorial lê arquivos CSV simples, então o link para download ainda funciona, mas novos projetos devem usar os conjuntos de dados de habitação da Califórnia ou de Ames.

O Erro Quadrático Médio (RMSE) restaura as unidades originais, o Erro Absoluto Médio (MAE) resiste a valores discrepantes e o R² indica a parcela da variância explicada. Apresente uma métrica de erro absoluto juntamente com o R², pois um R² alto ainda pode mascarar grandes erros de previsão individuais.

A regressão linear prevê um número contínuo, como o preço de uma casa. classificador linear prevê um rótulo de classe discreto. Ambos ajustam uma soma ponderada das características, mas o classificador passa essa soma por um limiar de decisão.

Os pipelines automatizados pontuam as características com regularização Lasso, informação mútua ou importância por permutação e, em seguida, descartam as mais fracas. As ferramentas de AutoML pesquisam opções de pré-processamento e de modelo em conjunto, para que você gaste menos tempo selecionando manualmente quais colunas pertencem a feature_cols.

O Copilot gera rapidamente código padrão, incluindo funções de entrada, listas de colunas de recursos e loops de avaliação. Considere cada sugestão como um rascunho, pois ela frequentemente emite chamadas obsoletas do Estimator. Verifique cada símbolo gerado em relação à API atual do TensorFlow antes de executá-lo.

Resuma esta postagem com: