Python Keras:大热门编码:二进制交叉熵或分类交叉熵

Python Keras:大热门编码:二进制交叉熵或分类交叉熵,python,machine-learning,keras,neural-network,deep-learning,Python,Machine Learning,Keras,Neural Network,Deep Learning,我正在训练一个文本分类模型,其中输入数据由4096个术语频率-反向文档频率组成 我的输出是416个可能的类别。每段数据有3个类别,因此在413个零的数组中有3个1(一个热编码) 我的模型如下所示: model=Sequential() 添加模型(密集(2048,activation=“relu”,input_dim=X.shape[1])) 添加(密集(512,activation=“relu”)) 添加(密集(416,activation=“sigmoid”)) 当我用binary_cros

我正在训练一个文本分类模型,其中输入数据由4096个术语频率-反向文档频率组成

我的输出是416个可能的类别。每段数据有3个类别,因此在413个零的数组中有3个1(一个热编码)

我的模型如下所示:

model=Sequential()
添加模型(密集(2048,activation=“relu”,input_dim=X.shape[1]))
添加(密集(512,activation=“relu”))
添加(密集(416,activation=“sigmoid”))
当我用binary_crossentropyloss对它进行训练时,一个历元后它的损失为0.185,准确率为96%。经过5个时代,损失为0.037,准确率为99.3%。我想这是错误的,因为我的标签中有很多0,它可以正确地分类

当我用
categorical_crossentropy
loss对它进行训练时,它在最初的几个时代损失了15.0,准确率低于5%,而在几个(超过50个)时代之后,它却陷入了5.0的损失和12%的准确率

其中哪一个适合我的情况(多个1的大1热编码)?这些分数告诉我什么

编辑:这些是
model.compile()
语句:

model.compile(loss='classifical\u crossentropy',
optimizer=keras.optimizers.Adam(),
指标=[‘准确度’])

model.compile(loss='binary\u crossentropy',
optimizer=keras.optimizers.Adam(),
指标=[‘准确度’])
简言之:使用
loss='binary\u crossentropy'
时报告的(高)准确度不是您已经猜到的正确值。对于您的问题,建议的损失是
categorical\u crossentropy


总之:

这种行为的根本原因是一个相当微妙且未记录的问题,即当您在模型编译中简单地包含
metrics=['accurity']
时,Keras如何根据您选择的损失函数猜测使用哪种精度。换句话说,当您的第一个编译选项

model.compile(loss='classifical\u crossentropy',
optimizer=keras.optimizers.Adam(),
指标=['准确度']
是有效的,您的第二个:

model.compile(loss='binary\u crossentropy',
optimizer=keras.optimizers.Adam(),
指标=[‘准确度’])
不会产生您期望的结果,但原因不是使用二进制交叉熵(至少在原则上,这是一个绝对有效的损失函数)

为什么会这样?如果你检查,Keras没有定义一个单一的精度指标,而是定义了几个不同的精度指标,其中包括
binary\u-accurity
category\u-accurity
。结果是,由于你选择了
loss='binary\u crossentropy'
,并且没有指定特定的精度指标,Keras(错误地…)推断您对二进制精度感兴趣,这就是它返回的结果-而实际上您对分类精度感兴趣

让我们通过以下修改,使用in-Keras验证这种情况:

model.compile(loss='binary\u crossentropy',optimizer='adam',metrics=['accurity'])错误的方式
模型安装(x_系列、y_系列、,
批次大小=批次大小,
epochs=2,#仅2个epochs,用于演示
verbose=1,
验证数据=(x_检验,y_检验)
#Keras报告的准确度:
分数=模型。评估(x_检验,y_检验,详细度=0)
分数[1]
# 0.9975801164627075
#手动计算的实际精度:
将numpy作为np导入
y_pred=模型预测(x_检验)
acc=sum([np.argmax(y_test[i])==np.argmax(y_pred[i]),适用于范围(10000)内的i)/10000
行政协调会
# 0.98780000000000001
分数[1]==acc
#假的
可以说,用您自己的数据验证上述行为应该很简单

为了讨论的完整性,如果出于任何原因,你坚持使用二元交叉熵作为损失函数(正如我所说,这没有错,至少在原则上是这样)在获得手头问题所需的分类准确度的同时,您应该在模型编译中明确要求
分类_准确度
,如下所示:

来自keras.metrics导入分类精度
compile(loss='binary\u crossentropy',optimizer='adam',metrics=[分类精度])
在MNIST示例中,经过培训、评分和预测测试集(如上所示),这两个指标现在应该是相同的:

#Keras报告的准确性:
分数=模型。评估(x_检验,y_检验,详细度=0)
分数[1]
# 0.98580000000000001
#手动计算的实际精度:
y_pred=模型预测(x_检验)
acc=sum([np.argmax(y_test[i])==np.argmax(y_pred[i]),适用于范围(10000)内的i)/10000
行政协调会
# 0.98580000000000001
分数[1]==acc
#真的
系统设置:

Python版本3.5.3
Tensorflow版本1.2.1
Keras版本2.0.4

非常感谢您的回答!有人向我指出,
分类交叉熵
毕竟不是正确的方法,因为我总是要预测3个,而
分类交叉熵
预期的是一个分布。是这样吗?如果是这样,是否值得将
二进制交叉熵
与分类交叉熵一起使用_准确度?@Tutanchamunon正如我所说,当你有多个类时,“标准”损失是
分类交叉熵
;但在(理论上非常差)深度学习领域,在实践中,最终的判断是实验!因此,你可以尝试一下(用我上面建议的补救方法),看看你得到了什么(顺便说一句,你也可以接受答案-谢谢)。无论是谁看了这篇文章:这是一个与Keras有关的编码问题,而不是一个relat