LSTM Keras - Many to many classification Value error: incompatible shapes

LSTM Keras - Many to many classification Value error: incompatible shapes

我刚刚开始使用 Tensorflow/Keras 在 Python 中实现 LSTM 来测试我的想法,但是我正在努力正确地创建模型。 post 主要是关于我经常遇到的值错误(请参阅底部的代码),但是非常感谢为以下问题创建正确的 LSTM 模型的任何和所有帮助。

对于每一天,我都想预测一组事件中的哪一个会发生。这个想法是一些事件在经过一定时间后重复出现/总是发生,而其他事件很少发生或没有任何结构。 LSTM 应该能够识别这些重复发生的事件,以便预测它们在未来几天内的发生。

为了显示事件,我使用了一个值为 0 和 1(未发生和发生)的列表。例如,如果我有事件 ["Going to school", "Going to the gym", "Buying a computer"] 我有 [1, 0, 1], [1, 1, 0], [1 , 0, 1], [1, 1, 0] 等。然后 LSTM 会识别出我每天上学,每隔一天去一次健身房,而且很少买电脑。所以按照向量序列,第二天它应该预测 [1,0,0].

到目前为止,我已经完成了以下工作:

  1. 创建 x_train:形状为 (305, 60, 193) 的 numpy.array。 x_train 的每个条目包含连续 60 天,其中一天由可以如上所述发生的相同 193 个事件的向量表示。
  2. 创建 y_train:一个形状为 (305, 1, 193) 的 numpy.array。类似于 x_train,但 y_train 每个条目仅包含 1 天。

x_train[0] 包含第 1,2,...,60 天,y_train[0] 包含第 61 天。x_train[1] 包含第 2 天,...,61 和 y_train[1] 包含第 62 天等。这个想法是 LSTM 应该学习使用过去 60 天的数据,然后它可以迭代地开始 predicting/generating未来几天事件发生的新向量。

我真的很苦恼如何创建一个简单的 LSTM 实现来处理这个问题。到目前为止,我想我已经弄清楚了以下几点:

  1. 我需要从下面的代码块开始,其中 N_INPUTS = 60N_FEATURES = 193。我不确定 N_BLOCKS 应该是什么,或者它应该取的值是否受到某些条件的严格约束。编辑:根据 https://zhuanlan.zhihu.com/p/58854907 它可以是我想要的任何东西
model = Sequential()
model.add(LSTM(N_BLOCKS, input_shape=(N_INPUTS, N_FEATURES)))
  1. 我应该添加一个致密层。如果我希望我的 LSTM 的输出是包含 193 个事件的向量,它应该如下所示:
model.add(layers.Dense(193,activation = 'linear') #or some other activation function
  1. 我还可以添加一个 dropout 层来防止过度拟合,例如 model.add.layers.dropout(0.2) 其中 0.2 是设置为 0 的某个速率。
  2. 我需要添加一个 model.compile(loss = ..., optimizer = ...)。如果我只想要一个有效的实现,我不确定损失函数(例如 MSE 或 categorical_crosstentropy)和优化器是否重要。
  3. 我需要训练我的模型,我可以使用 model.fit(x_train,y_train)
  4. 来实现
  5. 如果以上所有方法都有效,我可以开始使用 model.predict(the 60 days before the day I want to predict)
  6. 预测第二天的值

我的一个尝试可以在这里看到:

print(x_train.shape)
print(y_train.shape)

model = keras.Sequential()
model.add(layers.LSTM(256, input_shape=(x_train.shape[1], x_train.shape[2])))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(y_train.shape[2], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
model.fit(x_train,y_train) #<- This line causes the ValueError

Output:
(305, 60, 193)
(305, 1, 193)
Model: "sequential_29"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 lstm_27 (LSTM)              (None, 256)               460800    
                                                                 
 dense_9 (Dense)             (None, 1)                 257       
                                                                 
=================================================================
Total params: 461,057
Trainable params: 461,057
Non-trainable params: 0
_________________________________________________________________
ValueError: Shapes (None, 1, 193) and (None, 193) are incompatible 

或者,我尝试用 model.add(layers.Dense(y_train.shape[1], activation='softmax')) 替换行 model.add(layers.Dense(y_train.shape[2], activation='softmax'))。这会产生 ValueError: Shapes (None, 1, 193) and (None, 1) are incompatible .

我的想法可以吗?如何解决此值错误?任何帮助将不胜感激。

编辑:正如评论中所建议的那样,改变 y_train 的大小就成功了。

print(x_train.shape)
print(y_train.shape)

model = keras.Sequential()
model.add(layers.LSTM(193, input_shape=(x_train.shape[1], x_train.shape[2]))) #De 193 mag ieder mogelijk getal zijn. zie: https://zhuanlan.zhihu.com/p/58854907
model.add(layers.Dropout(0.2))
model.add(layers.Dense(y_train.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
model.fit(x_train,y_train)


(305, 60, 193)
(305, 193)
Model: "sequential_40"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 lstm_38 (LSTM)              (None, 193)               298764    
                                                                 
 dropout_17 (Dropout)        (None, 193)               0         
                                                                 
 dense_16 (Dense)            (None, 193)               37442     
                                                                 
=================================================================
Total params: 336,206
Trainable params: 336,206
Non-trainable params: 0
_________________________________________________________________
10/10 [==============================] - 3s 89ms/step - loss: 595.5011

现在我坚持这样一个事实,即 model.predict(x) 要求 x 的大小与 x_train 相同,并将输出一个与 y_train 大小相同的数组。我希望只需要一组 60 天就可以输出第 61 天。有谁知道如何做到这一点?

解决方案可能是 y_train 的形状 (305, 193) 而不是你预测的 (305, 1, 193) 有一天,这不会改变数据,只是它的形状。然后你应该能够训练和预测。 当然还有model.add(layers.Dense(y_train.shape[1], activation='softmax'))