Tutorial RNN (rede neural recorrente): exemplo do TensorFlow

Por que precisamos de uma Rede Neural Recorrente (RNN)?

Rede Neural Recorrente (RNN) permite modelar unidades de memória para persistir dados e modelar dependências de curto prazo. Também é usado na previsão de séries temporais para a identificação de correlações e padrões de dados. Também ajuda a produzir resultados preditivos para dados sequenciais, proporcionando um comportamento semelhante ao do cérebro humano.

A estrutura de uma Rede Neural Artificial é relativamente simples e trata principalmente da multiplicação de matrizes. Durante a primeira etapa, as entradas são multiplicadas por pesos inicialmente aleatórios e o viés é transformado com uma função de ativação e os valores de saída são usados ​​para fazer uma previsão. Esta etapa dá uma ideia de quão distante a rede está da realidade.

A métrica aplicada é a perda. Quanto maior a função de perda, mais burro é o modelo. Para melhorar o conhecimento da rede, é necessária alguma otimização ajustando os pesos da rede. A descida gradiente estocástica é o método empregado para alterar os valores dos pesos na direção direita. Feito o ajuste, a rede pode usar outro lote de dados para testar seu novo conhecimento.

O erro, felizmente, é menor do que antes, mas não é pequeno o suficiente. A etapa de otimização é feita iterativamente até que o erro seja minimizado, ou seja, nenhuma informação mais possa ser extraída.

O problema desse tipo de modelo é que ele não possui memória. Isso significa que a entrada e a saída são independentes. Em outras palavras, o modelo não se importa com o que veio antes. Isso levanta algumas questões quando você precisa prever séries temporais ou sentenças porque a rede precisa ter informações sobre os dados históricos ou palavras anteriores.

Para superar esse problema, um novo tipo de arquitetura foi desenvolvido: Rede Neural Recorrente (doravante RNN)

O que é uma rede neural recorrente (RNN)?

A Rede Neural Recorrente (RNN) é uma classe de Rede neural artificial em que a conexão entre diferentes nós forma um gráfico direcionado para fornecer um comportamento dinâmico temporal. Ajuda a modelar dados sequenciais derivados de redes feedforward. Funciona de forma semelhante ao cérebro humano para fornecer resultados preditivos.

Uma rede neural recorrente é bastante semelhante a uma rede neural tradicional, exceto que um estado de memória é adicionado aos neurônios. O cálculo para incluir uma memória é simples.

Imagine um modelo simples com apenas um neurônio alimentado por um lote de dados. Em uma rede neural tradicional, o modelo produz a saída multiplicando a entrada pelo peso e pela função de ativação. Com um RNN, essa saída é enviada de volta para si mesma várias vezes. Nós chamamos intervalo de tempo a quantidade de tempo que a saída se torna a entrada da próxima multiplicação da matriz.

Por exemplo, na imagem abaixo, você pode ver que a rede é composta por um neurônio. A rede calcula a multiplicação das matrizes entre a entrada e o peso e adiciona não linearidade com a função de ativação. Torna-se a saída em t-1. Esta saída é a entrada da segunda multiplicação da matriz.

Rede Neural Recorrente (RNN)
Rede Neural Recorrente (RNN)

Abaixo, codificamos um RNN simples no TensorFlow para entender a etapa e também o formato da saída.

A rede é composta por:

  • Quatro entradas
  • Seis neurônios
  • Etapas de 2 vezes

A rede continuará conforme ilustrado na imagem abaixo.

Rede Neural Recorrente (RNN)

A rede é chamada de 'recorrente' porque realiza a mesma operação em cada quadrado ativado. A rede calculou os pesos das entradas e da saída anterior antes de usar uma função de ativação.

import numpy as np
import tensorflow as tf
n_inputs = 4
n_neurons = 6
n_timesteps = 2
The data is a sequence of a number from 0 to 9 and divided into three batches of data.
## Data 
X_batch = np.array([
        [[0, 1, 2, 5], [9, 8, 7, 4]], # Batch 1
        [[3, 4, 5, 2], [0, 0, 0, 0]], # Batch 2
        [[6, 7, 8, 5], [6, 5, 4, 2]], # Batch 3
    ])

