Serie temporal - Modelo LSTM

Ahora, estamos familiarizados con el modelado estadístico en series de tiempo, pero el aprendizaje automático está de moda en este momento, por lo que es esencial estar familiarizado también con algunos modelos de aprendizaje automático. Comenzaremos con el modelo más popular en el dominio de las series de tiempo: el modelo de memoria a corto plazo.

LSTM es una clase de red neuronal recurrente. Entonces, antes de que podamos saltar a LSTM, es esencial comprender las redes neuronales y las redes neuronales recurrentes.

Redes neuronales

Una red neuronal artificial es una estructura en capas de neuronas conectadas, inspirada en redes neuronales biológicas. No es un algoritmo, sino combinaciones de varios algoritmos que nos permiten realizar operaciones complejas con datos.

Redes neuronales recurrentes

Es una clase de redes neuronales diseñadas para tratar con datos temporales. Las neuronas de RNN tienen un estado / memoria celular, y la entrada se procesa de acuerdo con este estado interno, que se logra con la ayuda de bucles en la red neuronal. Hay módulos recurrentes de capas 'tanh' en las RNN que les permiten retener información. Sin embargo, no por mucho tiempo, por eso necesitamos modelos LSTM.

LSTM

Es un tipo especial de red neuronal recurrente que es capaz de aprender dependencias a largo plazo en los datos. Esto se logra porque el módulo recurrente del modelo tiene una combinación de cuatro capas que interactúan entre sí.

La imagen de arriba muestra cuatro capas de redes neuronales en cuadros amarillos, operadores puntuales en círculos verdes, entrada en círculos amarillos y estado de celda en círculos azules. Un módulo LSTM tiene un estado de celda y tres puertas que les proporciona el poder de aprender, desaprender o retener información de forma selectiva de cada una de las unidades. El estado de la celda en LSTM ayuda a que la información fluya a través de las unidades sin ser alterada al permitir solo algunas interacciones lineales. Cada unidad tiene una entrada, salida y una puerta de olvido que puede agregar o quitar la información al estado de la celda. La puerta de olvido decide qué información del estado anterior de la celda debe olvidarse para lo cual utiliza una función sigmoidea. La puerta de entrada controla el flujo de información al estado actual de la celda usando una operación de multiplicación puntual de 'sigmoide' y 'tanh' respectivamente. Finalmente, la puerta de salida decide qué información se debe pasar al siguiente estado oculto.

Ahora que hemos entendido el funcionamiento interno del modelo LSTM, vamos a implementarlo. Para comprender la implementación de LSTM, comenzaremos con un ejemplo simple: una línea recta. Veamos, si LSTM puede aprender la relación de una línea recta y predecirla.

Primero, creemos el conjunto de datos que representa una línea recta.

En [402]:

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

Fuera [402]:

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

En [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)))

Ahora que los datos se han creado y dividido en entrenar y probar. Convirtamos los datos de la serie temporal en forma de datos de aprendizaje supervisados ​​de acuerdo con el valor del período retrospectivo, que es esencialmente el número de retrasos que se ven para predecir el valor en el tiempo 't'.

Entonces, una serie de tiempo como esta ...

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

Cuando el período retroactivo es 1, se convierte en -

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

En [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)

En [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))

Ahora entrenaremos nuestro modelo.

Pequeños lotes de datos de entrenamiento se muestran en la red, una ejecución cuando los datos de entrenamiento completos se muestran al modelo en lotes y se calcula el error se llama época. Las épocas se ejecutarán hasta el momento en que se reduzca el error.

En []:

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')

En [407]:

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

Ahora veamos cómo son nuestras predicciones.

En [408]:

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

Fuera [408]:

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

Ahora, deberíamos intentar modelar una onda seno o coseno de una manera similar. Puede ejecutar el código que se proporciona a continuación y jugar con los parámetros del modelo para ver cómo cambian los resultados.

En [409]:

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

Fuera [409]:

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

En [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)))

En [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))

En []:

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')

En [413]:

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

En [415]:

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

Fuera [415]:

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

Ahora está listo para pasar a cualquier conjunto de datos.