#python #tensorflow #lstm
#python #тензорный поток #lstm
Вопрос:
Я пытаюсь построить модель LSTM, которая использует данные временных рядов обменного курса валюты и оценку настроений за тот же диапазон дат, чтобы предсказать обменный курс на следующий день. Теперь у меня есть дата x_train, которая представляет собой фрейм данных pandas, первый столбец — это скорость, а второй столбец — оценка. Данные y_train — это просто данные, содержащие только обменный курс и сдвинутые на один день. Данные приведены с 2016-01-01 по 2017-07-06.
Таким образом, X_train имеет форму (486,2), а y_train имеет форму (486,). Я следовал некоторым руководствам, чтобы изменить X_train на (486,1,2), форма ввода равна (1,2), размер пакета равен 200, а эпоха равна 1000. Здесь у меня небольшая путаница.
Означает ли это, что в каждую эпоху модель будет начинаться с индекса 1 и принимать данные формы (200,1,2) в LSTM для обучения до индекса 286? Или партия просто выбирается случайным образом? Как я могу убедиться, что текущий пакет связан со следующим?
Другой вопрос касается количества единиц, которое является другим параметром. Я установил его равным четырем, я думаю, что это выходные данные каждого временного шага и входные данные для следующего плотного слоя, который будет иметь выходной размер 1, это правильно? Итак, речь идет о процессе прогнозирования, верно?
Ответ №1:
Если общее количество обучающих данных, которые у вас есть, составляет 486 точек временных рядов, вы, вероятно, захотите получить больше данных. При этом обычно выполняется прогнозирование временных рядов: вы выбираете размер окна, который меньше вашего набора данных, и говорите: «Если я добавлю данные за последние N дней в этот RNN, может ли он предсказать N 1-й день». Затем вы выполняете итерацию по всему вашему временному ряду, выбирая фрагменты временных рядов размером N X
и устанавливая N 1-й в качестве желаемого прогноза ( y
) .
Пример:
import numpy as np
import pandas as pd
import tensorflow as tf
# fake data.
cny = 8.0 * np.abs(np.random.normal(size=486))
compound = np.random.normal(0, 0.1, size=486)
# make a pandas data-frame
df = pd.DataFrame({'cny': cny, 'compound': compound})
# shift `cny` by one into the future and set that as the label
df['next_cny'] = df['cny'].shift(-1)
# drop the nan that shifting creates
df = df.dropna()
# check the data
print(df.head())
# cny compound next_cny
# 0 10.827493 -0.127950 0.923700
# 1 0.923700 0.039958 12.787946
# 2 12.787946 0.024724 15.817607
# 3 15.817607 -0.065448 5.866374
# 4 5.866374 0.143691 8.864016
# choose a window
window = 16 # <= you can make this whatever you want
num_windows = len(df) - window 1
# make slices of data
Xs, ys = [], []
for w in range(num_windows):
current_slice = df.iloc[w:w window]
X = current_slice[['cny', 'compound']].values
y = current_slice['next_cny'].values[-1]
Xs.append(X)
ys.append(y)
X = np.stack(Xs)
y = np.stack(ys)
# check the shape
print(X.shape)
print(y.shape)
# (470, 16, 2)
# (470,)
# make a network
x_in = tf.keras.Input([16, 2])
x, *_ = tf.keras.layers.LSTM(128, return_state=True)(x_in)
x_out = tf.keras.layers.Dense(1)(x)
# create model
model = tf.keras.Model(x_in, x_out)
# load data into tensorflow
ds = tf.data.Dataset.from_tensor_slices((X, y))
ds = ds.shuffle(1 << 6).batch(32)
# compile the model
model.compile(optimizer='Adam', loss=tf.keras.losses.MSE)
# train
model.fit(ds, epochs=10)
# Epoch 1/10
# 15/15 [==============================] - 2s 12ms/step - loss: 40.0351
# Epoch 2/10
# 15/15 [==============================] - 0s 10ms/step - loss: 21.3910
# ...
Одна вещь, о которой следует помнить при прогнозировании данных временных рядов, заключается в том, что из-за упорядоченного характера данных модель может извлекать закономерности из будущих данных и использовать их для прогнозирования прошлого. Вот хороший пост о перекрестной проверке, в котором объясняется, как разделить данные временных рядов на обучающие / тестовые наборы. Вот разделитель временных рядов в scikit-learn.
Комментарии:
1. Спасибо за ваш ответ. У меня есть вопрос по поводу партии. Итак, в вашем коде размер пакета равен 32, и у нас есть 486-16 1 windows. Что касается первого пакета, я знаю, что он будет принимать данные из окна 1 в окно 32. Но для второго пакета он будет переносить данные из окна 33 в окно 64 или из окна 2 в окно 33? Вот чего я не совсем понимаю.
2. Время (2-е измерение) во всех образцах (в этом примере) имеет длину 16. Я перебирал данные и захватывал фрагменты временных рядов длиной 16, создавая 17-е значение, метку (мы прогнозируем завтрашнее значение). Затем я случайным образом взял 32 из них для пакета. Вот как вы получаете форму
(32, 16, 2)
для своих функций.3. Вы сказали, что случайным образом захватили 32 из этих фрагментов для пакета, так что это не похоже на то, что я говорил, что фрагменты были захвачены последовательно (от первого фрагмента до 32-го фрагмента и так далее)? Тогда для одной эпохи, как должна завершаться каждая эпоха? После того, как все эти фрагменты были захвачены?
4. Если мы установим (shuffle = false), то как будут выбраны эти фрагменты? Делает ли это LSTM с сохранением состояния? И какой из них (без состояния или с сохранением состояния) в этом случае лучше?