Predicción del valor de una acción a tres días. Apple (LSTM)#

Importar las librería requeridas#

import tensorflow as tf

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#%matplotlib inline
from sklearn.preprocessing import MinMaxScaler

#setting figure size
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = 20,10

#importing required libraries
from sklearn.preprocessing import MinMaxScaler

# importa objetos de keras
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense, Dropout, LSTM
print("Versión de Tensorflow: ", tf.__version__)

# optimizador
from tensorflow.keras.optimizers import Adam
Versión de Tensorflow:  2.9.1

Lectura de los datos#

Estos datos corresponden a la empresa Apple. Son 3019 datos que corresponden a observaciones del precio de la acción, el número de transacciones de la acción (compra-venta). Los datos son diarios (dias hábiles o comerciales). Están entre el 3 de enero de 2006 hasta el 1 de enero de 2018.

la columna Date es la fecha, Open es el valor de acción a la apertura del mercado, High el valor más alto alcanzado en el día, Low el valor más bajo del día, Close el valor al cierre, Volume es el volúmenes de acciones transadas en el día y Name es el código de identificación de la empresa, Apple en este caso.

Los datos puede ser bajados directamente de Kaggle

#reading from a local file

df = pd.read_csv('https://raw.githubusercontent.com/AprendizajeProfundo/Libro-Fundamentos/main/Redes_Recurrentes/Datos/AAPL_2006-01-01_to_2018-01-01.csv')
# looking at the first five rows of the data
print('\n Shape of the data:')
print(df.shape)
df.head()
 Shape of the data:
(3019, 7)
Date Open High Low Close Volume Name
0 2006-01-03 10.34 10.68 10.32 10.68 201853036 AAPL
1 2006-01-04 10.73 10.85 10.64 10.71 155225609 AAPL
2 2006-01-05 10.69 10.70 10.54 10.63 112396081 AAPL
3 2006-01-06 10.75 10.96 10.65 10.90 176139334 AAPL
4 2006-01-09 10.96 11.03 10.82 10.86 168861224 AAPL

Vamos a cambiar el índice de los datos. Tomaremos la fecha como indice: df.index. Los datos se reordenan para invertir la tabla, debido a que los datos contienen las observaciones más recientes en la parte superior de la tabla.

Extrae datos para la serie que se desea predecir-close#

#creating dataframe with date and the target variable

df['Date'] = pd.to_datetime(df.Date,format='%Y-%m-%d')
df.index = df['Date']
# df = df.sort_index(ascending=True, axis=0)
data = pd.DataFrame(df[['Date', 'Close']])
#
#setting index
data.index = data.Date
data.drop('Date', axis=1, inplace=True)
data.head()
Close
Date
2006-01-03 10.68
2006-01-04 10.71
2006-01-05 10.63
2006-01-06 10.90
2006-01-09 10.86

Visualización de la serie precio al cierre#

# plot
len_data = len(data)
len_train = int(len_data*0.8) # 80%  = 3019
len_test = len_data- len_train # 20% = 2415
print (len_data, '=', len_train, '+',len_test)
3019 = 2415 + 604
plt.figure(figsize=(16,8))
plt.plot(data[:len_train], label='Conjunto de entrenamiento (Training set): {} puntos (80%)'.format(len_train))
plt.plot(data['Close'][len_train:], label='Conjunto de validación (Validation set): {} puntos (20%)'.format(len_test)) #248 data
plt.title("Apple: Historia del precio la acción al cierre (Close)", size = 20)
plt.legend()
plt.show()
../../_images/rnr_accion_Apple_Prediccion_tres_dias-dropout_12_0.png

Preparación de los datos para el entrenamiento de la red LSTM#

Para evitar problemas con las tendencias y para mejorar la estimación (entrenamiento) los datos se van a transformar a la escala \([0,1]\). Para las predicciones se utiliza la transformación inversa.

Primero extrae los valores y se crea el objeto MinMaxScaler#

#creating train and test sets
dataset = data.values


# create the scaler object and scale the data
scaler = MinMaxScaler(feature_range=(0, 1))
#scaled_data = np.array(scaler.fit_transform(dataset))
dataset = np.squeeze(np.array(scaler.fit_transform(dataset)),axis=1)
# dataset = pd.DataFrame(scaled_data,index=data.index, columns=['serie'])
dataset.shape
(3019,)

Crea datos de entrenamiento#

