Análisis de series temporales con LSTM utilizando la biblioteca Keras de Python

El análisis de series de tiempo se refiere al análisis del cambio en la tendencia de los datos durante un período de tiempo. El análisis de series de tiempo tiene una variedad de aplicaciones. Unos...

Introducción

El análisis de series de tiempo se refiere al análisis del cambio en la tendencia de los datos durante un período de tiempo. El análisis de series de tiempo tiene una variedad de aplicaciones. Una de esas aplicaciones es la predicción del valor futuro de un artículo en función de sus valores pasados. La predicción del precio futuro de las acciones es probablemente el mejor ejemplo de tal aplicación. En este artículo, veremos cómo podemos realizar un análisis de series temporales con la ayuda de una recurrente neuronal roja. Pronosticaremos los precios futuros de las acciones de Apple Company (AAPL), en función de los precios de las acciones de los últimos 5 años.

Conjunto de datos

Los datos que vamos a utilizar para este artículo se pueden descargar de Yahoo Finanzas. Para entrenar nuestro algoritmo, usaremos los precios de las acciones de Apple desde el 1 de enero de 2013 hasta el 31 de diciembre de 2017. En aras de la predicción, usaremos los precios de las acciones de Apple para el mes de enero de 2018. Entonces, para evaluar el desempeño de el algoritmo, descargue también los precios reales de las acciones para el mes de enero de 2018.

Veamos ahora cómo se ven nuestros datos. Abra el archivo de capacitación de precios de acciones de Apple que contiene datos de cinco años. Verá que contiene siete columnas: Fecha, Apertura, Máximo, Mínimo, Cierre, Ajuste de cierre y Volumen. Estaremos pronosticando el precio de apertura de las acciones, por lo tanto, no estamos interesados ​​en el resto de las columnas.

Si traza los precios de las acciones de apertura contra la fecha, verá el siguiente gráfico:

{.img-responsive}

Puede ver que la tendencia es altamente no lineal y es muy difícil capturar la tendencia utilizando esta información. Aquí es donde se puede utilizar el poder de LSTM. LSTM (Long Short-Term Memory network) es un tipo de red neuronal recurrente capaz de recordar la información pasada y, al predecir los valores futuros, tiene en cuenta esta información pasada.

Basta de preliminares, veamos cómo se puede usar LSTM para el análisis de series de tiempo.

Predicción de los precios futuros de las acciones

La predicción del precio de las acciones es similar a cualquier otro problema de aprendizaje automático en el que se nos da un conjunto de características y tenemos que predecir un valor correspondiente. Realizaremos los mismos pasos que realizamos para resolver cualquier problema de aprendizaje automático. Sigue estos pasos:

Importar bibliotecas

El primer paso, como siempre, es importar las bibliotecas requeridas. Ejecute el siguiente script para hacerlo:

1
2
3
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

Importar conjunto de datos

Ejecute el siguiente script para importar el conjunto de datos. Por el bien de este artículo, los datos se almacenaron en la carpeta Conjuntos de datos, dentro de la unidad "E". Puede cambiar la ruta en consecuencia.

1
apple_training_complete = pd.read_csv(r'E:\Datasets\apple_training.csv')

Como dijimos anteriormente, solo nos interesa el precio de apertura de la acción. Por lo tanto, filtraremos todos los datos de nuestro conjunto de entrenamiento y conservaremos solo los valores de la columna Abrir. Ejecute el siguiente script:

1
apple_training_processed = apple_training_complete.iloc[:, 1:2].values

Normalización de datos {#normalización de datos}

Como regla general, siempre que utilice una red neuronal, debe normalizar o escalar sus datos. Usaremos la clase MinMaxScaler de la biblioteca sklear.preprocessing para escalar nuestros datos entre 0 y 1. El parámetro feature_range se usa para especificar el rango de los datos escalados. Ejecute el siguiente script:

1
2
3
4
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range = (0, 1))

apple_training_scaled = scaler.fit_transform(apple_training_processed)

Convertir datos de entrenamiento en la forma correcta

Como dije antes, en un problema de series de tiempo, tenemos que predecir un valor en el tiempo T, con base en los datos de los días T-N, donde N puede ser cualquier número de pasos. En este artículo, vamos a predecir el precio de apertura de las acciones de los datos en función de los precios de apertura de las acciones de los últimos 60 días. Probé y probé diferentes números y descubrí que los mejores resultados se obtienen cuando se usan los últimos 60 pasos de tiempo. Puede probar diferentes números y ver cómo funciona su algoritmo.

Nuestro conjunto de características debe contener los valores del precio de apertura de las acciones durante los últimos 60 días, mientras que la etiqueta o variable dependiente debe ser el precio de las acciones en el día 61. Ejecute el siguiente script para crear un conjunto de características y etiquetas.

1
2
3
4
5
features_set = []
labels = []
for i in range(60, 1260):
    features_set.append(apple_training_scaled[i-60:i, 0])
    labels.append(apple_training_scaled[i, 0])