Podemos construir a rede com um espaço reservado para os dados, o estágio recorrente e a saída.

  1. Defina o espaço reservado para os dados
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])

Aqui:

  • Nenhum: Desconhecido e terá o tamanho do lote
  • n_timesteps: Número de vezes que a rede enviará a saída de volta ao neurônio
  • n_inputs: Número de entradas por lote
  1. Defina a rede recorrente

Conforme mencionado na imagem acima, a rede é composta por 6 neurônios. A rede calculará dois produtos escalares:

  • Dados de entrada com o primeiro conjunto de pesos (ou seja, 6: igual ao número de neurônios)
  • Saída anterior com um segundo conjunto de pesos (ou seja, 6: correspondente ao número de saída)

Observe que, durante o primeiro feedforward, os valores da saída anterior são iguais a zero porque não temos nenhum valor disponível.

O objeto para construir um RNN é tf.contrib.rnn.BasicRNNCell com o argumento num_units para definir o número de entradas

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)

Agora que a rede está definida, você pode calcular as saídas e estados

outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)

Este objeto usa um loop interno para multiplicar as matrizes o número apropriado de vezes.

Observe que o neurônio recorrente é uma função de todas as entradas dos intervalos de tempo anteriores. É assim que a rede constrói sua própria memória. As informações do momento anterior podem se propagar no futuro. Esta é a magia da rede neural recorrente

## Define the shape of the tensor
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])
## Define the network
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
init = tf.global_variables_initializer()
init = tf.global_variables_initializer()
with tf.Session() as sess:
    init.run()
    outputs_val = outputs.eval(feed_dict={X: X_batch})
print(states.eval(feed_dict={X: X_batch}))
[[ 0.38941205 -0.9980438   0.99750966  0.7892596   0.9978241   0.9999997 ]
 [ 0.61096436  0.7255889   0.82977575 -0.88226104  0.29261455 -0.15597084]
 [ 0.62091285 -0.87023467  0.99729395 -0.58261937  0.9811445   0.99969864]]

Para fins explicativos, imprima os valores do estado anterior. A saída impressa acima mostra a saída do último estado. Agora imprima toda a saída, você pode notar que os estados são a saída anterior de cada lote. Ou seja, a saída anterior contém as informações sobre toda a sequência.e

print(outputs_val)    
print(outputs_val.shape)    
[[[-0.75934666 -0.99537754  0.9735819  -0.9722234  -0.14234993
   -0.9984044 ]
  [ 0.99975264 -0.9983206   0.9999993  -1.         -0.9997506
   -1.        ]]

 [[ 0.97486496 -0.98773265  0.9969686  -0.99950117 -0.7092863
   -0.99998885]
  [ 0.9326837   0.2673438   0.2808514  -0.7535883  -0.43337247
    0.5700631 ]]

 [[ 0.99628735 -0.9998728   0.99999213 -0.99999976 -0.9884324
   -1.        ]
  [ 0.99962527 -0.9467421   0.9997403  -0.99999714 -0.99929446
   -0.9999795 ]]]
(3, 2, 6)

Rede Neural Recorrente (RNN)

A saída tem o formato de (3, 2, 6):

  • 3: Número de lotes
  • 2: Número do intervalo de tempo
  • 6: Número de neurônios

A otimização de uma rede neural recorrente é idêntica a uma rede neural tradicional. Você verá com mais detalhes como codificar a otimização na próxima parte deste tutorial sobre Rede Neural Recorrente.

Aplicações de RNN

RNN tem múltiplos usos, especialmente quando se trata de prever o futuro. No setor financeiro, o RNN pode ser útil na previsão dos preços das ações ou no sinal da direção do mercado de ações (ou seja, positivo ou negativo).