La red LSTM tendrá como entrada «time_step» datos consecutivos, y como salida 5 datos (la predicción a partir de esos «time_step» datos se hace para los siguentes 5 días). Se conformará de esta forma el set de entrenamiento

  1. Número de datos consecutivos para entrenamiento: time_step = 60.

  2. Días a predecir: days = 1

Función para crear los datos de entrenamiento#

def univariate_data(dataset, start_index, end_index, history_size, target_size):
    ''' dataset: conjunto de datos
        start_index: índice inicial de donde empezar a tomar los datos
        end_index: índice final para tomar los datos. None para tomarlos todos
        history_size: tamaño de la venytana para crear las secuencias
        target_size: dentro de cuántas observaciones futuras desea pronosticar
    '''  
    data = []
    labels = []

    start_index = start_index + history_size
    if end_index is None:
        end_index = len(dataset) - target_size

    for i in range(start_index, end_index):
        indices = range(i-history_size, i)
        # Reshape data from (history_size,) to (history_size, 1)
        data.append(np.reshape(dataset[indices], (history_size, 1)))
        labels.append(dataset[i+target_size])

    return np.array(data), np.array(labels)

Se coloca una semilla para gerantizar reproductibidad

tf.random.set_seed(100)
#
# hiperparámetros para crear las secuencias
past_history = 60 # tamaño secuencias de entrada
future_target = 3 # días adelante
TRAIN_SPLIT = int(len_data*0.8) #2415: nuḿer0 de datos entreno

# secuencias de entrenamiento
X_train, y_train = univariate_data(dataset, 0, TRAIN_SPLIT,
                                           past_history,
                                           future_target)
#
#secuencias de validación
# No se usará ningún dato que el modelo haya visto
X_test, y_test = univariate_data(dataset, TRAIN_SPLIT, None,
                                       past_history,
                                       future_target)

print(TRAIN_SPLIT)
print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)
2415
(2355, 60, 1)
(2355,)
(541, 60, 1)
(541,)

Crea el modelo LSTM#

Omitimos esta sección. Usaremso el modelo entrenado a un día

# shapes
input_shape = (X_train.shape[1], X_train.shape[2])
units = 64

