我有一个时间序列的数据,其值代表按分钟收集的“活动”。我设置了一个LSTM来建模数据。 LSTM设置为输入300点,然后输出接下来的60点。
我稍微调整了LSTM的架构,但是损失通常在一个时期之后收敛,并且对于任何300个输入,预测似乎是相同的60个点。
我的代码或一般方法有什么问题吗?
n_test = int(df.shape[0] * 0.2)
n_in = 300
n_out = 60
n_batch = 1
n_epochs = 3
verbose = 1
neurons = (5,5)
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 = pd.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 = pd.concat(cols, axis=1)
agg.columns = names
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg
def prepare_data(series, n_test, n_lag, n_seq):
raw_values = series.values
raw_values = raw_values.reshape(len(raw_values), 1)
scaler = MinMaxScaler(feature_range=(-1, 1))
scaled_values = scaler.fit_transform(raw_values)
# series_to_supervised is above
supervised = series_to_supervised(scaled_values, n_lag, n_seq)
supervised_values = supervised.values
train, test = supervised_values[0:-n_test], supervised_values[-n_test:]
return scaler, train, test
scaler, train, test = prepare_data(df, n_test, n_in, n_out)
def fit_lstm(train, test, n_lag, n_seq, n_batch, nb_epoch, n_neurons, verbose):
# reshape training into [samples, timesteps, features]
X, y = train[:, :n_lag], train[:, n_lag:]
X = X.reshape(X.shape[0], 1, X.shape[1])
X_test, y_test = test[:, :n_lag], test[:, n_lag:]
X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])
model = Sequential()
model.add(LSTM(n_neurons[0], batch_input_shape=(n_batch, X.shape[1], X.shape[2]),
return_sequences=True, stateful=True, dropout=0.4))
model.add(LSTM(n_neurons[1], batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(y.shape[1]))
model.compile(loss='mse', optimizer='adam')
losses = []
val_losses = []
min_val_loss = (99999,999999)
for i in range(nb_epoch):
if verbose!=0:
print(i)
history = model.fit(X, y, validation_data=(X_test,y_test), epochs=1, batch_size=n_batch, verbose=verbose, shuffle=False)
losses.append(history.history['loss'])
val_losses.append(history.history['val_loss'][0])
if val_losses[-1] < min_val_loss[0]:
min_val_loss = (val_losses[-1], i)
model.reset_states()
print('best val_loss and epoch:',min_val_loss)
plt.title('loss')
plt.plot(losses)
plt.plot(val_losses, color='red')
plt.show()
return model
model = fit_lstm(train, test, n_in, n_out, n_batch, n_epochs, neurons, verbose)
# Running on 3 epochs:
# Train on 420005 samples, validate on 105091 samples
# Epoch 1/1
# 420005/420005 [==============================] - 1183s - loss: 0.0143 - val_loss: 0.0086
# Train on 420005 samples, validate on 105091 samples
# Epoch 1/1
# 420005/420005 [==============================] - 1185s - loss: 0.0142 - val_loss: 0.0086
# Train on 420005 samples, validate on 105091 samples
# Epoch 1/1
# 420005/420005 [==============================] - 1179s - loss: 0.0142 - val_loss: 0.0086
def forecast_lstm(model, X, n_batch):
X = X.reshape(1, 1, len(X))
model.reset_states()
forecast = model.predict(X, batch_size=n_batch, verbose=0)
model.reset_states()
return [x for x in forecast[0, :]]
def make_forecasts(model, n_batch, points, n_lag, n_seq):
forecasts = list()
for i in range(len(points)):
X = points[i, 0:n_lag]
forecast = forecast_lstm(model, X, n_batch)
forecasts.append(forecast)
return forecasts
forecasts = make_forecasts(model, n_batch, test, n_in, n_out)
def inverse_transform(forecasts, scaler):
inverted = list()
for i in range(len(forecasts)):
forecast = np.array(forecasts[i])
forecast = forecast.reshape(1, len(forecast))
inv_scale = scaler.inverse_transform(forecast)
inv_scale = inv_scale[0, :]
inverted.append(list(inv_scale))
return inverted
forecasts = inverse_transform(forecasts, scaler)
actual = inverse_transform(test, scaler)
def evaluate_forecasts(test, forecasts, n_lag, n_seq):
total_rmse = 0
if type(test) is list:
test = np.array(test)
for i in range(n_seq):
actual = test[:,(n_lag+i)]
predicted = [forecast[i] for forecast in forecasts]
rmse = np.sqrt(mean_squared_error(actual, predicted))
print('t+%d RMSE: %f' % ((i+1), rmse))
total_rmse += rmse
print('total rmse: ', total_rmse)
evaluate_forecasts(actual,forecasts,n_in, n_out)
# t+1 RMSE: 155.838490
# t+2 RMSE: 168.965727
# t+3 RMSE: 167.270456
# t+4 RMSE: 176.760815
# t+5 RMSE: 127.637996
# t+6 RMSE: 186.222487
# t+7 RMSE: 160.867497
# t+8 RMSE: 131.757333
# t+9 RMSE: 171.576859
# t+10 RMSE: 164.078086
# t+11 RMSE: 189.710840
# t+12 RMSE: 135.071027
# t+13 RMSE: 176.108870
# t+14 RMSE: 123.596369
# t+15 RMSE: 176.243116
# t+16 RMSE: 158.860359
# t+17 RMSE: 146.936220
# t+18 RMSE: 146.639956
# t+19 RMSE: 153.618794
# t+20 RMSE: 147.312042
# t+21 RMSE: 149.182079
# t+22 RMSE: 138.054920
# t+23 RMSE: 145.804312
# t+24 RMSE: 166.382771
# t+25 RMSE: 143.922779
# t+26 RMSE: 156.105344
# t+27 RMSE: 115.304277
# t+28 RMSE: 135.514702
# t+29 RMSE: 154.820486
# t+30 RMSE: 188.279115
# t+31 RMSE: 138.019347
# t+32 RMSE: 160.715638
# t+33 RMSE: 173.415381
# t+34 RMSE: 180.411886
# t+35 RMSE: 145.646395
# t+36 RMSE: 128.124628
# t+37 RMSE: 164.583304
# t+38 RMSE: 182.525903
# t+39 RMSE: 145.345988
# t+40 RMSE: 172.166096
# t+41 RMSE: 129.625155
# t+42 RMSE: 137.745757
# t+43 RMSE: 198.990463
# t+44 RMSE: 166.928849
# t+45 RMSE: 171.436070
# t+46 RMSE: 186.811325
# t+47 RMSE: 144.422246
# t+48 RMSE: 156.781829
# t+49 RMSE: 172.120825
# t+50 RMSE: 149.682804
# t+51 RMSE: 141.673213
# t+52 RMSE: 172.357648
# t+53 RMSE: 158.622753
# t+54 RMSE: 184.421916
# t+55 RMSE: 171.320013
# t+56 RMSE: 106.285773
# t+57 RMSE: 114.165503
# t+58 RMSE: 124.827654
# t+59 RMSE: 102.873840
# t+60 RMSE: 134.097910
# total rmse: 9274.59023828
def plot_forecasts(series, test, forecasts, n_in, n_out):
t = pd.DataFrame(test)
f = pd.DataFrame(forecasts)
t.iloc[:,n_in:n_in+n_out] = f.values
t['idx'] = len(series) + t.index.values - n_in - len(test) -n_out
# plot the forecasts in red
for i in range(len(forecasts)):
xaxis = np.array([t.loc[i,'idx']] * (n_in+n_out)) + np.array(range((n_in+n_out)))
yaxis = t.iloc[i,:-1].values
plt.plot(xaxis, yaxis, color='red')
# plot the entire dataset in blue
plt.plot(series.values)
plt.show()
plot_forecasts(train,actual,forecasts[-1],n_in,n_out)
图片:
以上是最新预测图(测试集:需要使用360点,其中前300个是LSTM的输入,最后60个将与红色显示的预测进行比较)。对于我放入的任何点,输出大约值200的相同锯齿线。这是一个使用不同300点的放大外观:
在预测中删除model.reset_states()后,RMSE减少到,图表看起来不同:
t+1 RMSE: 56.001612
t+2 RMSE: 55.304949
t+3 RMSE: 54.572932
t+4 RMSE: 53.878164
t+5 RMSE: 53.252430
t+6 RMSE: 52.709159
t+7 RMSE: 52.188684
t+8 RMSE: 51.722300
t+9 RMSE: 51.298685
t+10 RMSE: 50.909361
t+11 RMSE: 50.534432
t+12 RMSE: 50.153235
t+13 RMSE: 49.843989
t+14 RMSE: 49.544826
t+15 RMSE: 49.251911
t+16 RMSE: 48.953321
t+17 RMSE: 48.736308
t+18 RMSE: 48.524235
t+19 RMSE: 48.319380
t+20 RMSE: 48.123144
t+21 RMSE: 47.924274
t+22 RMSE: 47.724813
t+23 RMSE: 47.548941
t+24 RMSE: 47.430078
t+25 RMSE: 47.320304
t+26 RMSE: 47.237417
t+27 RMSE: 47.138287
t+28 RMSE: 47.041020
t+29 RMSE: 46.933505
t+30 RMSE: 46.832966
t+31 RMSE: 46.733669
t+32 RMSE: 46.637092
t+33 RMSE: 46.564030
t+34 RMSE: 46.419809
t+35 RMSE: 46.220688
t+36 RMSE: 46.112665
t+37 RMSE: 46.053153
t+38 RMSE: 45.999633
t+39 RMSE: 45.950166
t+40 RMSE: 45.903748
t+41 RMSE: 45.861863
t+42 RMSE: 45.825802
t+43 RMSE: 45.798098
t+44 RMSE: 45.776262
t+45 RMSE: 45.702105
t+46 RMSE: 45.659707
t+47 RMSE: 45.613096
t+48 RMSE: 45.577615
t+49 RMSE: 45.554801
t+50 RMSE: 45.531822
t+51 RMSE: 45.506663
t+52 RMSE: 45.485158
t+53 RMSE: 45.461476
t+54 RMSE: 45.400751
t+55 RMSE: 45.365654
t+56 RMSE: 45.334558
t+57 RMSE: 45.316315
t+58 RMSE: 45.300184
t+59 RMSE: 45.253731
t+60 RMSE: 45.223637
total rmse: 2870.0986146
图片:
编辑:添加几个点和输出。任何300输入都输出相同的60个点。