LSTM 序列预测:3d 输入到 2d 输出

数据挖掘 lstm 多标签分类 rnn
2022-03-09 00:18:44

我有这个 LSTM 模型

model = Sequential()
model.add(Masking(mask_value=0, input_shape=(timesteps, features)))
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2, return_sequences=False))
model.add(Dense(features, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

和形状X_train (21, 11, 5), y_train (21, 5)

每个时间步由 5 个特征表示并 return_sequences设置为,False因为我想为 11 个时间步的每个输入序列预测一个 5D 数组(下一个时间步)。

我得到错误

ValueError: y_true 和 y_pred 的输出数量不同 (5!=1)

如果我重塑数据,X_train (21, 11, 5), y_train (21, 1, 5)而不是我得到错误

ValueError:y 的形状无效:(14, 1, 5)

注意:值 14 是因为我使用了交叉验证。

我该怎么办?

编辑

我将模型更改为

model = Sequential()
model.add(Masking(mask_value=0, input_shape=(timesteps, features)))
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(features, activation='sigmoid')) 
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

并使用与以前相同的形状。这里model.summary()给出

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
masking_1 (Masking)          (None, 11, 5)             0         
_________________________________________________________________
lstm_1 (LSTM)                (None, 100)               42400     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 505       
=================================================================

这个想法是产生一个多标签分类训练模型后,我在测试数据上对其进行评估,这就是我得到的:

X[0] = [[0 0 0 0 0],[1 0 0 1 0], ...,[0 0 1 0 0],[0 0 1 0 0]]

y_true[0] = [0 0 1 0 0]

y_pred[0] = 2

这不是我想要的。如何获得与 y_true 形状相同的输出,从而将其转换为多标签分类?

2个回答

你的特点是什么?假设您有一个输出大小为 5 的 softmax 的 Dense 层,这意味着您想要预测的只是 1 个特征,一个具有 5 个选项的分类特征。

如果这不是真的,这里需要有关这些功能的更多信息来提供帮助。

每个特征的 Y 变量应该是大小(num_samples、time_step_len、num_categories_of_feature)。您需要单独对每个分类特征进行一次热编码,这给出了最后一个维度大小 num_categories_of_feature。正如你目前所拥有的那样,Y_train 的大小是 (num_samples, features)。因此,当您提出问题时,网络无法学习序列模式,因为您只能给它最终结果。您应该将 Y_train 数据创建为下一个时间步长的真实值,对于每个时间步长。因此,(num_samples,time_step_len,num_categories_of_feature)。旁注:我只使用 LSTM/RNN 解决了​​一个问题,这就是我的做法。我关心的是完整地学习序列,因为我在预测时的输入是可变的。如果您总是有 11 个时间步长并且总是只想要下一个时间步长预测,那么这可能不适用。我真的不知道说实话。

这是我不完全确定这是否是这样做的唯一方法的地方,但是我认为这个问题想要预测 5 个分类变量的方式,你需要一种为每个变量输出 softmax 的方法。大小“特征”的 softmax 激活,就像您在此处所拥有的一样,正在估计大小为 5 的概率分布,这意味着您的 Y 变量只是具有 5 个潜在值的 1 个分类特征。因此,您需要将网络设置为具有 5 个输出,其中独立的 softmax 输出的大小等于每个变量的类别数。单个 softmax 只能用于估计单个类变量的分布。feat1 的 10 个选项?大小为 10 的 Softmax 等。

losses = {"feat1_output": "categorical_crossentropy", "feat2_output": "categorical_crossentropy", "feat3_output": "categorical_crossentropy", "feat4_output": "categorical_crossentropy", "feat5_output": "categorical_crossentropy"}
lossWeights = {"feat1_output": 1.0, "feat2_output": 1.0, ... , ...}# if everything is equal, dont worry about specifying loss weights.
metrics = {"feat1_output": "categorical_accuracy", "feat2_output": "categorical_accuracy", "feat3_output": "categorical_accuracy", "feat4_output": "categorical_accuracy", "feat5_output": "categorical_accuracy"}
opt = Adam(lr=init_lr,decay=init_lr / num_epochs)
model.compile(loss = losses, loss_weights = lossWeights, optimizer=opt, metrics=metrics)

现在,您将同时优化 5 个损失函数,每个类别预测一个。您现在必须有 5 个 Y 变量数据集,每个数据集的大小(num_samples、time_step_len、num_categories_of_feature)。然后,您将为 fit 函数中的输出提供 5 y 数据集,作为列表。但是,要正确命名输出层,您需要在模型定义中指定输出层的名称。

解决方案

我在这里找到了我的问题的解决方案:https ://github.com/keras-team/keras/issues/9331 我只需要覆盖 KerasClassifier 包装器并使其适用于多标签序列预测。