O RNN é útil para um carro autônomo, pois pode evitar um acidente de carro antecipando a trajetória do veículo.

RNN é amplamente utilizado em análise de texto, legendagem de imagens, análise de sentimento e tradução automática. Por exemplo, pode-se utilizar uma crítica de filme para compreender o sentimento que o espectador percebeu após assistir ao filme. Automatizar essa tarefa é muito útil quando a produtora cinematográfica não tem tempo suficiente para revisar, rotular, consolidar e analisar as resenhas. A máquina pode fazer o trabalho com maior nível de precisão.

Limitações do RNN

Em teoria, o RNN deveria transportar as informações até certo ponto. No entanto, é bastante desafiador propagar todas essas informações quando o intervalo de tempo é muito longo. Quando uma rede tem muitas camadas profundas, ela se torna impossível de treinar. Este problema é denominado: problema de gradiente de desaparecimento. Se você se lembra, a rede neural atualiza o peso usando o algoritmo de gradiente descendente. Os gradientes ficam menores quando a rede progride para as camadas inferiores.

Concluindo, os gradientes permanecem constantes, o que significa que não há espaço para melhorias. O modelo aprende com uma mudança no gradiente; esta mudança afeta a saída da rede. Porém, se a diferença no gradiente for muito pequena (ou seja, os pesos mudam um pouco), a rede não consegue aprender nada e, portanto, a saída. Portanto, uma rede que enfrenta um problema de gradiente evanescente não pode convergir para uma boa solução.

Melhoria LSTM

Para superar o problema potencial de desaparecimento do gradiente enfrentado pelo RNN, três pesquisadores, Hochreiter, Schmidhuber e Bengio melhoraram o RNN com uma arquitetura chamada Long Short-Term Memory (LSTM). Em resumo, o LSMT fornece à rede informações passadas relevantes para tempos mais recentes. A máquina usa uma arquitetura melhor para selecionar e transportar informações posteriormente.

A arquitetura LSTM está disponível no TensorFlow, tf.contrib.rnn.LSTMCell. LSTM está fora do escopo do tutorial. Você pode consultar o oficial documentação para mais informações

RNN em série temporal

Neste tutorial do TensorFlow RNN, você usará um RNN com dados de série temporal. As séries temporais dependem do tempo anterior, o que significa que os valores passados ​​incluem informações relevantes com as quais a rede pode aprender. A ideia por trás da previsão de séries temporais é estimar o valor futuro de uma série, digamos, preço das ações, temperatura, PIB e assim por diante.

A preparação de dados para Keras RNN e séries temporais pode ser um pouco complicada. Em primeiro lugar, o objetivo é prever o próximo valor da série, ou seja, você usará as informações anteriores para estimar o valor em t + 1. O rótulo é igual à sequência de entrada e deslocado um período à frente. Em segundo lugar, o número de entradas é definido como 1, ou seja, uma observação por vez. Por último, o intervalo de tempo é igual à sequência do valor numérico. Por exemplo, se você definir o intervalo de tempo como 10, a sequência de entrada retornará dez vezes consecutivas.

Observe o gráfico abaixo, representamos os dados da série temporal à esquerda e uma sequência de entrada fictícia à direita. Você cria uma função para retornar um conjunto de dados com valor aleatório para cada dia de janeiro de 2001 a dezembro de 2016

# To plot pretty figures
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
def create_ts(start = '2001', n = 201, freq = 'M'):
    rng = pd.date_range(start=start, periods=n, freq=freq)
    ts = pd.Series(np.random.uniform(-18, 18, size=len(rng)), rng).cumsum()
    return ts
ts= create_ts(start = '2001', n = 192, freq = 'M')
ts.tail(5)

saída

2016-08-31    -93.459631
2016-09-30    -95.264791
2016-10-31    -95.551935
2016-11-30   -105.879611
2016-12-31   -123.729319
Freq: M, dtype: float64
ts = create_ts(start = '2001', n = 222)

