Série Temporal - Modelo LSTM

Agora, estamos familiarizados com a modelagem estatística em séries temporais, mas o aprendizado de máquina está na moda agora, por isso é essencial estar familiarizado com alguns modelos de aprendizado de máquina também. Começaremos com o modelo mais popular no domínio das séries temporais - o modelo de Memória de Longo Prazo.

LSTM é uma classe de rede neural recorrente. Portanto, antes de passarmos para o LSTM, é essencial entender as redes neurais e as redes neurais recorrentes.

Redes neurais

Uma rede neural artificial é uma estrutura em camadas de neurônios conectados, inspirada por redes neurais biológicas. Não é um algoritmo, mas combinações de vários algoritmos que nos permitem fazer operações complexas nos dados.

Redes Neurais Recorrentes

É uma classe de redes neurais adaptadas para lidar com dados temporais. Os neurônios do RNN possuem um estado / memória celular, e a entrada é processada de acordo com esse estado interno, que é conseguido com a ajuda de loops na rede neural. Existem módulos recorrentes de camadas 'tanh' nos RNNs que permitem reter informações. No entanto, não por muito tempo, e é por isso que precisamos de modelos LSTM.

LSTM

É um tipo especial de rede neural recorrente, capaz de aprender dependências de dados de longo prazo. Isso é obtido porque o módulo recorrente do modelo possui uma combinação de quatro camadas interagindo entre si.

A imagem acima mostra quatro camadas de rede neural em caixas amarelas, operadores pontuais em círculos verdes, entrada em círculos amarelos e o estado da célula em círculos azuis. Um módulo LSTM tem um estado de célula e três portas que fornecem o poder de aprender, desaprender ou reter seletivamente as informações de cada uma das unidades. O estado da célula em LSTM ajuda a informação a fluir através das unidades sem ser alterada, permitindo apenas algumas interações lineares. Cada unidade tem uma entrada, uma saída e uma porta de esquecimento que pode adicionar ou remover as informações do estado da célula. A porta de esquecimento decide quais informações do estado anterior da célula devem ser esquecidas, pois usa uma função sigmóide. A porta de entrada controla o fluxo de informações para o estado atual da célula usando uma operação de multiplicação pontual de 'sigmóide' e 'tanh', respectivamente. Finalmente, a porta de saída decide quais informações devem ser passadas para o próximo estado oculto

Agora que entendemos o funcionamento interno do modelo LSTM, vamos implementá-lo. Para entender a implementação do LSTM, começaremos com um exemplo simples - uma linha reta. Vejamos se o LSTM pode aprender a relação de uma linha reta e predizê-la.

Primeiro, vamos criar o conjunto de dados que descreve uma linha reta.

Em [402]:

x = numpy.arange (1,500,1)
y = 0.4 * x + 30
plt.plot(x,y)

Fora [402]:

[<matplotlib.lines.Line2D at 0x1eab9d3ee10>]

Em [403]:

trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
train = numpy.array(list(zip(trainx,trainy)))
test = numpy.array(list(zip(trainx,trainy)))

Agora que os dados foram criados e divididos em treinar e testar. Vamos converter os dados da série temporal na forma de dados de aprendizagem supervisionada de acordo com o valor do período de lookback, que é essencialmente o número de defasagens que são vistas para prever o valor no tempo 't'.

Então, uma série temporal como esta -

time variable_x
t1  x1
t2  x2
 :   :
 :   :
T   xT

Quando o período de lookback é 1, é convertido em -

x1   x2
x2   x3
 :    :
 :    :
xT-1 xT

Em [404]:

def create_dataset(n_X, look_back):
   dataX, dataY = [], []
   for i in range(len(n_X)-look_back):
      a = n_X[i:(i+look_back), ]
      dataX.append(a)
      dataY.append(n_X[i + look_back, ])
   return numpy.array(dataX), numpy.array(dataY)

Em [405]:

look_back = 1
trainx,trainy = create_dataset(train, look_back)
testx,testy = create_dataset(test, look_back)

trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
testx = numpy.reshape(testx, (testx.shape[0], 1, 2))

Agora vamos treinar nosso modelo.

Pequenos lotes de dados de treinamento são mostrados para a rede, uma execução de quando todos os dados de treinamento são mostrados ao modelo em lotes e o erro é calculado é chamada de época. As épocas devem ser executadas até o momento em que o erro estiver reduzindo.

Dentro [ ]:

from keras.models import Sequential
from keras.layers import LSTM, Dense

model = Sequential()
model.add(LSTM(256, return_sequences = True, input_shape = (trainx.shape[1], 2)))
model.add(LSTM(128,input_shape = (trainx.shape[1], 2)))
model.add(Dense(2))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
model.save_weights('LSTMBasic1.h5')

Em [407]:

model.load_weights('LSTMBasic1.h5')
predict = model.predict(testx)

Agora vamos ver como são nossas previsões.

Em [408]:

plt.plot(testx.reshape(398,2)[:,0:1], testx.reshape(398,2)[:,1:2])
plt.plot(predict[:,0:1], predict[:,1:2])

Fora [408]:

[<matplotlib.lines.Line2D at 0x1eac792f048>]

Agora, devemos tentar modelar uma onda seno ou cosseno de maneira semelhante. Você pode executar o código fornecido abaixo e brincar com os parâmetros do modelo para ver como os resultados mudam.

Em [409]:

x = numpy.arange (1,500,1)
y = numpy.sin(x)
plt.plot(x,y)

Fora [409]:

[<matplotlib.lines.Line2D at 0x1eac7a0b3c8>]

Em [410]:

trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
train = numpy.array(list(zip(trainx,trainy)))
test = numpy.array(list(zip(trainx,trainy)))

Em [411]:

look_back = 1
trainx,trainy = create_dataset(train, look_back)
testx,testy = create_dataset(test, look_back)
trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
testx = numpy.reshape(testx, (testx.shape[0], 1, 2))

Dentro [ ]:

model = Sequential()
model.add(LSTM(512, return_sequences = True, input_shape = (trainx.shape[1], 2)))
model.add(LSTM(256,input_shape = (trainx.shape[1], 2)))
model.add(Dense(2))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
model.save_weights('LSTMBasic2.h5')

Em [413]:

model.load_weights('LSTMBasic2.h5')
predict = model.predict(testx)

Em [415]:

plt.plot(trainx.reshape(398,2)[:,0:1], trainx.reshape(398,2)[:,1:2])
plt.plot(predict[:,0:1], predict[:,1:2])

Fora [415]:

[<matplotlib.lines.Line2D at 0x1eac7a1f550>]

Agora você está pronto para avançar para qualquer conjunto de dados.