我有P
个过程的时间序列,每个过程的长度各不相同,但都包含5个变量(维度)。我试图预测一个测试过程的预计寿命。我使用Keras中的状态LSTM
来解决这个问题。但我不确定我的训练过程是否正确。
我将每个序列分成长度为30
的批次。因此,每个序列的形状为(s_i, 30, 5)
,其中s_i
对于每个P
序列是不同的(s_i = len(P_i)//30
)。我将所有序列附加到我的训练数据中,训练数据的形状为(N, 30, 5)
,其中N = s_1 + s_2 + ... + s_p
。
模型:
# 设计网络
model = Sequential()
model.add(LSTM(32, batch_input_shape=(1, train_X[0].shape[1], train_X[0].shape[2]), stateful=True, return_sequences=True))
model.add(LSTM(16, return_sequences=False))
model.add(Dense(1, activation="linear"))
model.compile(loss='mse', optimizer=Adam(lr=0.0005), metrics=['mse'])
model.summary()
看起来像
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm_1 (LSTM) (1, 30, 32) 4864
_________________________________________________________________
lstm_2 (LSTM) (1, 16) 3136
_________________________________________________________________
dense_1 (Dense) (1, 1) 17
=================================================================
训练循环:
for epoch in range(epochs):
mean_tr_acc = []
mean_tr_loss = []
for seq in range(train_X.shape[0]): #24
# 按批次训练整个序列
for batch in range(train_X[seq].shape[0]): #68
b_loss, b_acc = model.train_on_batch(np.expand_dims(train_X[seq][batch], axis=0), train_Y[seq][batch][-1])
mean_tr_acc.append(b_acc)
mean_tr_loss.append(b_loss)
# 在训练完每个完整序列后重置LSTM的内部状态
model.reset_states()
编辑:
损失图的问题是我在自定义损失中对值进行了除法,使它们变得太小。如果我移除除法并以对数方式绘制损失图,看起来就正常了。
新问题:
训练完成后,我试图进行预测。我向模型展示了一个新过程的30个时间样本;因此,输入形状与训练时的batch_input_shape
相同,即(1, 30, 5)
。我对同一序列的不同批次得到的预测结果都是相同的。
我认为我在训练过程中做了一些错误的事情。
编辑2:
所以,模型只有在训练超过20个周期后才会预测出完全相同的结果。否则,预测值非常接近但仍略有不同。我猜这是由于某种过度拟合造成的。
回答:
通常,当结果相同的时候,是因为你的数据没有进行归一化。我建议你通过一个简单的归一化变换使你的数据中心化,均值为0,标准差为1(即(数据-均值)/标准差)。在训练和测试之前尝试这样转换数据。训练和测试集之间数据归一化方式的差异也会引起问题,这可能是你训练与测试损失差异的原因。始终对所有数据使用相同的归一化技术。