我正在训练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作为损失函数编译它:

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

or

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

直观地说,我为什么要使用分类交叉熵,我不明白为什么我用二进制得到好的结果,而用分类得到的结果很差。


当前回答

您正在传递一个形状的目标数组(x-dim, y-dim),同时使用作为损失categorical_crossentropy。Categorical_crossentropy期望目标是形状(样本,类)的二进制矩阵(1和0)。如果你的目标是整数类,你可以通过以下方法将它们转换为预期的格式:

from keras.utils import to_categorical
y_binary = to_categorical(y_int)

或者,您也可以使用损失函数sparse_categorical_crossentropy,它需要整数目标。

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

其他回答

由于这是一个多类问题,你必须使用categorical_crossentropy,二元交叉熵会产生虚假的结果,很可能只会评估前两个类。

对于一个多类问题,50%的概率是相当不错的,这取决于类的数量。如果您有n个类,那么100/n是通过输出一个随机类可以获得的最小性能。

这完全取决于你要处理的分类问题的类型。主要有三个类别

二元分类(两个目标类), 多类分类(两个以上专属目标), 多标签分类(两个以上的非排他目标),其中多个目标类别可以同时打开。

在第一种情况下,应该使用二进制交叉熵,目标应该被编码为单热向量。

在第二种情况下,应使用分类交叉熵,并将目标编码为单热向量。

在最后一种情况下,应该使用二进制交叉熵和目标应该编码为一个热向量。每个输出神经元(或单元)被视为一个单独的随机二进制变量,整个输出向量的损失是单个二进制变量损失的乘积。因此,它是每个单个输出单元的二进制交叉熵的乘积。

二元交叉熵定义为

分类交叉熵定义为

其中c是运行在c类数量上的索引。

您正在传递一个形状的目标数组(x-dim, y-dim),同时使用作为损失categorical_crossentropy。Categorical_crossentropy期望目标是形状(样本,类)的二进制矩阵(1和0)。如果你的目标是整数类,你可以通过以下方法将它们转换为预期的格式:

from keras.utils import to_categorical
y_binary = to_categorical(y_int)

或者,您也可以使用损失函数sparse_categorical_crossentropy,它需要整数目标。

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

在评论@Marcin的答案后,我更仔细地检查了我的一个学生的代码,在那里我发现了同样奇怪的行为,即使只有2个纪元!(所以@Marcin的解释在我的情况下不太可能)。

我发现答案其实很简单:当使用超过2个标签的binary_crossentropy时,用Keras方法evaluate计算的准确性完全错误。你可以自己重新计算准确率(首先调用Keras方法“predict”,然后计算由predict返回的正确答案的数量):你得到了真正的准确率,这比Keras的“evaluate”要低得多。

看一下这个方程,你会发现二进制交叉熵不仅惩罚了label = 1, predicted =0,而且也惩罚了label =0, predicted = 1。

然而,分类交叉熵只惩罚那些标签= 1但预测= 1的人。这就是为什么我们假设只有一个标签是正的。