# Left
plt.figure(figsize=(11,4))
plt.subplot(121)
plt.plot(ts.index, ts)
plt.plot(ts.index[90:100], ts[90:100], "b-", linewidth=3, label="A training instance")
plt.title("A time series (generated)", fontsize=14)

# Right
plt.subplot(122)
plt.title("A training instance", fontsize=14)
plt.plot(ts.index[90:100], ts[90:100], "b-", markersize=8, label="instance")
plt.plot(ts.index[91:101], ts[91:101], "bo", markersize=10, label="target", markerfacecolor='red')
plt.legend(loc="upper left")
plt.xlabel("Time")

plt.show()

RNN em séries temporais

A parte direita do gráfico mostra todas as séries. Começou em 2001 e termina em 2019. Não faz sentido alimentar todos os dados da rede, em vez disso, é necessário criar um lote de dados com comprimento igual ao intervalo de tempo. Este lote será a variável X. A variável Y é igual a X, mas deslocada em um período (ou seja, você deseja prever t+1).

Ambos os vetores têm o mesmo comprimento. Você pode ver isso na parte direita do gráfico acima. A linha representa os dez valores da entrada X, enquanto os pontos vermelhos são os dez valores do rótulo, Y. Observe que o rótulo começa um período antes de X e termina um período depois.

Crie um RNN para prever séries temporais no TensorFlow

Agora neste treinamento RNN, é hora de construir seu primeiro RNN para prever a série acima. Você precisa especificar alguns hiperparâmetros (os parâmetros do modelo, ou seja, número de neurônios, etc.) para o modelo:

  • Número de entrada: 1
  • Intervalo de tempo (janelas em série temporal): 10
  • Número de neurônios: 120
  • Número de saída: 1

Sua rede aprenderá com uma sequência de 10 dias e conterá 120 neurônios recorrentes. Você alimenta o modelo com uma entrada, ou seja, um dia. Sinta-se à vontade para alterar os valores para ver se o modelo melhorou.

Antes de construir o modelo, você precisa dividir o conjunto de dados em um conjunto de treinamento e um conjunto de teste. O conjunto de dados completo possui 222 pontos de dados; você usará os primeiros 201 pontos para treinar o modelo e os últimos 21 pontos para testar seu modelo.

Depois de definir um conjunto de treinamento e teste, você precisa criar um objeto contendo os lotes. Nestes lotes, você tem valores X e valores Y. Lembre-se de que os valores de X estão defasados ​​em um período. Portanto, você usa as primeiras 200 observações e o intervalo de tempo é igual a 10. O objeto X_batches deve conter 20 lotes de tamanho 10*1. O y_batches tem o mesmo formato do objeto X_batches, mas com um ponto à frente.

Passo 1) Crie o trem e teste

Primeiro de tudo, você converte a série em um numpy variedade; em seguida, você define as janelas (ou seja, o número de tempo com o qual a rede aprenderá), o número de entradas, saídas e o tamanho do conjunto de trens, conforme mostrado no exemplo do TensorFlow RNN abaixo.

series = np.array(ts)
n_windows = 20   
n_input =  1
n_output = 1
size_train = 201

Depois disso, basta dividir o array em dois conjuntos de dados.

## Split data
train = series[:size_train]
test = series[size_train:]
print(train.shape, test.shape)
(201,) (21,)

Passo 2) Crie a função para retornar X_batches e y_batches

Para facilitar, você pode criar uma função que retorne dois arrays diferentes, um para X_batches e outro para y_batches.

Vamos escrever uma função RNN TensorFlow para construir os lotes.

Observe que os lotes X estão defasados ​​​​de um período (assumimos o valor t-1). A saída da função deve ter três dimensões. As primeiras dimensões equivalem ao número de lotes, a segunda ao tamanho das janelas e a última ao número de entradas.

A parte complicada é selecionar os pontos de dados corretamente. Para os pontos de dados X, você escolhe as observações de t = 1 a t = 200, enquanto para o ponto de dados Y, você retorna as observações de t = 2 a 201. Depois de ter os pontos de dados corretos, é simples remodelar as séries.