# layers
inputs = Input(input_shape)
#x = Dropout(0.0, name= 'Dropout_01')(inputs)
#x = LSTM(units=units, name='LSTM_layer')(x)
x = LSTM(units=units, return_sequences=True,name='LSTM_layer')(inputs)
x = Dropout(0.4, name= 'Dropout_02')(x)
x = LSTM(units=units//2, name='LSTM_layer_2')(x)
x = Dropout(0.4, name= 'Dropout_03')(x)
outputs = Dense(1)(x)

# model
model_01 = Model(inputs=inputs, outputs=outputs, name='series_LSTM_model')
model_01.summary()
Model: "series_LSTM_model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 60, 1)]           0         
                                                                 
 LSTM_layer (LSTM)           (None, 60, 64)            16896     
                                                                 
 Dropout_02 (Dropout)        (None, 60, 64)            0         
                                                                 
 LSTM_layer_2 (LSTM)         (None, 32)                12416     
                                                                 
 Dropout_03 (Dropout)        (None, 32)                0         
                                                                 
 dense (Dense)               (None, 1)                 33        
                                                                 
=================================================================
Total params: 29,345
Trainable params: 29,345
Non-trainable params: 0
_________________________________________________________________

Compila#

Se usará el optimizador Adam y la función de pérdida MSE

model_01.compile(loss='mean_squared_error',
  optimizer=Adam(0.001))

Entrena el modelo#

#history = model_01.fit(X_train,y_train,epochs=20,batch_size=32)
tf.random.set_seed(100)
history = model_01.fit(
    X_train, y_train,
    epochs=15,
    batch_size=32,
    validation_split=0.1,
    verbose=1,
    shuffle=False
)
Epoch 1/15
 1/67 [..............................] - ETA: 7:44 - loss: 2.4157e-04

 2/67 [..............................] - ETA: 5s - loss: 1.4562e-04  

 3/67 [>.............................] - ETA: 4s - loss: 1.2524e-04

 4/67 [>.............................] - ETA: 4s - loss: 1.0101e-04

 5/67 [=>............................] - ETA: 4s - loss: 9.9967e-05

 6/67 [=>............................] - ETA: 4s - loss: 1.1648e-04

 7/67 [==>...........................] - ETA: 3s - loss: 1.1462e-04

 8/67 [==>...........................] - ETA: 3s - loss: 1.0868e-04

 9/67 [===>..........................] - ETA: 3s - loss: 1.1215e-04

10/67 [===>..........................] - ETA: 3s - loss: 1.2017e-04

11/67 [===>..........................] - ETA: 3s - loss: 1.3608e-04

12/67 [====>.........................] - ETA: 3s - loss: 1.5585e-04

13/67 [====>.........................] - ETA: 3s - loss: 2.0753e-04

14/67 [=====>........................] - ETA: 3s - loss: 2.1871e-04

15/67 [=====>........................] - ETA: 3s - loss: 3.1331e-04

16/67 [======>.......................] - ETA: 3s - loss: 3.2149e-04

18/67 [=======>......................] - ETA: 3s - loss: 3.8504e-04

19/67 [=======>......................] - ETA: 3s - loss: 3.9329e-04

20/67 [=======>......................] - ETA: 3s - loss: 4.2395e-04

21/67 [========>.....................] - ETA: 2s - loss: 4.5621e-04

22/67 [========>.....................] - ETA: 2s - loss: 4.9952e-04

23/67 [=========>....................] - ETA: 2s - loss: 5.0137e-04

24/67 [=========>....................] - ETA: 2s - loss: 4.8637e-04

25/67 [==========>...................] - ETA: 2s - loss: 4.8661e-04

26/67 [==========>...................] - ETA: 2s - loss: 5.1376e-04

27/67 [===========>..................] - ETA: 2s - loss: 6.0306e-04

28/67 [===========>..................] - ETA: 2s - loss: 7.3945e-04

29/67 [===========>..................] - ETA: 2s - loss: 8.4674e-04

30/67 [============>.................] - ETA: 2s - loss: 9.2930e-04

31/67 [============>.................] - ETA: 2s - loss: 9.6262e-04

32/67 [=============>................] - ETA: 2s - loss: 0.0010    

33/67 [=============>................] - ETA: 2s - loss: 0.0011

34/67 [==============>...............] - ETA: 2s - loss: 0.0011

35/67 [==============>...............] - ETA: 2s - loss: 0.0011

36/67 [===============>..............] - ETA: 1s - loss: 0.0011

37/67 [===============>..............] - ETA: 1s - loss: 0.0012

38/67 [================>.............] - ETA: 1s - loss: 0.0012

39/67 [================>.............] - ETA: 1s - loss: 0.0013

40/67 [================>.............] - ETA: 1s - loss: 0.0013

41/67 [=================>............] - ETA: 1s - loss: 0.0013

42/67 [=================>............] - ETA: 1s - loss: 0.0014

43/67 [==================>...........] - ETA: 1s - loss: 0.0015

44/67 [==================>...........] - ETA: 1s - loss: 0.0015

45/67 [===================>..........] - ETA: 1s - loss: 0.0016

46/67 [===================>..........] - ETA: 1s - loss: 0.0016

47/67 [====================>.........] - ETA: 1s - loss: 0.0017

48/67 [====================>.........] - ETA: 1s - loss: 0.0018

49/67 [====================>.........] - ETA: 1s - loss: 0.0019

50/67 [=====================>........] - ETA: 1s - loss: 0.0020

51/67 [=====================>........] - ETA: 1s - loss: 0.0022

52/67 [======================>.......] - ETA: 0s - loss: 0.0023

53/67 [======================>.......] - ETA: 0s - loss: 0.0026

54/67 [=======================>......] - ETA: 0s - loss: 0.0026

55/67 [=======================>......] - ETA: 0s - loss: 0.0027

56/67 [========================>.....] - ETA: 0s - loss: 0.0027

57/67 [========================>.....] - ETA: 0s - loss: 0.0027

58/67 [========================>.....] - ETA: 0s - loss: 0.0027

60/67 [=========================>....] - ETA: 0s - loss: 0.0030

61/67 [==========================>...] - ETA: 0s - loss: 0.0032

62/67 [==========================>...] - ETA: 0s - loss: 0.0033

63/67 [===========================>..] - ETA: 0s - loss: 0.0034

64/67 [===========================>..] - ETA: 0s - loss: 0.0034

65/67 [============================>.] - ETA: 0s - loss: 0.0035

66/67 [============================>.] - ETA: 0s - loss: 0.0036

67/67 [==============================] - ETA: 0s - loss: 0.0036

67/67 [==============================] - 13s 98ms/step - loss: 0.0036 - val_loss: 0.0017
Epoch 2/15
 1/67 [..............................] - ETA: 5s - loss: 0.0616

 2/67 [..............................] - ETA: 4s - loss: 0.0603

 3/67 [>.............................] - ETA: 4s - loss: 0.0552

 4/67 [>.............................] - ETA: 3s - loss: 0.0490

 5/67 [=>............................] - ETA: 3s - loss: 0.0435

 6/67 [=>............................] - ETA: 3s - loss: 0.0383

 7/67 [==>...........................] - ETA: 3s - loss: 0.0339

 8/67 [==>...........................] - ETA: 3s - loss: 0.0300

 9/67 [===>..........................] - ETA: 3s - loss: 0.0268

10/67 [===>..........................] - ETA: 3s - loss: 0.0242

11/67 [===>..........................] - ETA: 3s - loss: 0.0220

12/67 [====>.........................] - ETA: 3s - loss: 0.0204

13/67 [====>.........................] - ETA: 3s - loss: 0.0193

14/67 [=====>........................] - ETA: 3s - loss: 0.0184

15/67 [=====>........................] - ETA: 3s - loss: 0.0173

16/67 [======>.......................] - ETA: 3s - loss: 0.0165

17/67 [======>.......................] - ETA: 3s - loss: 0.0159

18/67 [=======>......................] - ETA: 3s - loss: 0.0153

19/67 [=======>......................] - ETA: 3s - loss: 0.0148

20/67 [=======>......................] - ETA: 2s - loss: 0.0141

21/67 [========>.....................] - ETA: 2s - loss: 0.0135

22/67 [========>.....................] - ETA: 2s - loss: 0.0129

23/67 [=========>....................] - ETA: 2s - loss: 0.0123

24/67 [=========>....................] - ETA: 2s - loss: 0.0118

25/67 [==========>...................] - ETA: 2s - loss: 0.0114

26/67 [==========>...................] - ETA: 2s - loss: 0.0110

27/67 [===========>..................] - ETA: 2s - loss: 0.0106

28/67 [===========>..................] - ETA: 2s - loss: 0.0103

29/67 [===========>..................] - ETA: 2s - loss: 0.0100

30/67 [============>.................] - ETA: 2s - loss: 0.0098

31/67 [============>.................] - ETA: 2s - loss: 0.0095

32/67 [=============>................] - ETA: 2s - loss: 0.0094

33/67 [=============>................] - ETA: 2s - loss: 0.0092

34/67 [==============>...............] - ETA: 2s - loss: 0.0090

35/67 [==============>...............] - ETA: 2s - loss: 0.0089

36/67 [===============>..............] - ETA: 2s - loss: 0.0087

37/67 [===============>..............] - ETA: 2s - loss: 0.0086

38/67 [================>.............] - ETA: 2s - loss: 0.0085

39/67 [================>.............] - ETA: 2s - loss: 0.0084

40/67 [================>.............] - ETA: 2s - loss: 0.0082

41/67 [=================>............] - ETA: 2s - loss: 0.0081

42/67 [=================>............] - ETA: 2s - loss: 0.0080

43/67 [==================>...........] - ETA: 2s - loss: 0.0078

44/67 [==================>...........] - ETA: 1s - loss: 0.0078

45/67 [===================>..........] - ETA: 1s - loss: 0.0077

46/67 [===================>..........] - ETA: 1s - loss: 0.0076

47/67 [====================>.........] - ETA: 1s - loss: 0.0076

48/67 [====================>.........] - ETA: 1s - loss: 0.0077

49/67 [====================>.........] - ETA: 1s - loss: 0.0077

50/67 [=====================>........] - ETA: 1s - loss: 0.0077

51/67 [=====================>........] - ETA: 1s - loss: 0.0078

52/67 [======================>.......] - ETA: 1s - loss: 0.0078

53/67 [======================>.......] - ETA: 1s - loss: 0.0079

54/67 [=======================>......] - ETA: 1s - loss: 0.0080

55/67 [=======================>......] - ETA: 1s - loss: 0.0079

56/67 [========================>.....] - ETA: 0s - loss: 0.0079

57/67 [========================>.....] - ETA: 0s - loss: 0.0078

58/67 [========================>.....] - ETA: 0s - loss: 0.0078

59/67 [=========================>....] - ETA: 0s - loss: 0.0077

60/67 [=========================>....] - ETA: 0s - loss: 0.0078

61/67 [==========================>...] - ETA: 0s - loss: 0.0079

62/67 [==========================>...] - ETA: 0s - loss: 0.0081

63/67 [===========================>..] - ETA: 0s - loss: 0.0081

64/67 [===========================>..] - ETA: 0s - loss: 0.0082

65/67 [============================>.] - ETA: 0s - loss: 0.0083

66/67 [============================>.] - ETA: 0s - loss: 0.0083

67/67 [==============================] - ETA: 0s - loss: 0.0083

67/67 [==============================] - 6s 91ms/step - loss: 0.0083 - val_loss: 0.0022
Epoch 3/15
 1/67 [..............................] - ETA: 7s - loss: 0.0553

 2/67 [..............................] - ETA: 6s - loss: 0.0567

 3/67 [>.............................] - ETA: 6s - loss: 0.0547

 4/67 [>.............................] - ETA: 5s - loss: 0.0518

 5/67 [=>............................] - ETA: 5s - loss: 0.0475

 6/67 [=>............................] - ETA: 5s - loss: 0.0439

 7/67 [==>...........................] - ETA: 5s - loss: 0.0396

 8/67 [==>...........................] - ETA: 5s - loss: 0.0357

 9/67 [===>..........................] - ETA: 5s - loss: 0.0322

10/67 [===>..........................] - ETA: 5s - loss: 0.0292

11/67 [===>..........................] - ETA: 5s - loss: 0.0266

12/67 [====>.........................] - ETA: 5s - loss: 0.0244

13/67 [====>.........................] - ETA: 5s - loss: 0.0226

14/67 [=====>........................] - ETA: 5s - loss: 0.0211

15/67 [=====>........................] - ETA: 5s - loss: 0.0197

16/67 [======>.......................] - ETA: 5s - loss: 0.0186

17/67 [======>.......................] - ETA: 5s - loss: 0.0177

18/67 [=======>......................] - ETA: 5s - loss: 0.0169

19/67 [=======>......................] - ETA: 5s - loss: 0.0162

20/67 [=======>......................] - ETA: 4s - loss: 0.0154

21/67 [========>.....................] - ETA: 4s - loss: 0.0147

22/67 [========>.....................] - ETA: 4s - loss: 0.0141

23/67 [=========>....................] - ETA: 4s - loss: 0.0135

24/67 [=========>....................] - ETA: 4s - loss: 0.0130

25/67 [==========>...................] - ETA: 4s - loss: 0.0126

26/67 [==========>...................] - ETA: 4s - loss: 0.0122

27/67 [===========>..................] - ETA: 4s - loss: 0.0118

28/67 [===========>..................] - ETA: 4s - loss: 0.0115

29/67 [===========>..................] - ETA: 4s - loss: 0.0112

30/67 [============>.................] - ETA: 4s - loss: 0.0109

31/67 [============>.................] - ETA: 3s - loss: 0.0106

32/67 [=============>................] - ETA: 3s - loss: 0.0104

33/67 [=============>................] - ETA: 3s - loss: 0.0102

34/67 [==============>...............] - ETA: 3s - loss: 0.0100

35/67 [==============>...............] - ETA: 3s - loss: 0.0097

36/67 [===============>..............] - ETA: 3s - loss: 0.0096

37/67 [===============>..............] - ETA: 3s - loss: 0.0095

38/67 [================>.............] - ETA: 3s - loss: 0.0093

39/67 [================>.............] - ETA: 3s - loss: 0.0091

40/67 [================>.............] - ETA: 3s - loss: 0.0090

41/67 [=================>............] - ETA: 2s - loss: 0.0088

42/67 [=================>............] - ETA: 2s - loss: 0.0086

43/67 [==================>...........] - ETA: 2s - loss: 0.0085

44/67 [==================>...........] - ETA: 2s - loss: 0.0083

45/67 [===================>..........] - ETA: 2s - loss: 0.0082

46/67 [===================>..........] - ETA: 2s - loss: 0.0081

47/67 [====================>.........] - ETA: 2s - loss: 0.0081

48/67 [====================>.........] - ETA: 2s - loss: 0.0081

49/67 [====================>.........] - ETA: 1s - loss: 0.0080

50/67 [=====================>........] - ETA: 1s - loss: 0.0080

51/67 [=====================>........] - ETA: 1s - loss: 0.0080

52/67 [======================>.......] - ETA: 1s - loss: 0.0081

53/67 [======================>.......] - ETA: 1s - loss: 0.0081

54/67 [=======================>......] - ETA: 1s - loss: 0.0081

55/67 [=======================>......] - ETA: 1s - loss: 0.0081

56/67 [========================>.....] - ETA: 1s - loss: 0.0080

57/67 [========================>.....] - ETA: 1s - loss: 0.0079

58/67 [========================>.....] - ETA: 0s - loss: 0.0078

59/67 [=========================>....] - ETA: 0s - loss: 0.0078

60/67 [=========================>....] - ETA: 0s - loss: 0.0077

61/67 [==========================>...] - ETA: 0s - loss: 0.0078

62/67 [==========================>...] - ETA: 0s - loss: 0.0078

63/67 [===========================>..] - ETA: 0s - loss: 0.0078

64/67 [===========================>..] - ETA: 0s - loss: 0.0079

65/67 [============================>.] - ETA: 0s - loss: 0.0079

66/67 [============================>.] - ETA: 0s - loss: 0.0079

67/67 [==============================] - ETA: 0s - loss: 0.0080

67/67 [==============================] - 7s 106ms/step - loss: 0.0080 - val_loss: 0.0045
Epoch 4/15
 1/67 [..............................] - ETA: 6s - loss: 0.0180

 2/67 [..............................] - ETA: 5s - loss: 0.0195

 3/67 [>.............................] - ETA: 5s - loss: 0.0199

 4/67 [>.............................] - ETA: 5s - loss: 0.0194

 5/67 [=>............................] - ETA: 5s - loss: 0.0189

 6/67 [=>............................] - ETA: 4s - loss: 0.0180

 7/67 [==>...........................] - ETA: 4s - loss: 0.0170

 8/67 [==>...........................] - ETA: 4s - loss: 0.0158

 9/67 [===>..........................] - ETA: 4s - loss: 0.0145

10/67 [===>..........................] - ETA: 4s - loss: 0.0134

11/67 [===>..........................] - ETA: 4s - loss: 0.0123

12/67 [====>.........................] - ETA: 4s - loss: 0.0113

13/67 [====>.........................] - ETA: 4s - loss: 0.0105

14/67 [=====>........................] - ETA: 4s - loss: 0.0098

15/67 [=====>........................] - ETA: 3s - loss: 0.0092

16/67 [======>.......................] - ETA: 3s - loss: 0.0087

17/67 [======>.......................] - ETA: 3s - loss: 0.0083

18/67 [=======>......................] - ETA: 3s - loss: 0.0079

19/67 [=======>......................] - ETA: 3s - loss: 0.0076

20/67 [=======>......................] - ETA: 3s - loss: 0.0072

21/67 [========>.....................] - ETA: 3s - loss: 0.0071

22/67 [========>.....................] - ETA: 3s - loss: 0.0069

23/67 [=========>....................] - ETA: 3s - loss: 0.0067

24/67 [=========>....................] - ETA: 3s - loss: 0.0066

25/67 [==========>...................] - ETA: 3s - loss: 0.0064

26/67 [==========>...................] - ETA: 2s - loss: 0.0062

27/67 [===========>..................] - ETA: 2s - loss: 0.0060

28/67 [===========>..................] - ETA: 2s - loss: 0.0058

29/67 [===========>..................] - ETA: 2s - loss: 0.0056

30/67 [============>.................] - ETA: 2s - loss: 0.0054

31/67 [============>.................] - ETA: 2s - loss: 0.0053

32/67 [=============>................] - ETA: 2s - loss: 0.0051

33/67 [=============>................] - ETA: 2s - loss: 0.0050

34/67 [==============>...............] - ETA: 2s - loss: 0.0049

35/67 [==============>...............] - ETA: 2s - loss: 0.0048

36/67 [===============>..............] - ETA: 2s - loss: 0.0047

37/67 [===============>..............] - ETA: 2s - loss: 0.0046

39/67 [================>.............] - ETA: 1s - loss: 0.0044

40/67 [================>.............] - ETA: 1s - loss: 0.0043

41/67 [=================>............] - ETA: 1s - loss: 0.0043

42/67 [=================>............] - ETA: 1s - loss: 0.0042

43/67 [==================>...........] - ETA: 1s - loss: 0.0042

44/67 [==================>...........] - ETA: 1s - loss: 0.0041

45/67 [===================>..........] - ETA: 1s - loss: 0.0041

46/67 [===================>..........] - ETA: 1s - loss: 0.0040
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='test')
plt.legend();
../../_images/rnr_accion_Apple_Prediccion_tres_dias-dropout_33_0.png

