Prédire la prochaine valeur future en utilisant Deep Learning et LSTM
Prédire l'avenir avec Deep Learning est un sujet brûlant. C'est pourquoi je veux le maîtriser.
De nombreux problèmes sont liés au temps. Nous avons collecté quelques échantillons et voulons maintenant les utiliser pour prédire la prochaine valeur. C'est le sujet de cet article. Il ne s'agit pas de prédire de nombreuses valeurs futures, c'est un autre sujet.
En tant que scientifique novice en matière de données, je me contente de travailler sur des exemples trouvés sur Internet. Je change la séquence d'entrée et je vois ce qui se passe. Vous trouverez peut-être cela utile. J'ai trouvé le site Web "Machine Learning Mastery" très utile. Je me référerai principalement à l'article suivant : Comment développer des modèles LSTM pour la prévision des séries chronologiques ", voir les liens ci-dessous.
LSTM (Mémoire à long terme)
LSTM est utilisé lorsque nous voulons faire des prédictions basées sur le temps. Vous avez un ensemble de données avec des échantillons. Un échantillon peut être une valeur comme le prix d'une action, mais il peut aussi être le prix d'une action associé à d'autres valeurs comme le sentiment d'un réseau social. C'est totalement différent de la prédiction d'une valeur basée sur des valeurs non liées au temps, comme dans mon précédent post 'Predicting values using Deep Learning and Keras'.
Avec LSTM , nous pouvons inclure la composante temporelle mais ce n'est pas nécessaire. LSTM a pour but de définir une séquence dans le temps, et non le temps lui-même.
Univariate vs Multivariate
Il existe deux types fondamentaux de LSTM.
Série chronologique Univariate :
- unidimensionnelle
Exemple1 : Utiliser uniquement le cours de clôture de la bourse
Exemple2 : Utiliser uniquement la consommation d'énergie
Multivariate Série chronologique :
- multidimensionnelle
Exemple1 : utiliser le cours de clôture de la bourse et par exemple le cours d'ouverture et le sentiment des médias sociaux
Exemple2 : utiliser la consommation d'énergie et la température
Je vais étudier ci-dessous les deux séries temporelles Univariate LSTM et Multivariate LSTM en utilisant des exemples. Pour moi, la partie la plus difficile était de savoir comment préparer les données pour le modèle. Une fois que j'ai compris cela, j'ai enfin pu me concentrer sur la solution.
Univariate Séries temporelles : pente, utiliser seulement y
J'ai travaillé sur l'exemple Univariate - Vanilla LSTM sur la page 'Comment développer des modèles LSTM pour la prévision des séries temporelles', voir les liens ci-dessous, et j'ai créé mon propre exemple en modifiant la séquence d'entrée à l'aide d'une fonction :
# 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)
Préparer les données d'entrée. Nous utilisons la fonction ci-dessus pour générer quelques échantillons :
raw_seq = [4, 7, 10, 13, 16, 19]
Choisir le nombre de pas de temps :
n_steps = 3
Puis nous transformons cela en entrées et sorties comme ceci :
[ 4, 7, 10] -> 13
[ 7, 10, 13] -> 16
[10, 13, 16] -> 19
Pour prédire la prochaine valeur, nous utilisons les dernières entrées :
[13, 16, 19] -> ?
Les entrées et les sorties sont converties en :
X = [
[ 4 7 10]
[ 7 10 13]
[10 13 16]
]
y = [13 16 19]
Et X est transformé en :
reshaped X = [
[ [ 4] [ 7] [10] ]
[ [ 7] [10] [13] ]
[ [10] [13] [16] ]
]
Notez que nous ne prédisons que la prochaine valeur ici. Le code :
# 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))
Et le résultat :
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
Vous pouvez l'essayer avec les modèles Vanilla_LSTM et Stacked_LSTM .
Série chronologique Multivariate : pente, utilisation de X et y
J'ai à nouveau travaillé sur l'exemple Multivariate - Séries à entrées multiples sur la page 'Comment développer des modèles LSTM pour la prévision des séries temporelles', voir les liens ci-dessous, et j'ai créé mon propre exemple en modifiant la séquence d'entrée à l'aide d'une fonction :
# 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)
Préparer les données d'entrée. Nous utilisons la fonction ci-dessus pour générer quelques échantillons :
in_seq = [0 1 2 3 4 5]
out_seq = [ 4 7 10 13 16 19]
Choisir le nombre de pas de temps :
n_steps = 3
Puis nous transformons cela en entrées et sorties comme ceci :
[ [0] [1] [2] ] -> 10
[ [1] [2] [3] ] -> 13
[ [2] [3] [4] ] -> 16
[ [3] [4] [5] ] -> 19
Pour prédire la prochaine valeur, nous utilisons les dernières entrées :
[ [ 4] [ 5] [ 6] ] -> ?
Les entrées et les sorties sont converties en :
X = [
[ [0] [1] [2] ]
[ [1] [2] [3] ]
[ [2] [3] [4] ]
[ [3] [4] [5] ]
]
y = [10 13 16 19]
Notez que nous ne prédisons que la prochaine valeur ici. Le code :
# 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))
Et le résultat :
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
Vous pouvez l'essayer avec les modèles Vanilla_LSTM et Stacked_LSTM .
Résumé
Cette expérience a été totalement différente de celle décrite dans le post précédent 'Predicting values using Deep Learning and Keras'. Comprendre comment préparer les données était très important, si ce n'est le plus important. Mais il existe une excellente documentation sur Internet à ce sujet.
LSMT est une boîte noire, j'aime ça. Mais il peut avoir besoin de beaucoup de points de données (échantillons). La chose la plus importante pour moi à l'heure actuelle est la qualité de la prédiction. Je peux aussi prédire l'avenir pour la prochaine unité de temps, mais je veux aussi prédire l'avenir pour beaucoup plus d'unités de temps. C'est ce que nous voulons tous, n'est-ce pas ? J'ai encore beaucoup à apprendre ...
Liens / crédits
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
En savoir plus...
Deep Learning Machine Learning
Récent
- Masquer les clés primaires de la base de données UUID de votre application web
- Don't Repeat Yourself (DRY) avec Jinja2
- SQLAlchemy, PostgreSQL, nombre maximal de lignes par user
- Afficher les valeurs des filtres dynamiques SQLAlchemy
- Transfert de données sécurisé grâce au cryptage à Public Key et à pyNaCl
- rqlite : une alternative à haute disponibilité et dist distribuée SQLite
Les plus consultés
- Utilisation des Python's pyOpenSSL pour vérifier les certificats SSL téléchargés d'un hôte
- Utiliser UUIDs au lieu de Integer Autoincrement Primary Keys avec SQLAlchemy et MariaDb
- Utiliser PyInstaller et Cython pour créer un exécutable Python
- Connexion à un service sur un hôte Docker à partir d'un conteneur Docker
- SQLAlchemy : Utilisation de Cascade Deletes pour supprimer des objets connexes
- Flask RESTful API validation des paramètres de la requête avec les schémas Marshmallow