#tensorflow #deep-learning #time-series #lstm #forecasting
Вопрос:
У меня есть анализатор для какой-то веб-страницы, каждые 20-60 секунд я получаю массив Xt=[x0, x1, x2, x3, x4]. Меня интересует только предсказание следующих пяти x0 из каждого массива, но я также хочу использовать x1,..x4. Итак, для Xt предсказать [Xt 1[0], Xt 2[0],…, Xt 5[0]]. Не знаю, как вообще подойти к этой проблеме.
Сначала я попытался разбить все данные в последовательности time_step=24
: х=[[х0,…,X23], [Х1,…,Х24], [Х2,…, Х25], …]; у = [[Х24[0],…,Х28[0]], [Х25[0],…,Х29[0]],…]. Использована куча водоснабжении.Слои LSTM и модель возвращают одинаковые значения в каждом столбце.
Теперь я сделал это (time_step=1, для Xt предсказать [Xt 1[0],…, Xt 5[0]]):
import pandas as pd
import numpy as np
df1 = pd.read_csv('data1.csv', index_col=0)
data1 = df1.to_numpy()
trX = []
trY = []
for i in range(0, len(data1)-6):
trX.append(data1[i])
trY.append(data1[i 1:i 6][:, 0])
trX = np.array(trX, dtype=np.float32)
trY = np.array(trY, dtype=np.float32)
trX = trX.reshape(-1, 1, 5)
BS = 600
trX = trX[:trX.shape[0] - trX.shape[0] % BS]
trY = trY[:trY.shape[0] - trY.shape[0] % BS]
valX = trX[-BS:]
trX = trX[:-BS]
valY = trY[-BS:]
trY = trY[:-BS]
import tensorflow as tf
import numpy as np
model1 = tf.keras.Sequential()
model1.add(tf.keras.layers.LSTM(256, return_sequences=True, batch_input_shape=(600, 1, 5), stateful=True))
model1.add(tf.keras.layers.LSTM(128, return_sequences=True, stateful=True))
model1.add(tf.keras.layers.LSTM(64, return_sequences=True, stateful=True))
model1.add(tf.keras.layers.Flatten())
model1.add(tf.keras.layers.Dense(64, activation=tf.keras.activations.elu))
model1.add(tf.keras.layers.Dense(32, activation=tf.keras.activations.elu))
model1.add(tf.keras.layers.Dense(5, activation=tf.keras.activations.elu))
model1.compile(optimizer='adam',
loss='mse',
metrics=['acc'])
model1.fit(trX, trY, 600, 5, 1, validation_data=(valX, valY), shuffle=False)
res1 = model1(valX)
res1
Epoch 1/5
21/21 [==============================] - 6s 66ms/step - loss: 5.6772e-04 - acc: 0.2037 - val_loss: 3.7310e-04 - val_acc: 0.1917
Epoch 2/5
21/21 [==============================] - 0s 11ms/step - loss: 8.0731e-04 - acc: 0.1967 - val_loss: 3.2517e-04 - val_acc: 0.2083
Epoch 3/5
21/21 [==============================] - 0s 12ms/step - loss: 6.7266e-04 - acc: 0.2015 - val_loss: 4.2750e-04 - val_acc: 0.2083
Epoch 4/5
21/21 [==============================] - 0s 12ms/step - loss: 8.3055e-04 - acc: 0.2023 - val_loss: 7.4263e-05 - val_acc: 0.1917
Epoch 5/5
21/21 [==============================] - 0s 11ms/step - loss: 6.4451e-04 - acc: 0.1983 - val_loss: 2.0734e-04 - val_acc: 0.1917
<tf.Tensor: shape=(600, 5), dtype=float32, numpy=
array([[ 0.01462946, -0.0035404 , -0.01471442, 0.01326532, -0.0222075 ],
[ 0.01454796, -0.00362718, -0.01483804, 0.01332456, -0.02220327],
[ 0.01449167, -0.0035699 , -0.01502049, 0.01351681, -0.02212006],
...,
[ 0.01451699, -0.00386065, -0.01463401, 0.01302508, -0.02228123],
[ 0.01449066, -0.00371438, -0.0148297 , 0.01326665, -0.02216893],
[ 0.01450208, -0.0035758 , -0.01488554, 0.01341164, -0.02206981]],
dtype=float32)>
Какой подход я должен использовать?
Ответ №1:
Ответ основан на моем понимании вашей проблемы.
Вы хотите взять все 5 атрибутов для x временных шагов и предсказать только один атрибут для следующих 5 временных шагов. Предположим, что для x=16 временных шагов вы хотите предсказать следующие 5.
Использование timeseries_dataset_from_array из keras.предварительная обработка
X = tf.keras.preprocessing.timeseries_dataset_from_array(
data1, None, 16, sequence_stride=1, sampling_rate=1, batch_size=128)
Y = tf.keras.preprocessing.timeseries_dataset_from_array(
data1.reshape((len(data1),5,1))[:,0],targets=None, sequence_length=5, sequence_stride=1, sampling_rate=1, batch_size=128,start_index=16)
Здесь мы хотим выполнить data1.reshape((len(data1), 5,1), чтобы иметь одну функцию на каждый шаг времени (5,1). В противном случае он будет рассматривать его как 5 функций за один шаг (1,5)
Вы можете убедиться в этом, посмотрев первый пример из одной партии
for y in Y.take(1):
print(y[0])
tf.Тензор( [[5.2513130 e-05] [6.7516880 e-05] [2.0505126 e-04]
[4.9012253 e-04] [2.6181545 e-03]], форма=(5, 1), dtype=float64)
for x in X.take(1):
print(x[0])
tf.Тензор( [[7.15178800 e-04 4.77345650 e-01 2.95000000 e-01
6.57851550 e-02
2.55877470 e-02] [4.15103770 e-04 4.77803350 e-01 2.61000000 e-01 4.81817540 e-02
1.53348090 e-02] [0.00000000 e 00 4.77858450 e-01 2.56750000 e-01 5.49672660 e-02
0.00000000 e 00] [1.17529380 e-04 4.78104230 e-01 2.30000000 e-01 4.48042680 e-02
1.49495100 e-03] [7.50187540 e-05 4.78617040 e-01 2.83500000 e-01 5.70335300 e-02
1.69152800 e-03] [9.75243800 e-05 4.78693340 e-01 2.48750000 e-01 5.27507600 e-02
2.45307600 e-03] [1.55038750 e-04 4.78943380 e-01 3.12500000 e-01 7.79491600 e-02
7.45544300 e-03] [6.50162500 e-04 4.79070500 e-01 3.22500000 e-01 8.41833000 e-02
3.43781560 e-02] [7.72693200 e-04 4.79375660 e-01 3.42250000 e-01 8.51799300 e-02
3.39922500 e-02] [2.25056260 e-05 4.79435000 e-01 3.20500000 e-01 6.69510960 e-02
1.01650000 e-05] [1.19584896 e-01 4.79981700 e-01 2.73750000 e-01 5.85157000 e-02
1.56834650 e-01] [3.91847970 e-03 4.80363100 e-01 2.93000000 e-01 6.89749400 e-02
5.97691870 e-02] [1.57539380 e-04 4.80617400 e-01 2.72000000 e-01 5.25309100 e-02
3.83557300 e-03] [2.17554390 e-04 4.80706400 e-01 2.51500000 e-01 5.18024450 e-02
7.34595600 e-03] [1.69292330 e-03 4.81036960 e-01 2.79000000 e-01 5.94664920 e-02
3.83583500 e-02] [4.00100030 e-05 4.81113260 e-01 3.16500000 e-01 6.70532600 e-02
8.07160000 e-04]], форма=(16, 5), dtype=float64)
Затем вам нужно будет скрепить их вместе, чтобы передать его в метод fit ().
ds = tf.data.Dataset.zip((X, Y))