我正在训练一个文本分类模型,其中输入数据由 4096 个词频 - 逆向文档频率组成。
我的输出是 416 个可能的类别。每条数据有 3 个类别,所以 413 个零的数组中有 3 个(one-hot-encodings)
我的模型是这样的:
model = Sequential()
model.add(Dense(2048, activation="relu", input_dim=X.shape[1]))
model.add(Dense(512, activation="relu"))
model.add(Dense(416, activation="sigmoid"))
当我用 binary_crossentropy 损失训练它时,它的损失为 0.185,一个时期后的准确率为 96%。 5 个 epoch 后,损失为 0.037,准确率为 99.3%。我猜这是错误的,因为我的标签中有很多 0,它正确分类了。
当我用 categorical_crossentropy 损失训练它时,它在前几个时期的损失为 15.0,准确度低于 5%,然后卡在损失 5.0 和准确度以下几个(超过 50 个)epoch 后 12%。
其中哪一个适合我的情况(具有多个 1 的大型 one-hot-encodings)?这些分数告诉我什么?
编辑:这些是 model.compile() 语句:
model.compile(loss='categorical_crossentropy',
optimizer=keras.optimizers.Adam(),
metrics=['accuracy'])
和
model.compile(loss='binary_crossentropy',
optimizer=keras.optimizers.Adam(),
metrics=['accuracy'])
请您参考如下方法:
简而言之:使用 loss='binary_crossentropy' 时报告的(高)准确度正如您已经猜到的那样,不是正确的。对于您的问题,建议损失为 categorical_crossentropy .
长:
这种行为的根本原因是一个相当微妙且未记录的问题,即当您简单地包含 metrics=['accuracy'] 时,Keras 实际上如何猜测使用哪种精度,具体取决于您选择的损失函数。在您的模型编译中,就像您一样。换句话说,当你的第一个编译选项
model.compile(loss='categorical_crossentropy',
optimizer=keras.optimizers.Adam(),
metrics=['accuracy']
是有效的,你的第二个:
model.compile(loss='binary_crossentropy',
optimizer=keras.optimizers.Adam(),
metrics=['accuracy'])
不会产生您期望的结果,但原因不是使用二元交叉熵(至少在原则上,这是一个绝对有效的损失函数)。
这是为什么呢?如果您检查 metrics source code , Keras 没有定义单一的精度指标,而是定义了几个不同的指标,其中 binary_accuracy和 categorical_accuracy .会发生什么under the hood就是这样,因为您选择了 loss='binary_crossentropy'并且没有指定特定精度指标,Keras(错误地...)推断您对 binary_accuracy 感兴趣,这就是它返回的内容——而实际上您对 categorical_accuracy 感兴趣.
让我们使用 MNIST CNN example 来验证情况是否如此。在 Keras 中,进行以下修改:
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # WRONG way
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=2, # only 2 epochs, for demonstration purposes
verbose=1,
validation_data=(x_test, y_test))
# Keras reported accuracy:
score = model.evaluate(x_test, y_test, verbose=0)
score[1]
# 0.9975801164627075
# Actual accuracy calculated manually:
import numpy as np
y_pred = model.predict(x_test)
acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000
acc
# 0.98780000000000001
score[1]==acc
# False
可以说,用您自己的数据验证上述行为应该很简单。
为了讨论的完整性,如果出于某种原因,你坚持使用二元交叉熵作为你的损失函数(正如我所说,这没有错,至少在原则上是这样),同时仍然得到 分类手头问题所需的准确性,您应该明确要求categorical_accuracy在模型编译中如下:
from keras.metrics import categorical_accuracy
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=[categorical_accuracy])
在 MNIST 示例中,在如上所示对测试集进行训练、评分和预测之后,这两个指标现在是相同的,因为它们应该是:
# Keras reported accuracy:
score = model.evaluate(x_test, y_test, verbose=0)
score[1]
# 0.98580000000000001
# Actual accuracy calculated manually:
y_pred = model.predict(x_test)
acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000
acc
# 0.98580000000000001
score[1]==acc
# True
系统设置:
Python version 3.5.3
Tensorflow version 1.2.1
Keras version 2.0.4
