为了账号安全,请及时绑定邮箱和手机立即绑定

Keras binary_crossentropy vs categorical

/ 猿问

Keras binary_crossentropy vs categorical

倚天杖 2019-09-19 10:56:53

我正在尝试培训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'])

要么


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


查看完整描述

3 回答

?
翻翻过去那场雪

分类和二元交叉熵之间明显的性能差异的原因是@ xtof54在他的答案中已经报道了,即:


evaluate当使用带有2个以上标签的binary_crossentropy时,使用Keras方法计算的精度是完全错误的


我想详细说明这一点,展示实际的根本问题,解释它,并提供补救措施。


这种行为不是一个bug; 根本原因是Keras实际上猜测使用哪种准确度是一个相当微妙和无证的问题,这取决于你选择的损失函数,当你简单地包含metrics=['accuracy']在你的模型编译中时。换句话说,当你的第一个编译选项


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

是有效的,你的第二个:


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

不会产生你所期望的,但原因不是使用二元交叉熵(至少在原理上,这是一个绝对有效的损失函数)。


这是为什么?如果您检查指标的源代码,Keras没有定义一个准确的度量,但有几个不同的,其中binary_accuracy和categorical_accuracy。发生了什么事情,因为你选择了二进制交叉熵作为你的损失函数并且没有指定一个特定的精度度量,Keras(错误地......)推断你对它感兴趣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


查看完整回答
反对 回复 2019-09-19
?
翻过高山走不出你

这一切都取决于您正在处理的分类问题的类型。主要有三类;

  • 二元分类(两个目标类)

  • 多级分类(超过两个独家目标)

  • 多标签分类(超过两个非独占目标),其中多个目标类可以同时打开

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

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

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

二元交叉熵定义如下: 二元交叉熵 和分类交叉熵定义如下: 分类交叉熵


查看完整回答
反对 回复 2019-09-19
?
慕虎7371278

我遇到了一个“倒置”的问题 - 我使用categorical_crossentropy(有2个类)并且使用binary_crossentropy很差。似乎问题是错误的激活功能。正确的设置是:

  • for binary_crossentropy:sigmoid激活,标量目标

  • for categorical_crossentropy:softmax激活,单热编码目标


查看完整回答
反对 回复 2019-09-19

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信