Ale*_*152 5 python machine-learning lstm keras tensorflow
我刚刚开始在keras中使用LSTM,我发现学习时间序列行为的可能性非常有趣。我已经在线阅读了几篇教程和文章,其中大多数都显示了令人印象深刻的预测时间序列的功能,因此我尝试了一下。我注意到的第一件事是,我发现的所有文章始终以非常不公平的方式使用验证数据。我预测时间序列的想法是,我使用训练数据来构建模型,并使用训练数据的最后N个元素来估计序列的未来行为。为此,该模型必须使用自己的预测作为输入,以便将来向前迈进。
我所看到的人们正在做的是,使用地面实况作为估计的输入来估计将来任何时候的测试集的准确性。这是非常不公平的,因为它不能产生真实的预测!
我尝试用Keras编写我自己的LSTM预测(请在下面找到代码),然后从一个相对简单的案例开始,即抛物线和正弦曲线的组合。不幸的是,结果令人非常不满意。以下是通过更改网络参数获得的一些示例:
您有什么建议以获得更好的结果吗?如果LSTM无法预测这样的“简单”信号,那么它们如何预测?
谢谢亚历山德罗
import os
import numpy as np
from matplotlib import pyplot as plt
import keras
# Number of vectors to consider in the time window
look_back = 50
N_datapoints = 2000
train_split = 0.8
# Generate a time signal composed of a linear function and a sinusoid
t = np.linspace(0, 200, N_datapoints)
y = t**2 + np.sin(t*2)*1000
y -= y.mean()
y /= y.std()
plt.plot(y)
# Reshape the signal into fixed windows for training
def create_blocks(y, look_back=1):
x_data, y_data = [], []
for i in range(0, len(y)-look_back-1):
x_data.append(y[i:i+look_back])
y_data.append(y[i+look_back])
return np.array(x_data), np.array(y_data)
x_data, y_data = create_blocks(y, look_back)
# Split data in training and testing
N_train = int(x_data.shape[0]*train_split)
x_train = x_data[:N_train, :, None]
y_train = y_data[:N_train, ]
x_test = x_data[N_train:-1, :, None]
y_test = y_data[N_train:-1:, ]
# Get the time vector for train and test (just to plot)
t_train = t[0:N_train-1, None]
t_test = t[N_train:-1, None]
# Network
from keras import Model, Input
from keras.layers import LSTM, Dense, Activation, BatchNormalization, Dropout
inputs = Input(shape=(look_back, 1))
net = LSTM(32, return_sequences=False)(inputs)
net = Dense(32)(net)
net = Dropout(0.25)(net)
outputs = Dense(1)(net)
model = Model(inputs=inputs, outputs=outputs)
model.compile(optimizer=keras.optimizers.rmsprop(), loss='mean_squared_error')
model.summary()
# Callback
from keras.callbacks import Callback
class PlotResuls(Callback):
def on_train_begin(self, logs=None):
self.fig = plt.figure()
def save_data(self, x_test, y, look_back, t_test):
self.x_test = x_test
self.y = y
self.t_test = t_test
self.look_back = look_back
def on_epoch_end(self, epoch, logs=None):
if epoch % 20 == 0:
plt.clf()
y_pred = self.x_test[0, ...]
for i in range(len(x_test)+1):
new_prediction = model.predict(y_pred[None, -self.look_back:, ])
y_pred = np.concatenate((y_pred, new_prediction), axis=0)
plt.plot(t, y, label='GT')
plt.plot(self.t_test, y_pred, '.-', label='Predicted')
plt.legend()
plt.pause(0.01)
plt.savefig('lstm_%d.png' % epoch)
plot_results = PlotResuls()
plot_results.save_data(x_test, y, look_back, t_test)
model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=100000, batch_size=32, callbacks=[plot_results])
Run Code Online (Sandbox Code Playgroud)
如Primusa的答案中所示,允许递归层使用return_sequences=True
以及Bidirectional
已显示出更好地捕获时间模式的层一起输出其隐藏状态是有帮助的。此外,我认为您需要对要尝试近似的功能有某种直觉-尝试将其分解为多个功能,并为每个功能构建一个子网通常可以加快学习过程,尤其是在使用适当的激活组合时。应用权重正则化也很重要,因为它可能会由于错误累积而停止极端差异。另请注意,除非您使用stateful=True
,您将需要为网络提供足够长的时间范围以检查远程模式(即,如果时间窗口较小,则抛物线很容易近似为一条线)。
具体而言,以下更改在20个周期后实现(1.0223e-04 / 0.0015)的(仍然迅速降低)MSE,在100个周期后实现(2.8111e-05 / 3.0393e-04)的MSE,回溯为100(请注意,也将您的优化器更改为Adam(我只是更喜欢)):
from keras import Model, Input
from keras.layers import (LSTM, Dense, Activation, BatchNormalization,
Dropout, Bidirectional, Add)
inputs = Input(shape=(look_back, 1))
bd_seq = Bidirectional(LSTM(128, return_sequences=True,
kernel_regularizer='l2'),
merge_mode='sum')(inputs)
bd_sin = Bidirectional(LSTM(32, return_sequences=True,
kernel_regularizer='l2'),
merge_mode='sum') (bd_seq)
bd_1 = Bidirectional(LSTM(1, activation='linear'),
merge_mode='sum')(bd_seq)
bd_2 = Bidirectional(LSTM(1, activation='tanh'),
merge_mode='sum')(bd_sin)
output = Add()([bd_1, bd_2])
model = Model(inputs=inputs, outputs=output)
model.compile(optimizer='adam', loss='mean_squared_error')
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
679 次 |
最近记录: |