Para construir o objeto com os lotes, você precisa dividir o conjunto de dados em dez lotes de igual comprimento (ou seja, 20). Você pode usar o método reshape e passar -1 para que a série seja semelhante ao tamanho do lote. O valor 20 é o número de observações por lote e 1 é o número de entradas.

Você precisa fazer o mesmo passo, mas para o rótulo.

Observe que você precisa mudar os dados para o número de vezes que deseja prever. Por exemplo, se você quiser prever um tempo de antecedência, mude a série em 1. Se quiser prever dois dias, mude os dados em 2.

x_data = train[:size_train-1]: Select all the training instance minus one day
X_batches = x_data.reshape(-1, windows, input): create the right shape for the batch e.g (10, 20, 1)
def create_batches(df, windows, input, output):
    ## Create X         
        x_data = train[:size_train-1] # Select the data
        X_batches = x_data.reshape(-1, windows, input)  # Reshape the data 
    ## Create y
        y_data = train[n_output:size_train]
        y_batches = y_data.reshape(-1, windows, output)
        return X_batches, y_batches

Agora que a função está definida, você pode chamá-la para criar os lotes conforme mostrado no exemplo RNN abaixo.

X_batches, y_batches = create_batches(df = train,
                                      windows = n_windows,
                                      input = n_input,
                                      output = n_output)

Você pode imprimir a forma para ter certeza de que as dimensões estão corretas.

print(X_batches.shape, y_batches.shape)
(10, 20, 1) (10, 20, 1)

Você precisa criar o conjunto de testes com apenas um lote de dados e 20 observações.

Observe que, se você prevê dias após dias, isso significa que o segundo valor previsto será baseado no valor verdadeiro do primeiro dia (t+1) do conjunto de dados de teste. Na verdade, o verdadeiro valor será conhecido.

Se você deseja prever t+2 (ou seja, dois dias antes), você precisa usar o valor previsto t+1; se você pretende prever t+3 (três dias à frente), precisará usar o valor previsto t+1 e t+2. Faz sentido que seja difícil prever com precisão t+n dias à frente.

X_test, y_test = create_batches(df = test, windows = 20,input = 1, output = 1)
print(X_test.shape, y_test.shape)
(10, 20, 1) (10, 20, 1)

Tudo bem, o tamanho do seu lote está pronto, você pode construir a arquitetura RNN. Lembre-se, você tem 120 neurônios recorrentes.

Passo 3) Construa o modelo

Para criar o modelo, você precisa definir três partes:

  1. A variável com os tensores
  2. O RNN
  3. A perda e otimização

Passo 3.1) Variáveis

Você precisa especificar as variáveis ​​Xey com a forma apropriada. Esta etapa é trivial. O tensor tem a mesma dimensão dos objetos X_batches e y_batches.

Por exemplo, o tensor X é um espaço reservado (confira o tutorial Introdução ao Tensorflow para refrescar sua mente sobre a declaração de variáveis) tem três dimensões:

  • Obs: tamanho do lote
  • n_windows: Comprimento das janelas. ou seja, o número de vezes que o modelo olha para trás
  • n_input: Número de entrada

O resultado é:

tf.placeholder(tf.float32, [None, n_windows, n_input])
## 1. Construct the tensors
X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

Passo 3.2) Crie o RNN

Na segunda parte deste exemplo RNN do TensorFlow, você precisa definir a arquitetura da rede. Como antes, você usa o objeto BasicRNNCell e dynamic_rnn do estimador TensorFlow.

## 2. create the model
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)   

A próxima parte é um pouco mais complicada, mas permite cálculos mais rápidos. Você precisa transformar a saída da execução em uma camada densa e depois convertê-la novamente para ter a mesma dimensão da entrada.

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])  

Passo 3.3) Crie a perda e a otimização

A otimização do modelo depende da tarefa que você está executando. No tutorial anterior sobre CNN, seu objetivo era classificar imagens, neste tutorial da RNN o objetivo é um pouco diferente. Você é solicitado a fazer uma previsão sobre uma variável contínua comparada a uma classe.

