我正在尝试训练一个简单的LSTM以适应一条线。我的假设是,我应该能够在零输入的情况下适应线性下降的趋势,因为LSTM可以决定它侦听其输入与内部状态之间的关系,从而可以学习仅对内部状态进行操作。基本上是一个退化的案例,用于测试LSTM是否可以用零输入满足预期结果。
我创建我的输入和目标数据:
seq_len = 1000
x_train = np.zeros((1, seq_len, 1)) # [batch_size, seq_len, num_feat]
target = np.linspace(100, 0, num=seq_len).reshape(1, -1, 1)
我创建了一个非常简单的网络:
from keras.models import Model
from keras.layers import LSTM, Dense, Input, TimeDistributed
x_in = Input((seq_len, 1))
seq1 = LSTM(8, return_sequences=True)(x_in)
dense1 = TimeDistributed(Dense(8))(seq1)
seq2 = LSTM(8, return_sequences=True)(dense1)
dense2 = TimeDistributed(Dense(8))(seq2)
out = TimeDistributed(Dense(1))(dense2)
model = Model(inputs=x_in, outputs=out)
model.compile(optimizer='adam', loss='mean_squared_error')
history = model.fit(x_train, target, batch_size=1, epochs=1000,
validation_split=0.)
我还创建了一个自定义回调,该回调在每个纪元后调用model.predict(x_train)
并将结果添加到数组中,以便我可以看到模型输出随时间的变化情况。基本上,模型只是学习预测一个恒定值,该值逐渐(渐近地)接近我的目标线的平均值(目标线为红色,不确定为什么图例不显示):
所以基本上没有什么驱动我做出适合实际线条的响应,我只是逐渐接近线条的平均值。我怀疑我没有得到关于时间(数据索引)的任何梯度,只是随时间的平均梯度。但是我本以为LSTM的损失会自动为您提供随时间变化的梯度。
我尝试过:
None
,'relu'
分别用于常规激活和循环激活)'nadam'
,'adadelta'
,'rmsprop'
)'mean_aboslute_error'
损失函数,我没想到它会改善结果,并且作用大致相同LSTM
代替GRU
似乎什么也没做。
有人建议我如何根据我的序列索引(即g(t)
)来强制该事物在梯度上进行训练?或关于如何使它工作的其他建议?
注意:具有所示趋势,如果LSTM得出的平均值恰好是平均值(50),则最小平均绝对误差将为25,最小均方误差将为约835.8。因此,如果我们没有看到比这更好的了,那我们可能就不适合这条线,只是平均值。
只是一些参考,以防您自己运行。