Keras: 大型独热编码:使用binary_crossentropy还是categorical_crossentropy

我正在训练一个文本分类模型,输入数据由4096个词频-逆文档频率组成。

我的输出有416个可能的类别。每个数据有3个类别,所以在一个包含413个零的数组中会有3个一(独热编码)。

我的模型如下所示:

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损失函数进行训练时,经过一个epoch后损失为0.185,准确率为96%。经过5个epoch后,损失降至0.037,准确率达到99.3%。我猜测这是错误的,因为我的标签中有很多零,它正确地分类了这些零。

当我使用categorical_crossentropy损失函数进行训练时,在最初几个epoch中损失为15.0,准确率低于5%,之后在经过多个(超过50个)epoch后,损失稳定在5.0,准确率为12%。

在我的情况下(大型独热编码且有多个1),使用哪种损失函数是正确的?这些分数告诉我什么信息?

编辑:这是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


详细说明:

这种行为背后的原因是一个相当微妙且未记录的问题,关于Keras如何根据你选择的损失函数来猜测使用哪种准确率,当你在模型编译时简单地使用metrics=['accuracy'],如你所做的那样。换句话说,虽然你的第一个编译选项

model.compile(loss='categorical_crossentropy',          optimizer=keras.optimizers.Adam(),          metrics=['accuracy']

是有效的,但你的第二个选项:

model.compile(loss='binary_crossentropy',          optimizer=keras.optimizers.Adam(),          metrics=['accuracy'])

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

为什么会这样呢?如果你查看度量源代码,Keras并没有定义单一的准确率度量,而是定义了多个不同的度量,其中包括binary_accuracycategorical_accuracy。在幕后,由于你选择了loss='binary_crossentropy'并且没有指定特定的准确率度量,Keras(错误地…)推断你对binary_accuracy感兴趣,并返回这个值——而实际上你对categorical_accuracy感兴趣。

让我们验证这是真的,使用Keras中的MNIST CNN示例,并进行以下修改:

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])  # 错误的方法model.fit(x_train, y_train,          batch_size=batch_size,          epochs=2,  # 只运行2个epoch,仅供演示          verbose=1,          validation_data=(x_test, y_test))# Keras报告的准确率:score = model.evaluate(x_test, y_test, verbose=0) score[1]# 0.9975801164627075# 手动计算的实际准确率:import numpy as npy_pred = model.predict(x_test)acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000acc# 0.98780000000000001score[1]==acc# False    

可以说,使用你自己的数据验证上述行为应该是直接的。

为了讨论的完整性,如果出于某种原因,你坚持使用二元交叉熵作为你的损失函数(正如我所说,至少在原则上,这没有问题),但仍然需要获取问题所需的分类准确率,你应该在模型编译时明确请求categorical_accuracy,如下所示:

from keras.metrics import categorical_accuracymodel.compile(loss='binary_crossentropy', optimizer='adam', metrics=[categorical_accuracy])

在MNIST示例中,训练后,评分并预测测试集如我上面所示,现在这两个度量值是相同的,正如它们应该的那样:

# Keras报告的准确率:score = model.evaluate(x_test, y_test, verbose=0) score[1]# 0.98580000000000001# 手动计算的实际准确率:y_pred = model.predict(x_test)acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000acc# 0.98580000000000001score[1]==acc# True    

系统设置:

Python version 3.5.3Tensorflow version 1.2.1Keras version 2.0.4

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注