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].
到目前为止,我已经完成了以下工作:
- 创建 x_train:形状为 (305, 60, 193) 的 numpy.array。 x_train 的每个条目包含连续 60 天,其中一天由可以如上所述发生的相同 193 个事件的向量表示。
- 创建 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 实现来处理这个问题。到目前为止,我想我已经弄清楚了以下几点:
- 我需要从下面的代码块开始,其中
N_INPUTS = 60
和 N_FEATURES = 193
。我不确定 N_BLOCKS
应该是什么,或者它应该取的值是否受到某些条件的严格约束。编辑:根据 https://zhuanlan.zhihu.com/p/58854907 它可以是我想要的任何东西
model = Sequential()
model.add(LSTM(N_BLOCKS, input_shape=(N_INPUTS, N_FEATURES)))
- 我应该添加一个致密层。如果我希望我的 LSTM 的输出是包含 193 个事件的向量,它应该如下所示:
model.add(layers.Dense(193,activation = 'linear') #or some other activation function
- 我还可以添加一个 dropout 层来防止过度拟合,例如
model.add.layers.dropout(0.2)
其中 0.2 是设置为 0 的某个速率。
- 我需要添加一个
model.compile(loss = ..., optimizer = ...)
。如果我只想要一个有效的实现,我不确定损失函数(例如 MSE 或 categorical_crosstentropy)和优化器是否重要。
- 我需要训练我的模型,我可以使用
model.fit(x_train,y_train)
来实现
- 如果以上所有方法都有效,我可以开始使用
model.predict(the 60 days before the day I want to predict)
预测第二天的值
我的一个尝试可以在这里看到:
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'))
。
我刚刚开始使用 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].
到目前为止,我已经完成了以下工作:
- 创建 x_train:形状为 (305, 60, 193) 的 numpy.array。 x_train 的每个条目包含连续 60 天,其中一天由可以如上所述发生的相同 193 个事件的向量表示。
- 创建 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 实现来处理这个问题。到目前为止,我想我已经弄清楚了以下几点:
- 我需要从下面的代码块开始,其中
N_INPUTS = 60
和N_FEATURES = 193
。我不确定N_BLOCKS
应该是什么,或者它应该取的值是否受到某些条件的严格约束。编辑:根据 https://zhuanlan.zhihu.com/p/58854907 它可以是我想要的任何东西
model = Sequential()
model.add(LSTM(N_BLOCKS, input_shape=(N_INPUTS, N_FEATURES)))
- 我应该添加一个致密层。如果我希望我的 LSTM 的输出是包含 193 个事件的向量,它应该如下所示:
model.add(layers.Dense(193,activation = 'linear') #or some other activation function
- 我还可以添加一个 dropout 层来防止过度拟合,例如
model.add.layers.dropout(0.2)
其中 0.2 是设置为 0 的某个速率。 - 我需要添加一个
model.compile(loss = ..., optimizer = ...)
。如果我只想要一个有效的实现,我不确定损失函数(例如 MSE 或 categorical_crosstentropy)和优化器是否重要。 - 我需要训练我的模型,我可以使用
model.fit(x_train,y_train)
来实现
- 如果以上所有方法都有效,我可以开始使用
model.predict(the 60 days before the day I want to predict)
预测第二天的值
我的一个尝试可以在这里看到:
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'))
。