[英]How can I use categorical one-hot labels for training with Keras?
I have inputs that look like this: 我的输入看起来像这样:
[
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
...]
of shape (1, num_samples, num_features)
, and labels that look like this: shape (1, num_samples, num_features)
和看起来像这样的标签:
[
[0, 1]
[1, 0]
[1, 0]
...]
of shape (1, num_samples, 2)
. 形状(1, num_samples, 2)
。
However, when I try to run the following Keras code, I get this error: ValueError: Error when checking model target: expected dense_1 to have 2 dimensions, but got array with shape (1, 8038, 2)
. 但是,当我尝试运行以下Keras代码时,我收到此错误: ValueError: Error when checking model target: expected dense_1 to have 2 dimensions, but got array with shape (1, 8038, 2)
。 From what I've read, this appears to stem from the fact that my labels are 2D, and not simply integers. 从我所读到的,这似乎源于我的标签是2D,而不仅仅是整数。 Is this correct, and if so, how can I use one-hot labels with Keras? 这是否正确,如果是这样, 我如何使用Keras的单热标签?
Here's the code: 这是代码:
num_features = 463
trX = np.random(8038, num_features)
trY = # one-hot array of shape (8038, 2) as described above
def keras_builder(): #generator to build the inputs
while(1):
x = np.reshape(trX, (1,) + np.shape(trX))
y = np.reshape(trY, (1,) + np.shape(trY))
print(np.shape(x)) # (1, 8038, 463)
print(np.shape(y)) # (1, 8038, 2)
yield x, y
model = Sequential()
model.add(LSTM(100, input_dim = num_features))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit_generator(keras_builder(), samples_per_epoch = 1, nb_epoch=3, verbose = 2, nb_worker = 1)
Which promptly throws the error above: 哪个迅速抛出上面的错误:
Traceback (most recent call last):
File "file.py", line 35, in <module>
model.fit_generator(keras_builder(), samples_per_epoch = 1, nb_epoch=3, verbose = 2, nb_worker = 1)
...
ValueError: Error when checking model target: expected dense_1 to have 2 dimensions, but got array with shape (1, 8038, 2)
Thank you! 谢谢!
There are a lot of things that do not add up. 有很多东西没有加起来。
I assume that you are trying to solve a sequential classification task, ie your data is shaped as (<batch size>, <sequence length>, <feature length>)
. 我假设您正在尝试解决顺序分类任务,即您的数据形状为(<batch size>, <sequence length>, <feature length>)
。
In your batch generator you create a batch consisting of one sequence of length 8038 and 463 features per sequence element. 在批生成器中,您创建一个批处理,其中包含一个长度为8038的序列和每个序列元素的463个特征。 You create a matching Y batch to compare against, consisting of one sequence with 8038 elements, each of size 2. 您创建一个匹配的Y批次进行比较,由一个序列组成,其中包含8038个元素,每个元素的大小为2。
Your problem is that Y
does not match up with the output of the last layer. 您的问题是Y
与最后一层的输出不匹配。 Your Y
is 3-dimensional while the output of your model is only 2-dimensional: Y.shape = (1, 8038, 2)
does not match dense_1.shape = (1,1)
. 您的Y
是三维的,而模型的输出只是二维的: Y.shape = (1, 8038, 2)
与dense_1.shape = (1,1)
不匹配。 This explains the error message you get. 这解释了您收到的错误消息。
The solution to this: you need to enable return_sequences=True
in the LSTM layer to return a sequence instead of only the last element (effectively removing the time-dimension). 对此的解决方案:您需要在LSTM层中启用return_sequences=True
以返回序列而不是仅返回最后一个元素(有效地删除时间维度)。 This would give an output shape of (1, 8038, 100)
at the LSTM layer. 这将在LSTM层处给出(1, 8038, 100)
的输出形状。 Since the Dense
layer is not able to handle sequential data you need to apply it to each sequence element individually which is done by wrapping it in a TimeDistributed
wrapper. 由于Dense
层无法处理顺序数据,因此需要将其单独应用于每个序列元素,这是通过将其包装在TimeDistributed
包装器中完成的。 This then gives your model the output shape (1, 8038, 1)
. 然后,这会为您的模型提供输出形状(1, 8038, 1)
。
Your model should look like this: 您的模型应如下所示:
from keras.layers.wrappers import TimeDistributed
model = Sequential()
model.add(LSTM(100, input_dim=num_features, return_sequences=True))
model.add(TimeDistributed(Dense(1, activation='sigmoid')))
This can be easily spotted when examining the summary of the model: 在检查模型摘要时可以很容易地发现这一点:
print(model.summary())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.