Predicciones#

Prepara los datos de validación#

X_test.shape
(541, 60, 1)

Calcula predicciones#

# predictions
prediction = model_01.predict(X_test)
#prediction = scaler.inverse_transform(prediction)
17/17 [==============================] - 2s 18ms/step
print(prediction.shape)
print(y_test.shape)
(541, 1)
(541,)

Elimina dimensiones sobrante para los gráficos#

y_train_p = y_train# np.squeeze(y_train, axis=-1)
y_test_p = y_test #np.squeeze(y_test, axis=-1)
y_pred_p = np.squeeze(prediction, axis=-1)
print(y_train_p.shape)
print(y_test_p.shape)
print(y_pred_p.shape)

k=0
for i,j in zip(y_test_p, y_pred_p):
    print (i,j, i-j)
    k+=1
    if k==10:
        break
(2355,)
(541,)
(541,)
0.6727745596406196 0.64994586 0.022828704499933572
0.6698782361981322 0.6543955 0.015482715511028977
0.6474169523584349 0.6584121 -0.010995146526147637
0.6435157820073296 0.6614015 -0.017885728231317843
0.6412105449816764 0.66360754 -0.022396992764753043
0.6212318240926825 0.664968 -0.04373618967074522
0.6321078141624307 0.664171 -0.03206316629106054
0.6292114907199433 0.66194737 -0.03273587885555718
0.6504906017259725 0.65891695 -0.008426348499857572
0.6592977893368012 0.6542779 0.00501986861383974

