Я использую tensorflow.keras.preprocessing.sequence.TimeseriesGenerator
для предварительной обработки многовариантных временных рядов для модели LSTM. Однако формы выборок кажутся несовместимыми в зависимости от временных и пакетных размеров, что в конечном итоге приводит к ошибке при подгонке модели.
Более явно, предположим, что у нас есть массив NxK, где первая ось - это измерение времени и столбцы K соответствуют признакам. Я хочу сделать прогноз на один шаг вперед по первому столбцу. т.е.
# Indices of data
# Sample 1: [1,2,...,n] -> [n+1]
# Sample 2: [2,3,...,n+1] -> [n+2]
Код:
import numpy as np
from tensorflow.keras.preprocessing.sequence import TimeseriesGenerator
def GenerateData(TIMESTEPS, BATCHSIZE, N_FEATURES, N_SAMPLES):
"""
Generates batches of one-step forward samples (x_1,...,x_n), (y_n+1)
Args: TIMESTEPS (int) Number of past observations
BATCHSIZE (int) Number of samples in each batch
N_FEATURES (int) Number of features in dataset
N_SAMPLES (int) Length of dataset
Each generated sample should be shape (BATCHSIZE, TIMESTEPS, N_FEATURES), (BATCHSIZE,)
"""
# Dummy multivariate series
dummy_x = np.random.rand(N_SAMPLES, N_FEATURES)
dummy_y = np.array([x[0] for x in dummy_x]) # Predict future values of first column
print(f'Data X Shape: {dummy_x.shape}, Data Y Shape: {dummy_y.shape}')
generator = TimeseriesGenerator(data=dummy_x, targets=dummy_y,
length=TIMESTEPS,
batch_size=BATCHSIZE,
sampling_rate=1,
stride=1
)
# Check whether each sample is shaped correctly
for n in range(len(generator)):
x,y = generator[n]
if x.shape != (BATCHSIZE, TIMESTEPS, N_FEATURES):
print(f'Check index {n}.')
Тесты:
[In]
GenerateData(TIMESTEPS=5, BATCHSIZE=2, N_FEATURES=5, N_SAMPLES=1000)
[Out]
Data X Shape: (1000, 5), Data Y Shape: (1000,)
Check index 497.
Index 497 shapes: (1, 5, 5), (1,)
[In]
GenerateData(TIMESTEPS=5, BATCHSIZE=2, N_FEATURES=5, N_SAMPLES=1001)
[Out]
Data X Shape: (1001, 5), Data Y Shape: (1001,)
[In]
GenerateData(TIMESTEPS=6, BATCHSIZE=2, N_FEATURES=5, N_SAMPLES=1001)
[Out]
Data X Shape: (1001, 5), Data Y Shape: (1001,)
Check index 497.
Index 497 shapes: (1, 6, 5), (1,)
[In]
GenerateData(TIMESTEPS=6, BATCHSIZE=32, N_FEATURES=5, N_SAMPLES=1001)
[Out]
Data X Shape: (1001, 5), Data Y Shape: (1001,)
Check index 31.
Index 31 shapes: (3, 6, 5), (3,)
Есть мысли? В приведенных выше тестах успешно работает только второй.
Обновление: До сих пор не выяснено, что вызывает проблемы, и исходный код для TimeseriesGenerator
является немного трудно следовать. На данный момент, это довольно не элегантный способ ручного поиска среди потенциальных кандидатов TIMESTEPS, BATCHSIZE
параметров, которые будут генерировать выборки с постоянным размером.
from collections import defaultdict
candidates = defaultdict()
# df = your data
# Range of candidate values
TIMESTEPS_LOWER = 2
TIMESTEPS_UPPER = 15
BATCHSIZE_LOWER = 1
BATCHSIZE_UPPER = 128
for t in range(TIMESTEPS_LOWER,TIMESTEPS_UPPER):
for b in range(BATCHSIZE_LOWER,BATCHSIZE_UPPER, 2):
test = GenerateData(TIMESTEPS=t, BATCHSIZE=b, N_FEATURES=df.shape[1], N_SAMPLES=len(df))
# Check if these parameters work
if test:
# Add to existing dict
prev_cand = candidates.get(t, False)
if prev_cand:
prev_cand.append(b)
else:
candidates.update({t:[b]})
candidates
--
[OUT]
defaultdict(None,
{2: [1],
3: [1, 3, 17, 47, 51],
4: [1, 5, 7, 35],
5: [1, 13], ...
Выводы - это словарь TIMESTEPS: BATCH_SIZE, который будет работать для вашего набора данных.