【问题标题】:Keras: Big one-hot-encoding: binary_crossentropy or categorical_crossentropyKeras:Big one-hot-encoding:binary_crossentropy 或 categorical_crossentropy
【发布时间】:2018-06-01 18:20:04
【问题描述】:

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

我的输出是 416 个可能的类别。每条数据有 3 个类别,因此在 413 个零的数组中有 3 个 1(one-hot-encodings)

我的模型如下所示:

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 损失对其进行训练时,它的损失为 0.185,一个 epoch 后的准确率为 96%。 5 个 epoch 后,损失为 0.037,准确率为 99.3%。我想这是错误的,因为我的标签中有很多 0,它可以正确分类。

当我使用 categorical_crossentropy 损失对其进行训练时,它在前几个时期的损失为 15.0,准确率低于 5%,之后在几次之后陷入 5.0 的损失和 12% 的准确率(超过 50 个)纪元。

其中哪一个适合我的情况(带有多个 1 的大型 one-hot-encodings)?这些分数告诉我什么?

编辑:这些是model.compile() 声明:

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

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

【问题讨论】:

  • 对于这篇文章的评论者:这是一个与 Keras 相关的编码问题,与统计/机器学习理论或实践无关;因此,它的位置就在这里,而不是在交叉验证中......
  • 只是好奇,为什么你在最后一层使用 'sigmoid' 而不是首选的 'softmax' 激活?

标签: python machine-learning keras neural-network deep-learning


【解决方案1】:

简而言之:正如您已经猜到的那样,当您使用 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'])

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

这是为什么呢?如果你检查metrics source code,Keras 并没有定义一个单一的准确度指标,而是几个不同的指标,其中有binary_accuracycategorical_accuracyunder the hood 发生的情况是,由于您选择了 loss='binary_crossentropy' 并且没有指定 特定 准确度指标,Keras(错误地......)推断您对 binary_accuracy 感兴趣,并且这就是它返回的内容 - 而实际上您对 categorical_accuracy 感兴趣。

让我们在 Keras 中使用 MNIST CNN example 验证是否是这种情况,并进行以下修改:

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

【讨论】:

  • 非常感谢您的回答!有人向我指出 categorical_crossentropy 毕竟不是要走的路,因为我总是必须预测 3 个,而 categorical_crossentropy 则期待一个分布。那正确吗?如果是这样,是否值得将 binary_crossentropy 与 categorical_accuracy 一起使用?
  • @Tutanchamunon 正如我所说,当你有多个类时,“典型”损失是categorical_crossentropy;但是在(理论上很差的)深度学习领域,在实践中,最终的判断是实验!所以,你可以试一试(使用我上面建议的补救措施),看看你得到了什么(顺便说一句,你也可以接受答案 - 谢谢)。
猜你喜欢
  • 2019-04-06
  • 2017-06-07
  • 2021-11-02
  • 2019-04-21
  • 2018-07-10
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 2017-06-21
相关资源
最近更新 更多