Прогнозирование следующей будущей стоимости с помощью Deep Learning и LSTM
Предсказание будущего с помощью Deep Learning - актуальная тема. Поэтому я хочу освоить ее.
Многие проблемы связаны со временем. Мы собрали несколько образцов и теперь хотим использовать их для предсказания следующего значения. Именно об этом и пойдет речь в этом посте. Речь не идет о предсказании множества будущих значений, это другая тема.
Как новичок в области data scientist, я просто прорабатываю некоторые примеры, которые нашел в интернете. Я меняю последовательность входных данных и смотрю, что происходит. Вы можете найти это полезным. Я нашел сайт 'Machine Learning Mastery' очень полезным. В основном я буду ссылаться на следующую статью: 'How to Develop LSTM Models for Time Series Forecasting', см. ссылки ниже.
LSTM (Длинная краткосрочная память)
LSTM используется, когда мы хотим сделать прогнозы, основанные на времени. У вас есть набор данных с образцами. Выборка может быть значением, например, ценой акции, но она также может быть ценой акции вместе с другими значениями, например, настроением в социальной сети. Это совершенно отличается от прогнозирования стоимости на основе значений, не связанных со временем, как в моем предыдущем посте "Predicting values using Deep Learning and Keras".
В LSTM мы можем включить временной компонент, но это не обязательно. LSTM - это определение последовательности во времени, а не самого времени.
Univariate против Multivariate
Существует два основных типа LSTM.
Временной ряд Univariate :
- одномерный
Пример1: Используется только цена закрытия фондового рынка
Пример2: Используется только потребление энергии.
Multivariate Временной ряд:
- многомерный
Пример1: использовать цену закрытия фондового рынка и, например, цену открытия и настроения в социальных сетях
Пример2: использовать потребление энергии и температуру.
Ниже я исследую как Univariate LSTM , так и Multivariate LSTM на примерах. Для меня самой сложной частью было то, как подготовить данные для модели. Как только я понял это, я наконец смог сосредоточиться на решении.
Univariate Временной ряд: наклон, используйте только y
Я проработал пример Univariate - Vanilla LSTM на странице 'How to Develop LSTM Models for Time Series Forecasting', см. ссылки ниже, и создал свой собственный пример, изменив последовательность входных данных с помощью функции:
# 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)
Подготовьте входные данные. Используем приведенную выше функцию для генерации некоторых образцов:
raw_seq = [4, 7, 10, 13, 16, 19]
Выбираем количество временных шагов:
n_steps = 3
Затем мы преобразуем это во входы и выходы следующим образом:
[ 4, 7, 10] -> 13
[ 7, 10, 13] -> 16
[10, 13, 16] -> 19
Для прогнозирования следующего значения мы используем последние входные данные:
[13, 16, 19] -> ?
Входы и выходы преобразуются в:
X = [
[ 4 7 10]
[ 7 10 13]
[10 13 16]
]
y = [13 16 19]
А X преобразуется в:
reshaped X = [
[ [ 4] [ 7] [10] ]
[ [ 7] [10] [13] ]
[ [10] [13] [16] ]
]
Обратите внимание, что здесь мы предсказываем только следующее значение. Код:
# 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))
И результат:
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
Вы можете попробовать это с моделями Vanilla_LSTM и Stacked_LSTM .
Multivariate Временные ряды: наклон, использование X и y
Я снова проработал пример Multivariate - Multiple Input Series на странице "How to Develop LSTM Models for Time Series Forecasting", см. ссылки ниже, и создал свой собственный пример, изменив последовательность входных данных с помощью функции:
# 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)
Подготовьте входные данные. Используем приведенную выше функцию для генерации некоторых образцов:
in_seq = [0 1 2 3 4 5]
out_seq = [ 4 7 10 13 16 19]
Выбираем количество временных шагов:
n_steps = 3
Затем мы преобразуем это во входы и выходы следующим образом:
[ [0] [1] [2] ] -> 10
[ [1] [2] [3] ] -> 13
[ [2] [3] [4] ] -> 16
[ [3] [4] [5] ] -> 19
Для прогнозирования следующего значения мы используем последние входные данные:
[ [ 4] [ 5] [ 6] ] -> ?
Входы и выходы преобразуются в:
X = [
[ [0] [1] [2] ]
[ [1] [2] [3] ]
[ [2] [3] [4] ]
[ [3] [4] [5] ]
]
y = [10 13 16 19]
Обратите внимание, что здесь мы предсказываем только следующее значение. Код:
# 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))
И результат:
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
Вы можете попробовать это с моделями Vanilla_LSTM и Stacked_LSTM .
Резюме
Это был совершенно другой опыт по сравнению с тем, который был описан в предыдущем посте "Predicting values using Deep Learning and Keras". Понимание того, как подготовить данные, было очень важным, если не самым важным. Но в интернете есть отличная документация по этому поводу.
LSMT - это черный ящик, мне это нравится. Но ему может понадобиться много точек данных (образцов). Самое важное для меня на данный момент - это качество предсказания. Насколько оно хорошо? Также я могу предсказать будущее на следующую единицу времени, но я также хочу предсказывать будущее на гораздо большее количество единиц времени. Мы все этого хотим, верно? Очень многое еще предстоит узнать...
Ссылки / кредиты
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
Подробнее
Deep Learning Machine Learning
Недавний
- Скрытие первичных ключей базы данных UUID вашего веб-приложения
- Don't Repeat Yourself (DRY) с Jinja2
- SQLAlchemy, PostgreSQL, максимальное количество строк для user
- Показать значения в динамических фильтрах SQLAlchemy
- Безопасная передача данных с помощью шифрования Public Key и pyNaCl
- rqlite: альтернатива dist с высокой степенью готовности и SQLite
Большинство просмотренных
- Используя Python pyOpenSSL для проверки SSL-сертификатов, загруженных с хоста
- Использование UUID вместо Integer Autoincrement Primary Keys с SQLAlchemy и MariaDb
- Подключение к службе на хосте Docker из контейнера Docker
- Использование PyInstaller и Cython для создания исполняемого файла Python
- SQLAlchemy: Использование Cascade Deletes для удаления связанных объектов
- Flask Удовлетворительный запрос API проверка параметров запроса с помощью схем Маршмэллоу