Gráfica de las predicciones#

plt.plot(np.arange(0, len(y_train_p)), y_train_p, 'g', label="historia")
plt.plot(np.arange(len(y_train_p), len(y_train_p) + len(y_test_p)), y_test_p, marker='.', label="verdadero")
plt.plot(np.arange(len(y_train_p), len(y_train_p) + len(y_test_p)), y_pred_p, 'r', label="predicción")
#plt.ylabel('Valor')
plt.xlabel('Time Step')
plt.title("Apple: Historia del precio la acción al cierre. Escala (0,1)", size = 20)
plt.legend()
plt.show();
../../_images/rnr_accion_Apple_Prediccion_tres_dias-dropout_44_0.png

Regreso a la escala original#

y_pred_or = scaler.inverse_transform(y_pred_p.reshape(-1,1))
y_test_or = scaler.inverse_transform(y_test_p.reshape(-1,1))
k=0
for i,j in zip(y_test_or, y_pred_or):
    print (i,j, i-j)
    k+=1
    if k==10:
        break
[121.06] [117.19784] [3.86216217]
[120.57] [117.95063] [2.61936981]
[116.77] [118.63016] [-1.86015747]
[116.11] [119.1359] [-3.0259024]
[115.72] [119.509125] [-3.78912476]
[112.34] [119.73929] [-7.39928833]
[114.18] [119.60445] [-5.42444641]
[113.69] [119.22826] [-5.53825623]
[117.29] [118.71557] [-1.42556854]
[118.78] [117.93074] [0.84925964]
rmsLSTM = np.sqrt(np.mean(np.power(y_pred_or-y_test_or,2)))
print(rmsLSTM )
8.170484800047866
plt.plot(np.arange(0, len(y_test_or)), y_test_or, marker='.', label="verdadero")
plt.plot(np.arange(0, len(y_test_or)), y_pred_or, marker='+', label="predicho")
plt.xlabel('Time Step')
plt.annotate("rms = "+str(round(rmsLSTM,2)) , xy=(100, 140), size = 15)
plt.annotate("modelo = LSTM(50), timestep=60" , xy=(100, 146), size = 15)
plt.annotate("epochs=40" , xy=(100, 143), size = 15)
plt.title("Apple: Intervalo de predicción a tres días. Escala original", size = 20)
plt.legend()
plt.show();
../../_images/rnr_accion_Apple_Prediccion_tres_dias-dropout_49_0.png

