angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Predicción del próximo valor futuro mediante Deep Learning y LSTM

Predecir el futuro con Deep Learning es un tema candente. Por eso quiero dominarlo.

30 enero 2022
post main image
https://www.pexels.com/nl-nl/@andrew

Muchos problemas están relacionados con el tiempo. Hemos recogido algunas muestras y ahora queremos utilizarlas para predecir el siguiente valor. De eso trata este post. No se trata de predecir muchos valores futuros, eso es un tema diferente.
Como científico de datos novato, sólo trabajo con algunos ejemplos que encontré en Internet. Cambio la secuencia de entrada y veo lo que sucede. Puede que esto te resulte útil. He encontrado el sitio web 'Machine Learning Mastery' muy útil. Me referiré principalmente al siguiente artículo: 'How to Develop LSTM Models for Time Series Forecasting', ver enlaces más abajo.

LSTM (Memoria a corto plazo)

LSTM se utiliza cuando queremos hacer predicciones basadas en el tiempo. Se tiene un conjunto de datos con muestras. Una muestra puede ser un valor como el precio de una acción, pero también puede ser el precio de una acción junto con otros valores como el sentimiento de las redes sociales. Esto es totalmente diferente a la predicción de un valor basado en valores no relacionados con el tiempo como en mi anterior post 'Predicting values using Deep Learning and Keras'.

Con LSTM podemos incluir el componente temporal pero no es necesario. LSTM trata de definir una secuencia en el tiempo, no del tiempo en sí.

Univariate vs Multivariate

Hay dos tipos básicos de LSTM.

Series temporales Univariate :

  • unidimensional
    Ejemplo1: Utilizar sólo el precio de cierre de la bolsa
    Ejemplo2: Utilizar sólo el consumo de energía

Multivariate Series temporales:

  • multidimensional
    Ejemplo1: utilizar el precio de cierre de la bolsa y, por ejemplo, el precio de apertura y el sentimiento de las redes sociales
    Ejemplo2: utilizar el consumo de energía y la temperatura

A continuación voy a investigar tanto Univariate LSTM como Multivariate LSTM utilizando ejemplos. Para mí la parte más difícil fue cómo preparar los datos para el modelo. Una vez que entendí esto, finalmente pude centrarme en la solución.

Univariate Series temporales: pendiente, usar sólo y

Trabajé a través del ejemplo Univariate - Vanilla LSTM en la página 'Cómo desarrollar modelos LSTM para la previsión de series temporales', ver enlaces más abajo, y creé mi propio ejemplo cambiando la secuencia de entrada utilizando una función:

# define input sequence
def fx(x):
    y = 4 + 3*x
    return y

x_end = 6
raw_seq = []
for x in range(0, x_end):
    y = fx(x)
    raw_seq.append(y)

Preparar los datos de entrada. Utilizamos la función anterior para generar algunas muestras:

raw_seq = [4, 7, 10, 13, 16, 19]

Elija el número de pasos de tiempo:

n_steps = 3

Luego transformamos esto en entradas y salidas así:

[ 4,  7, 10] -> 13
[ 7, 10, 13] -> 16
[10, 13, 16] -> 19

Para predecir el siguiente valor utilizamos las últimas entradas:

[13, 16, 19] -> ?

Las entradas y salidas se convierten en:

X = [
  [ 4  7 10]
  [ 7 10 13]
  [10 13 16]
]
y = [13 16 19]

Y X se transforma en:

reshaped X = [
  [ [ 4] [ 7] [10] ]
  [ [ 7] [10] [13] ]
  [ [10] [13] [16] ]
]

Nótese que aquí sólo predecimos el siguiente valor. El código:

# Based on the Univariate Vanilla LSTM example from this page:
# How to Develop LSTM Models for Time Series Forecasting
# https://machinelearningmastery.com/how-to-develop-lstm-models-for-time-series-forecasting
#
# input sequence is a slope:
# - y = 4 + 3*x 
# - we are using only y
#
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, LSTM

