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

Voorspelling van de volgende toekomstige waarde met behulp van Deep Learning en LSTM

De toekomst voorspellen met Deep Learning is een hot topic. Daarom wil ik me dit eigen maken.

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

Veel problemen zijn tijdgerelateerd. We hebben een aantal steekproeven verzameld en willen die nu gebruiken om de volgende waarde te voorspellen. Dat is waar deze post over gaat. Het gaat niet over het voorspellen van veel toekomstige waarden, dat is een ander onderwerp.
Als data scientist noob, werk ik gewoon door wat voorbeelden die ik op het internet heb gevonden. Ik verander de invoerreeks en kijk wat er gebeurt. Misschien vind je dit nuttig. Ik vond de 'Machine Learning Mastery' website erg nuttig. Ik zal vooral verwijzen naar het volgende artikel: 'How to Develop LSTM Models for Time Series Forecasting', zie onderstaande links.

LSTM (Lange-korte-termijngeheugen)

LSTM wordt gebruikt wanneer wij voorspellingen willen doen die op de tijd zijn gebaseerd. U hebt een dataset met steekproeven. Een steekproef kan een waarde zijn zoals de prijs van een aandeel, maar het kan ook de prijs van een aandeel zijn samen met andere waarden zoals het sentiment van een sociaal netwerk. Dit is totaal verschillend van het voorspellen van een waarde op basis van niet tijdgerelateerde waarden zoals in mijn vorige post 'Predicting values using Deep Learning and Keras'.

Bij LSTM kunnen we de tijdcomponent opnemen, maar dat is niet nodig. Bij LSTM gaat het om het definiëren van een opeenvolging in de tijd, niet om de tijd zelf.

Univariate vs. Multivariate

Er zijn twee basistypen LSTM.

Univariate Tijdreeksen:

  • eendimensionaal
    Voorbeeld1: Gebruik alleen de slotkoers van de aandelenmarkt
    Voorbeeld2: Gebruik alleen het energieverbruik

Multivariate Tijdreeks:

  • multidimensionaal
    Voorbeeld1: gebruik de slotkoers van de beurs en bijv. de openingskoers en het sentiment van de sociale media
    Voorbeeld2: gebruik het energieverbruik en de temperatuur

Hieronder zal ik zowel Univariate LSTM als Multivariate LSTM onderzoeken aan de hand van voorbeelden. Voor mij was het moeilijkste deel hoe de gegevens voor het model voor te bereiden. Toen ik dit eenmaal begreep, kon ik me eindelijk op de oplossing concentreren.

Univariate Tijdreeks: helling, gebruik alleen y

Ik werkte door het Univariate - Vanilla LSTM voorbeeld op de pagina 'How to Develop LSTM Models for Time Series Forecasting', zie links hieronder, en creëerde mijn eigen voorbeeld door de invoerreeks te veranderen met behulp van een functie:

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

Bereid de invoergegevens voor. We gebruiken de bovenstaande functie om enkele steekproeven te genereren:

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

Kies het aantal tijdstappen:

n_steps = 3

Dan zetten we dit om in inputs en outputs zoals dit:

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

Om de volgende waarde te voorspellen gebruiken we de laatste inputs:

[13, 16, 19] -> ?

De inputs en outputs worden omgezet in:

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

En X wordt omgevormd tot:

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

Merk op dat we hier alleen de volgende waarde voorspellen. De 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))

En het resultaat:

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

U kunt het proberen met Vanilla_LSTM en Stacked_LSTM modellen.

Multivariate Tijdreeksen: helling, gebruik X en y

Opnieuw heb ik het voorbeeld van Multivariate - Multiple Input Series op de pagina 'How to Develop LSTM Models for Time Series Forecasting', zie onderstaande links, doorgewerkt en mijn eigen voorbeeld gemaakt door de invoerreeks met behulp van een functie te wijzigen:

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

Bereid de invoergegevens voor. We gebruiken de bovenstaande functie om enkele steekproeven te genereren:

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

Kies het aantal tijdstappen:

n_steps = 3

Dan zetten we dit om in inputs en outputs zoals dit:

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

Om de volgende waarde te voorspellen gebruiken we de laatste inputs:

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

De inputs en outputs worden omgezet in:

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

Merk op dat we hier alleen de volgende waarde voorspellen. De 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))

En het resultaat:

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

U kunt het proberen met Vanilla_LSTM en Stacked_LSTM modellen.

Samenvatting

Dit was een totaal andere ervaring dan die beschreven in de vorige post 'Predicting values using Deep Learning and Keras'. Begrijpen hoe de gegevens moeten worden voorbereid was erg belangrijk, zo niet het belangrijkste. Maar er is hierover uitstekende documentatie op het internet te vinden.
LSMT is een black box, daar hou ik van. Maar het kan veel datapunten (monsters) nodig hebben. Het belangrijkste voor mij op dit moment is de kwaliteit van de voorspelling. Hoe goed is het? Ook kan ik de toekomst voorspellen voor de volgende tijdseenheid, maar ik wil ook de toekomst voorspellen voor veel meer tijdseenheden. Dat willen we toch allemaal? Heel veel nog te leren ...

Links / credits

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

Laat een reactie achter

Reageer anoniem of log in om commentaar te geven.

Opmerkingen

Laat een antwoord achter

Antwoord anoniem of log in om te antwoorden.