Essa diferença é importante porque mudará o problema de otimização. O problema de otimização para uma variável contínua é minimizar o erro quadrático médio. Para construir essas métricas no TF, você pode usar:

  • tf.reduce_sum(tf.square(saídas – y))

O restante do código RNN é o mesmo de antes; você usa um otimizador Adam para reduzir a perda (ou seja, MSE):

  • tf.train.AdamOptimizer(learning_rate=learning_rate)
  • otimizador.minimize(perda)

É isso, você pode embalar tudo e seu modelo está pronto para treinar.

tf.reset_default_graph()
r_neuron = 120    

## 1. Construct the tensors
X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

## 2. create the model
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)              

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])   

## 3. Loss + optimization
learning_rate = 0.001  
 
loss = tf.reduce_sum(tf.square(outputs - y))    
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)         
training_op = optimizer.minimize(loss)                                          

init = tf.global_variables_initializer() 

Você treinará o modelo usando 1500 épocas e imprimirá a perda a cada 150 iterações. Depois que o modelo for treinado, você avalia o modelo no conjunto de teste e cria um objeto contendo as previsões, conforme mostrado no exemplo de rede neural recorrente abaixo.

iteration = 1500 

with tf.Session() as sess:
    init.run()
    for iters in range(iteration):
        sess.run(training_op, feed_dict={X: X_batches, y: y_batches})
        if iters % 150 == 0:
            mse = loss.eval(feed_dict={X: X_batches, y: y_batches})
            print(iters, "\tMSE:", mse)
    
    y_pred = sess.run(outputs, feed_dict={X: X_test})
0 	MSE: 502893.34
150 	MSE: 13839.129
300 	MSE: 3964.835
450 	MSE: 2619.885
600 	MSE: 2418.772
750 	MSE: 2110.5923
900 	MSE: 1887.9644
1050 	MSE: 1747.1377
1200 	MSE: 1556.3398
1350 	MSE: 1384.6113

Por fim, neste tutorial RNN Deep Learning, você pode traçar o valor real da série com o valor previsto. Se o seu modelo for corrigido, os valores previstos deverão ser colocados acima dos valores reais.

Como você pode ver, o modelo pode ser melhorado. Cabe a você alterar os hiperparâmetros como as janelas, o tamanho do lote e o número de neurônios recorrentes.

plt.title("Forecast vs Actual", fontsize=14)
plt.plot(pd.Series(np.ravel(y_test)), "bo", markersize=8, label="Actual", color='green')
plt.plot(pd.Series(np.ravel(y_pred)), "r.", markersize=8, label="Forecast", color='red')
plt.legend(loc="lower left")
plt.xlabel("Time")

plt.show()
Previsão versus Real

Previsão versus Real

Resumo

Uma rede neural recorrente é uma arquitetura robusta para lidar com séries temporais ou análise de texto. A saída do estado anterior é um feedback para preservar a memória da rede ao longo do tempo ou sequência de palavras.

No TensorFlow, você pode usar os seguintes códigos para treinar uma rede neural recorrente do TensorFlow para séries temporais:

Parâmetros do modelo

n_windows = 20   
n_input =  1
n_output = 1
size_train = 201

Defina o modelo

X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)              

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])

Construa a otimização

learning_rate = 0.001  
 
loss = tf.reduce_sum(tf.square(outputs - y))    
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)         
training_op = optimizer.minimize(loss)                                          

Treine o modelo

init = tf.global_variables_initializer() 
iteration = 1500 

with tf.Session() as sess:
    init.run()
    for iters in range(iteration):
        sess.run(training_op, feed_dict={X: X_batches, y: y_batches})
        if iters % 150 == 0:
            mse = loss.eval(feed_dict={X: X_batches, y: y_batches})
            print(iters, "\tMSE:", mse)
    
    y_pred = sess.run(outputs, feed_dict={X: X_test})