# split a univariate sequence into samples
def split_sequence(sequence, n_steps):
    X, y = list(), list()
    for i in range(len(sequence)):
        # find the end of this pattern
        end_ix = i + n_steps
        # check if we are beyond the sequence
        if end_ix > len(sequence)-1:
            break
        # gather input and output parts of the pattern
        seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
        X.append(seq_x)
        y.append(seq_y)
    return np.array(X), np.array(y)

# choose a number of time steps
n_steps = 3

# define input sequence
def fx(x):
    y = 4 + 3*x
    return y

x_end = 6
raw_seq = []
for x in range(0, x_end):
    y = fx(x)
    raw_seq.append(y)
print('raw_seq = {}'.format(raw_seq))

# predict data
x_input = raw_seq[-1*n_steps:]
print('x_input = {}'.format(x_input))
y_expected = fx(x_end)
print('y_expected = {}'.format(y_expected))

# split into samples
X, y = split_sequence(raw_seq, n_steps)
print('X = {}'.format(X))
print('y = {}'.format(y))

# reshape from [samples, timesteps] into [samples, timesteps, features]
n_features = 1
print('X.shape[0] = {}'.format(X.shape[0]))
print('X.shape[1] = {}'.format(X.shape[1]))
X = X.reshape((X.shape[0], X.shape[1], n_features))
print('reshaped X = {}'.format(X))

# define model
def get_model(m):
    if m == 'Vanilla_LSTM':
        model = Sequential(name=m)
        model.add(LSTM(50, activation='relu', input_shape=(n_steps, n_features)))
        model.add(Dense(1))
        model.compile(optimizer='adam', loss='mse')
    elif m == 'Stacked_LSTM':
        model = Sequential(name=m)
        model.add(LSTM(50, activation='relu', return_sequences=True, input_shape=(n_steps, n_features)))
        model.add(LSTM(50, activation='relu'))
        model.add(Dense(1))
        model.compile(optimizer='adam', loss='mse')
    model.summary()
    return model
#model = get_model('Vanilla_LSTM')
model = get_model('Stacked_LSTM')

# fit model
model.fit(X, y, epochs=200, verbose=0)

# show prediction
x_input = np.array(x_input)
x_input = x_input.reshape((1, n_steps, n_features))
yhat = model.predict(x_input, verbose=0)
print('prediction: for x_input = {}, yhat = {}, y_expected = {}'.format(x_input, yhat, y_expected))

Y el resultado:

raw_seq = [4, 7, 10, 13, 16, 19]
x_input = [13, 16, 19]
y_expected = 22
X = [[ 4  7 10]
 [ 7 10 13]
 [10 13 16]]
y = [13 16 19]
X.shape[0] = 3
X.shape[1] = 3
reshaped X = [[[ 4]
  [ 7]
  [10]]

 [[ 7]
  [10]
  [13]]

 [[10]
  [13]
  [16]]]
Model: "Stacked_LSTM"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 lstm (LSTM)                 (None, 3, 50)             10400     
                                                                 
 lstm_1 (LSTM)               (None, 50)                20200     
                                                                 
 dense (Dense)               (None, 1)                 51        
                                                                 
=================================================================
Total params: 30,651
Trainable params: 30,651
Non-trainable params: 0
_________________________________________________________________
prediction: for x_input = [[[13]
  [16]
  [19]]], yhat = [[21.4401]], y_expected = 22

Puede probarlo con los modelos Vanilla_LSTM y Stacked_LSTM .

Multivariate Series temporales: pendiente, uso de X e y

Una vez más, he trabajado con el ejemplo Multivariate - Multiple Input Series en la página 'Cómo desarrollar modelos LSTM para la previsión de series temporales', ver enlaces más abajo, y he creado mi propio ejemplo cambiando la secuencia de entrada mediante una función:

# define input sequence
def fx(x):
    y = 4 + 3*x
    return y

x_end = 6
in_seq = []
out_seq = []
for x in range(0, x_end):
    y = fx(x)
    in_seq.append(x)
    out_seq.append(y)
in_seq = np.array(in_seq)
out_seq = np.array(out_seq)

Preparar los datos de entrada. Utilizamos la función anterior para generar algunas muestras:

in_seq = [0 1 2 3 4 5]
out_seq = [ 4  7 10 13 16 19]