En el script anterior, creamos dos listas: feature_set y labels. Hay 1260 registros en los datos de entrenamiento. Ejecutamos un ciclo que comienza desde el registro 61 y almacena todos los 60 registros anteriores en la lista feature_set. El registro 61 se almacena en la lista de etiquetas.

Necesitamos convertir la lista feature_set y labels a la matriz numpy antes de que podamos usarla para el entrenamiento. Ejecute el siguiente script:

1
features_set, labels = np.array(features_set), np.array(labels)

Para entrenar LSTM en nuestros datos, necesitamos convertir nuestros datos en la forma aceptada por LSTM. Necesitamos convertir nuestros datos en formato tridimensional. La primera dimensión es el número de registros o filas en el conjunto de datos, que en nuestro caso es 1260. La segunda dimensión es el número de pasos de tiempo que es 60 mientras que la última dimensión es el número de indicadores. Dado que solo usamos una función, es decir, Abrir, el número de indicadores será uno. Ejecute el siguiente script:

1
features_set = np.reshape(features_set, (features_set.shape[0], features_set.shape[1], 1))

Entrenamiento del LSTM

Hemos preprocesado nuestros datos y los hemos convertido al formato deseado. ahora es el momento de crear nuestro LSTM. El modelo LSTM que vamos a crear será un modelo secuencial con varias capas. Agregaremos cuatro capas LSTM a nuestro modelo seguidas de una capa densa que predice el precio futuro de las acciones.

Importemos primero las bibliotecas que vamos a necesitar para crear nuestro modelo:

1
2
3
4
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout

En el script anterior, importamos la clase Sequential de la biblioteca keras.models y las clases Dense, LSTM y Dropout de la biblioteca keras.layers.

Como primer paso, necesitamos instanciar la clase Sequential. Esta será nuestra clase modelo y agregaremos capas LSTM, Dropout y Dense a este modelo. Ejecute el siguiente script

1
model = Sequential()
Creación de capas LSTM y de abandono

Agreguemos la capa LSTM al modelo que acabamos de crear. Ejecute el siguiente script para hacerlo:

1
model.add(LSTM(units=50, return_sequences=True, input_shape=(features_set.shape[1], 1)))

Para agregar una capa al modelo secuencial, se utiliza el método add. Dentro del método add, pasamos nuestra capa LSTM. El primer parámetro de la capa LSTM es el número de neuronas o nodos que queremos en la capa. El segundo parámetro es return_sequences, que se establece en verdadero ya que agregaremos más capas al modelo. El primer parámetro de input_shape es el número de pasos de tiempo, mientras que el último parámetro es el número de indicadores.

Agreguemos ahora una capa de abandono a nuestro modelo. Se agrega una capa de abandono para evitar el sobreajuste, que es un fenómeno en el que un modelo de aprendizaje automático funciona mejor en los datos de entrenamiento en comparación con los datos de prueba. Ejecute el siguiente script para agregar una capa de exclusión.

1
model.add(Dropout(0.2))

Agreguemos tres capas más de LSTM y abandono a nuestro modelo. Ejecute el siguiente script.

1
2
3
4
5
6
7
8
model.add(LSTM(units=50, return_sequences=True))
model.add(Dropout(0.2))

model.add(LSTM(units=50, return_sequences=True))
model.add(Dropout(0.2))

model.add(LSTM(units=50))
model.add(Dropout(0.2))
Creando una capa densa

Para hacer que nuestro modelo sea más robusto, agregamos una capa densa al final del modelo. El número de neuronas en la capa densa se establecerá en 1 ya que queremos predecir un solo valor en la salida.

1
model.add(Dense(units = 1))
Compilación de modelos

Finalmente, necesitamos compilar nuestro LSTM antes de que podamos entrenarlo con los datos de entrenamiento. El siguiente script compila nuestro modelo.

1
model.compile(optimizer = 'adam', loss = 'mean_squared_error')

