Я реализовал модель прогнозирования, используя LSTM в Керасе. Набор данных разделен на 15 минут, и я прогнозирую на 12 будущих шагов.
Модель хорошо справляется с этой задачей. Но есть небольшая проблема с сделанным прогнозом. Это показывает небольшой эффект сдвига. Чтобы получить более четкую картину, см. Прикрепленный ниже рисунок.
Как справиться с этой проблемой.? Как данные должны быть преобразованы для решения такого рода проблем .?
Модель, которую я использовал, приведена ниже
init_lstm = RandomUniform(minval=-.05, maxval=.05)
init_dense_1 = RandomUniform(minval=-.03, maxval=.06)
model = Sequential()
model.add(LSTM(15, input_shape=(X.shape[1], X.shape[2]), kernel_initializer=init_lstm, recurrent_dropout=0.33))
model.add(Dense(1, kernel_initializer=init_dense_1, activation='linear'))
model.compile(loss='mae', optimizer=Adam(lr=1e-4))
history = model.fit(X, y, epochs=1000, batch_size=16, validation_data=(X_valid, y_valid), verbose=1, shuffle=False)
Я сделал такие прогнозы
my_forecasts = model.predict(X_valid, batch_size=16)
Данные временных рядов преобразуются в контролируемые для подачи в LSTM с помощью этой функции
# convert time series into supervised learning problem
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
df = DataFrame(data)
cols, names = list(), list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
if i == 0:
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
else:
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
# put it all together
agg = concat(cols, axis=1)
agg.columns = names
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg
super_data = series_to_supervised(data, 12, 1)
Мой временной ряд многовариантный. var2
это то, что мне нужно прогнозировать. Я бросил будущее var1
как
del super_data['var1(t)']
Раздельный поезд и действительный как этот
features = super_data[feat_names]
values = super_data[val_name]
ntest = 3444
train_feats, test_feats = features[0:-n_test], features[-n_test:]
train_vals, test_vals = values [0:-n_test], values [-n_test:]
X, y = train_feats.values, train_vals.values
X = X.reshape(X.shape[0], 1, X.shape[1])
X_valid, y_valid = test_feats .values, test_vals .values
X_valid = X_valid.reshape(X_valid.shape[0], 1, X_valid.shape[1])
Я не сделал данные стационарными для этого прогноза. Я также пытался взять разницу и сделать модель как можно более стационарной, но проблема осталась прежней.
Я также пробовал разные диапазоны масштабирования для скейлера min-max, надеясь, что это может помочь модели. Но прогнозы ухудшаются.
Other Things I have tried
=> Tried other optimizers
=> Tried mse loss and custom log-mae loss functions
=> Tried varying batch_size
=> Tried adding more past timesteps
=> Tried training with sliding window and TimeSeriesSplit
Я понимаю, что модель копирует на нее последнее известное значение, тем самым сводя к минимуму потери настолько хорошо, насколько это возможно
Проверка и потери при обучении остаются достаточно низкими в течение всего процесса обучения. Это заставляет меня задуматься, нужно ли мне придумать новую функцию потерь для этой цели.
Это необходимо? Если да, то на какую функцию потерь я должен идти ??
Я перепробовал все методы, на которые наткнулся. Я не могу найти какой-либо ресурс, который указывает на такого рода проблемы. Это проблема данных.? Это потому, что LSTM очень трудно понять эту проблему?