Guarda el modelo entrenado#

model_01.save('../Datos/modelo_Apple_3_dia.h5')

Intervalos de confianza. TO DO#

model_01.get_config()
{'name': 'series_LSTM_model',
 'layers': [{'class_name': 'InputLayer',
   'config': {'batch_input_shape': (None, 60, 1),
    'dtype': 'float32',
    'sparse': False,
    'ragged': False,
    'name': 'input_1'},
   'name': 'input_1',
   'inbound_nodes': []},
  {'class_name': 'LSTM',
   'config': {'name': 'LSTM_layer',
    'trainable': True,
    'dtype': 'float32',
    'return_sequences': True,
    'return_state': False,
    'go_backwards': False,
    'stateful': False,
    'unroll': False,
    'time_major': False,
    'units': 64,
    'activation': 'tanh',
    'recurrent_activation': 'sigmoid',
    'use_bias': True,
    'kernel_initializer': {'class_name': 'GlorotUniform',
     'config': {'seed': None},
     'shared_object_id': 1},
    'recurrent_initializer': {'class_name': 'Orthogonal',
     'config': {'gain': 1.0, 'seed': None},
     'shared_object_id': 2},
    'bias_initializer': {'class_name': 'Zeros',
     'config': {},
     'shared_object_id': 3},
    'unit_forget_bias': True,
    'kernel_regularizer': None,
    'recurrent_regularizer': None,
    'bias_regularizer': None,
    'activity_regularizer': None,
    'kernel_constraint': None,
    'recurrent_constraint': None,
    'bias_constraint': None,
    'dropout': 0.0,
    'recurrent_dropout': 0.0,
    'implementation': 2},
   'name': 'LSTM_layer',
   'inbound_nodes': [[['input_1', 0, 0, {}]]]},
  {'class_name': 'Dropout',
   'config': {'name': 'Dropout_02',
    'trainable': True,
    'dtype': 'float32',
    'rate': 0.4,
    'noise_shape': None,
    'seed': None},
   'name': 'Dropout_02',
   'inbound_nodes': [[['LSTM_layer', 0, 0, {}]]]},
  {'class_name': 'LSTM',
   'config': {'name': 'LSTM_layer_2',
    'trainable': True,
    'dtype': 'float32',
    'return_sequences': False,
    'return_state': False,
    'go_backwards': False,
    'stateful': False,
    'unroll': False,
    'time_major': False,
    'units': 32,
    'activation': 'tanh',
    'recurrent_activation': 'sigmoid',
    'use_bias': True,
    'kernel_initializer': {'class_name': 'GlorotUniform',
     'config': {'seed': None},
     'shared_object_id': 7},
    'recurrent_initializer': {'class_name': 'Orthogonal',
     'config': {'gain': 1.0, 'seed': None},
     'shared_object_id': 8},
    'bias_initializer': {'class_name': 'Zeros',
     'config': {},
     'shared_object_id': 9},
    'unit_forget_bias': True,
    'kernel_regularizer': None,
    'recurrent_regularizer': None,
    'bias_regularizer': None,
    'activity_regularizer': None,
    'kernel_constraint': None,
    'recurrent_constraint': None,
    'bias_constraint': None,
    'dropout': 0.0,
    'recurrent_dropout': 0.0,
    'implementation': 2},
   'name': 'LSTM_layer_2',
   'inbound_nodes': [[['Dropout_02', 0, 0, {}]]]},
  {'class_name': 'Dropout',
   'config': {'name': 'Dropout_03',
    'trainable': True,
    'dtype': 'float32',
    'rate': 0.4,
    'noise_shape': None,
    'seed': None},
   'name': 'Dropout_03',
   'inbound_nodes': [[['LSTM_layer_2', 0, 0, {}]]]},
  {'class_name': 'Dense',
   'config': {'name': 'dense',
    'trainable': True,
    'dtype': 'float32',
    'units': 1,
    'activation': 'linear',
    'use_bias': True,
    'kernel_initializer': {'class_name': 'GlorotUniform',
     'config': {'seed': None}},
    'bias_initializer': {'class_name': 'Zeros', 'config': {}},
    'kernel_regularizer': None,
    'bias_regularizer': None,
    'activity_regularizer': None,
    'kernel_constraint': None,
    'bias_constraint': None},
   'name': 'dense',
   'inbound_nodes': [[['Dropout_03', 0, 0, {}]]]}],
 'input_layers': [['input_1', 0, 0]],
 'output_layers': [['dense', 0, 0]]}

Referencias#

  1. Introducción a Redes LSTM

  2. Time Series Forecasting with LSTMs using TensorFlow 2 and Keras in Python

  3. Dive into Deep Learnig

  4. Understanding LSTM Networks

  5. Ralf C. Staudemeyer and Eric Rothstein Morris,Understanding LSTM a tutorial into Long Short-Term Memory Recurrent Neural Networks, arxiv, September 2019

  6. Karpathy, The Unreasonable Effectiveness of Recurrent Neural Networks

  7. Anton Lucanus, Making Automation More Efficient by Learning from Historical Trade Data, 8:43 AM, January 7, 2020

  8. https://www.analyticsvidhya.com/blog/2018/10/predicting-stock-price-machine-learningnd-deep-learning-techniques-python/

  9. https://www.youtube.com/watch?v=2BrpKpWwT2A&list=PLQVvvaa0QuDcOdF96TBtRtuQksErCEBYZ&index=1

  10. https://towardsdatascience.com/using-lstms-for-stock-market-predictions-tensorflow-9e83999d4653

  11. https://github.com/llSourcell/Reinforcement_Learning_for_Stock_Prediction/blob/master/README.md