Llamamos al método de compilación en el objeto de modelo secuencial que es "modelo" en nuestro caso. Usamos el error medio cuadrado como función de pérdida y para reducir la pérdida u optimizar el algoritmo usamos el [Adán](https://machinelearningmastery. com/adam-optimization-algorithm-for-deep-learning/) optimizador.

Entrenamiento de algoritmos

Ahora es el momento de entrenar el modelo que definimos en los pasos anteriores. Para hacerlo, llamamos al método fit en el modelo y le pasamos nuestras características y etiquetas de entrenamiento como se muestra a continuación:

1
model.fit(features_set, labels, epochs = 100, batch_size = 32)

Dependiendo de su hardware, el entrenamiento del modelo puede llevar algún tiempo.

Probando nuestro LSTM

Hemos entrenado con éxito nuestro LSTM, ahora es el momento de probar el rendimiento de nuestro algoritmo en el conjunto de prueba al predecir los precios de apertura de las acciones para el mes de enero de 2018. Sin embargo, como hicimos con los datos de entrenamiento, necesitamos convertir nuestro datos de prueba en el formato correcto.

Primero importemos nuestros datos de prueba. Ejecute el siguiente script:

1
2
apple_testing_complete = pd.read_csv(r'E:\Datasets\apple_testing.csv')
apple_testing_processed = apple_testing_complete.iloc[:, 1:2].values

En el script anterior, importamos nuestros datos de prueba y, como hicimos con los datos de entrenamiento, eliminamos todas las columnas de los datos de prueba excepto la columna que contiene los precios de las acciones de apertura.

Si los precios de las acciones de apertura para el mes de enero de 2018 se comparan con las fechas, debería ver el siguiente gráfico.

{.img-responsive}

Puede ver que la tendencia es altamente no lineal. En general, los precios de las acciones experimentan un pequeño aumento a principios de mes seguido de una tendencia a la baja al final del mes, con un ligero aumento y una disminución en los precios de las acciones en el medio. Es extremadamente difícil pronosticar tal tendencia. Veamos si el LSTM que entrenamos es realmente capaz de predecir tal tendencia.

Conversión de datos de prueba al formato correcto

Para cada día de enero de 2018, queremos que nuestro conjunto de características contenga los precios de apertura de las acciones de los 60 días anteriores. Para el 1 de enero, necesitamos los precios de las acciones de los 60 días anteriores. Para hacerlo, necesitamos concatenar nuestros datos de entrenamiento y datos de prueba antes del preprocesamiento. Ejecute el siguiente script para hacerlo:

1
apple_total = pd.concat((apple_training_complete['Open'], apple_testing_complete['Open']), axis=0)

Ahora preparemos nuestras entradas de prueba. La entrada para cada día debe contener los precios de apertura de las acciones de los 60 días anteriores. Eso significa que necesitamos los precios de las acciones de apertura para los 20 días de prueba del mes de enero de 2018 y los 60 precios de las acciones de los últimos 60 días para el conjunto de entrenamiento. Ejecute el siguiente script para obtener esos 80 valores.

1
test_inputs = apple_total[len(apple_total) - len(apple_testing_complete) - 60:].values

Como hicimos con el conjunto de entrenamiento, necesitamos escalar nuestros datos de prueba. Ejecute el siguiente script:

1
2
test_inputs = test_inputs.reshape(-1,1)
test_inputs = scaler.transform(test_inputs)

Escalamos nuestros datos, ahora preparemos nuestro conjunto de entrada de prueba final que contendrá los 60 precios de acciones anteriores para el mes de enero. Ejecute el siguiente script:

1
2
3
test_features = []
for i in range(60, 80):
    test_features.append(test_inputs[i-60:i, 0])

Finalmente, necesitamos convertir nuestros datos al formato tridimensional que se puede usar como entrada para el LSTM. Ejecute el siguiente script:

1
2
test_features = np.array(test_features)
test_features = np.reshape(test_features, (test_features.shape[0], test_features.shape[1], 1))
Hacer predicciones

Ahora es el momento de ver la magia. Preprocesamos nuestros datos de prueba y ahora podemos usarlos para hacer predicciones. Para hacerlo, simplemente necesitamos llamar al método predecir en el modelo que entrenamos. Ejecute el siguiente script:

1
predictions = model.predict(test_features)

Dado que escalamos nuestros datos, las predicciones realizadas por el LSTM también se escalan. Necesitamos revertir la predicción escalada a sus valores reales. Para hacerlo, podemos usar el método ìnverse_transform del objeto escalador que creamos durante el entrenamiento. Echa un vistazo al siguiente script:

1
predictions = scaler.inverse_transform(predictions)

Finalmente, veamos qué tan bien predijo nuestro algoritmo los precios futuros de las acciones. Ejecute el siguiente script:

1
2
3
4
5
6
7
8
plt.figure(figsize=(10,6))
plt.plot(apple_testing_processed, color='blue', label='Actual Apple Stock Price')
plt.plot(predictions , color='red', label='Predicted Apple Stock Price')
plt.title('Apple Stock Price Prediction')
plt.xlabel('Date')
plt.ylabel('Apple Stock Price')
plt.legend()
plt.show()

La salida se ve así:

{.img-responsive}

En el resultado, la línea azul representa los precios de las acciones reales para el mes de enero de 2018, mientras que la línea roja representa los precios de las acciones pronosticados. Puede ver claramente que nuestro algoritmo ha podido capturar la tendencia general. Los precios pronosticados también ven una tendencia alcista al principio seguida de una tendencia bajista o bajista al final. Increíble, ¿no?

Conclusión

Una red de memoria larga a corto plazo (LSTM) es una de las redes neuronales más utilizadas para el análisis de series temporales. La capacidad de LSTM para recordar información previa lo hace ideal para tales tareas. En este artículo, vimos cómo podemos usar LSTM para la predicción del precio de las acciones de Apple. Le sugiero que descargue acciones de alguna otra organización como Google o Microsoft de Yahoo Finance y vea si su algoritmo es capaz de capturar las tendencias.