我正在尝试训练 CNN 按主题对文本进行分类。当我使用二元交叉熵时,我得到约 80% 的准确度,而使用分类交叉熵时,我得到约 50% 的准确度。
我不明白为什么会这样。这是一个多类问题,这是否意味着我必须使用分类交叉熵并且二进制交叉熵的结果没有意义?
model.add(embedding_layer) model.add(Dropout(0.25)) # convolution layers model.add(Conv1D(nb_filter=32, filter_length=4, border_mode='valid', activation='relu')) model.add(MaxPooling1D(pool_length=2)) # dense layers model.add(Flatten()) model.add(Dense(256)) model.add(Dropout(0.25)) model.add(Activation('relu')) # output layer model.add(Dense(len(class_id_index))) model.add(Activation('softmax'))
categorical_crossentropy然后我像这样使用损失函数编译它:
categorical_crossentropy
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
或者
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
直观地说,为什么我要使用分类交叉熵是有道理的,我不明白为什么我用二进制得到好的结果,而用分类的结果却很差。
分类和二元交叉熵之间存在明显性能差异的原因是用户 xtof54在他的回答中已经报告了以下)内容,即:
evaluate当使用带有超过 2 个标签的 binary_crossentropy 时,使用Keras 方法计算的准确度完全错误
evaluate
我想详细说明这一点,展示实际的潜在问题,解释它,并提供补救措施。
这种行为不是错误;根本原因是一个相当微妙且未记录的问题,即当您简单地包含在模型编译中时, Keras 如何根据您选择的损失函数实际 猜测要使用的准确度。metrics=['accuracy']换句话说,当你的第一个编译选项
metrics=['accuracy']
是有效的,你的第二个:
不会产生您期望的结果,但原因不是使用二元交叉熵(至少在原则上,这是一个绝对有效的损失函数)。
这是为什么?如果查看指标源代码,Keras 并没有定义一个单一的准确度指标,而是定义了几个不同的指标,其中binary_accuracy和categorical_accuracy. 幕后发生的事情是,由于您选择二元交叉熵作为损失函数并且没有指定特定的准确度指标,Keras(错误地......)推断您对 感兴趣binary_accuracy,这就是它返回的内容 -而实际上你对categorical_accuracy.
binary_accuracy
categorical_accuracy
让我们使用 Keras 中的MNIST CNN 示例验证是否是这种情况,并进行以下修改:
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
更新 :在我的帖子之后,我发现这个问题已经在这个答案中确定了。