Elija el número de pasos de tiempo:

n_steps = 3

Luego transformamos esto en entradas y salidas así:

[ [0] [1] [2] ] -> 10
[ [1] [2] [3] ] -> 13
[ [2] [3] [4] ] -> 16
[ [3] [4] [5] ] -> 19

Para predecir el siguiente valor utilizamos las últimas entradas:

[ [ 4] [ 5] [ 6] ] -> ?

Las entradas y salidas se convierten en:

X = [
  [ [0] [1] [2] ]
  [ [1] [2] [3] ]
  [ [2] [3] [4] ]
  [ [3] [4] [5] ]
]
y = [10 13 16 19]

Obsérvese que aquí sólo predecimos el siguiente valor. El código:

# Based on the multivariate LSTM Multiple Input Series example from this page:
# How to Develop LSTM Models for Time Series Forecasting
# https://machinelearningmastery.com/how-to-develop-lstm-models-for-time-series-forecasting
#
# input sequence is a slope:
# - y = 4 + 3*x 
# - we are using both x and y
#
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, LSTM
 
# split a multivariate sequence into samples
def split_sequences(sequences, n_steps):
	X, y = list(), list()
	for i in range(len(sequences)):
		# find the end of this pattern
		end_ix = i + n_steps
		# check if we are beyond the dataset
		if end_ix > len(sequences):
			break
		# gather input and output parts of the pattern
		seq_x, seq_y = sequences[i:end_ix, :-1], sequences[end_ix-1, -1]
		X.append(seq_x)
		y.append(seq_y)
	return np.array(X), np.array(y)

# choose a number of time steps
n_steps = 4

# define input sequence
def fx(x):
    y = 4 + 3*x
    return y

x_end = 12
in_seq = []
out_seq = []
for x in range(0, x_end):
    y = fx(x)
    in_seq.append(x)
    out_seq.append(y)
in_seq = np.array(in_seq)
out_seq = np.array(out_seq)
print('in_seq = {}'.format(in_seq))
print('out_seq = {}'.format(out_seq))

# convert to [rows, columns] structure
in_seq = in_seq.reshape((len(in_seq), 1))
out_seq = out_seq.reshape((len(out_seq), 1))
print('after convert to [rows, columns]:')
print('in_seq = {}'.format(in_seq))
print('out_seq = {}'.format(out_seq))

# horizontally stack columns
dataset = np.hstack((in_seq, out_seq))
print('dataset = {}'.format(dataset))

# convert into input/output
X, y = split_sequences(dataset, n_steps)
print('X = {}'.format(X))
print('y = {}'.format(y))

# prediction data = last row of dataset
x_input = X[-1]
y_expected = y[-1]

# remove prediction data from dataset
X = X[:-1]
y = y[:-1]
print('X = {}'.format(X))
print('y = {}'.format(y))

# the dataset knows the number of features, e.g. 2
n_features = X.shape[2]
print('n_features = {}'.format(n_features))

# define model
def get_model(m):
    if m == 'Vanilla_LSTM':
        model = Sequential(name=m)
        model.add(LSTM(50, activation='relu', input_shape=(n_steps, n_features)))
        model.add(Dense(1))
        model.compile(optimizer='adam', loss='mse')
    elif m == 'Stacked_LSTM':
        model = Sequential(name=m)
        model.add(LSTM(50, activation='relu', return_sequences=True, input_shape=(n_steps, n_features)))
        model.add(LSTM(50, activation='relu'))
        model.add(Dense(1))
        model.compile(optimizer='adam', loss='mse')
    model.summary()
    return model
model = get_model('Vanilla_LSTM')
#model = get_model('Stacked_LSTM')

# fit model
model.fit(X, y, epochs=200, verbose=0)

# show prediction
x_input = x_input.reshape((1, n_steps, n_features))
yhat = model.predict(x_input, verbose=0)
print('prediction: for x_input = {}, yhat = {}, y_expected = {}'.format(x_input, yhat, y_expected))

Y el resultado:

in_seq = [ 0  1  2  3  4  5  6  7  8  9 10 11]
out_seq = [ 4  7 10 13 16 19 22 25 28 31 34 37]
after convert to [rows, columns]:
in_seq = [[ 0]
 [ 1]
 [ 2]
 [ 3]
 [ 4]
 [ 5]
 [ 6]
 [ 7]
 [ 8]
 [ 9]
 [10]
 [11]]
out_seq = [[ 4]
 [ 7]
 [10]
 [13]
 [16]
 [19]
 [22]
 [25]
 [28]
 [31]
 [34]
 [37]]
dataset = [[ 0  4]
 [ 1  7]
 [ 2 10]
 [ 3 13]
 [ 4 16]
 [ 5 19]
 [ 6 22]
 [ 7 25]
 [ 8 28]
 [ 9 31]
 [10 34]
 [11 37]]
X = [[[ 0]
  [ 1]
  [ 2]
  [ 3]]

 [[ 1]
  [ 2]
  [ 3]
  [ 4]]

 [[ 2]
  [ 3]
  [ 4]
  [ 5]]

 [[ 3]
  [ 4]
  [ 5]
  [ 6]]

 [[ 4]
  [ 5]
  [ 6]
  [ 7]]

 [[ 5]
  [ 6]
  [ 7]
  [ 8]]

 [[ 6]
  [ 7]
  [ 8]
  [ 9]]

 [[ 7]
  [ 8]
  [ 9]
  [10]]

 [[ 8]
  [ 9]
  [10]
  [11]]]
y = [13 16 19 22 25 28 31 34 37]
X = [[[ 0]
  [ 1]
  [ 2]
  [ 3]]

 [[ 1]
  [ 2]
  [ 3]
  [ 4]]

 [[ 2]
  [ 3]
  [ 4]
  [ 5]]

 [[ 3]
  [ 4]
  [ 5]
  [ 6]]

 [[ 4]
  [ 5]
  [ 6]
  [ 7]]

 [[ 5]
  [ 6]
  [ 7]
  [ 8]]

 [[ 6]
  [ 7]
  [ 8]
  [ 9]]

 [[ 7]
  [ 8]
  [ 9]
  [10]]]
y = [13 16 19 22 25 28 31 34]
n_features = 1
Model: "Vanilla_LSTM"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 lstm (LSTM)                 (None, 50)                10400     
                                                                 
 dense (Dense)               (None, 1)                 51        
                                                                 
=================================================================
Total params: 10,451
Trainable params: 10,451
Non-trainable params: 0
_________________________________________________________________
prediction: for x_input = [[[ 8]
  [ 9]
  [10]
  [11]]], yhat = [[35.79921]], y_expected = 37

Puedes probarlo con los modelos Vanilla_LSTM y Stacked_LSTM .

Resumen

Esta fue una experiencia totalmente diferente a la descrita en el post anterior 'Predicting values using Deep Learning and Keras'. Entender cómo preparar los datos fue muy importante, si no lo más importante. Pero hay una excelente documentación en Internet sobre esto.
LSMT es una caja negra, esto me gusta. Pero puede necesitar muchos puntos de datos (muestras). Lo más importante para mí en este momento es la calidad de la predicción. También puedo predecir el futuro para la siguiente unidad de tiempo, pero también quiero predecir el futuro para muchas más unidades de tiempo. Todos queremos esto, ¿verdad? Todavía queda mucho por aprender...

Enlaces / créditos

How to Convert a Time Series to a Supervised Learning Problem in Python
https://machinelearningmastery.com/convert-time-series-supervised-learning-problem-python

How to Develop LSTM Models for Time Series Forecasting
https://machinelearningmastery.com/how-to-develop-lstm-models-for-time-series-forecasting

How to Use the TimeseriesGenerator for Time Series Forecasting in Keras
https://machinelearningmastery.com/how-to-use-the-timeseriesgenerator-for-time-series-forecasting-in-keras

Understand Keras's RNN behind the scenes with a sin wave example - Stateful and Stateless prediction
https://fairyonice.github.io/Understand-Keras's-RNN-behind-the-scenes-with-a-sin-wave-example.html

Deje un comentario

Comente de forma anónima o inicie sesión para comentar.

Comentarios

Deje una respuesta.

Responda de forma anónima o inicie sesión para responder.