如何为 binary_crossentropy、activation=sigmoid 和 activation=softmax 指定 model.compile?

Posted

技术标签:

【中文标题】如何为 binary_crossentropy、activation=sigmoid 和 activation=softmax 指定 model.compile?【英文标题】:How To specify model.compile for binary_crossentropy, activation=sigmoid and activation=softmax? 【发布时间】:2019-09-19 14:45:53 【问题描述】:

我试图弄清楚如何将activation=sigmoidactivation=softmax 与正确的model.compile() 损失参数相匹配。特别是与binary_crossentropy 相关的那些。

我研究了相关主题并阅读了文档。我还建立了一个模型并让它与sigmoid 一起工作,但不是softmax。而且我无法使用“from_logits”参数使其正常工作。

具体来说,here 它说:

参数: from_logitsoutput 是否预期为 logits 张量。 默认情况下,我们认为output 对概率分布进行编码。

这告诉我,如果您使用sigmoid 激活,您需要“from_logits=True”。对于softmax 激活,默认情况下您需要“from_logits=False”。这里我假设sigmoid 提供logitssoftmax 提供概率分布。

接下来是一些代码:

model = Sequential()
model.add(LSTM(units=128,
               input_shape=(n_timesteps, n_features), 
               return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(units=64, return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(units=32))
model.add(Dropout(0.3))
model.add(Dense(16, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(1, activation='sigmoid'))

注意最后一行是使用sigmoid 激活。那么:

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

这很好用,但它使用的是默认的“from_logits=False”,它期望概率分布。

如果我执行以下操作,它会失败:

model.compile(optimizer=optimizer,
              loss='binary_crossentropy',  
              metrics=['accuracy'],
              from_logits=True) # For 'sigmoid' in above Dense

带有此错误消息:

ValueError:使用 TensorFlow 后端传递给 K.function 的参数“from_logits”无效

如果我尝试使用 softmax 激活:

model.add(Dense(1, activation='softmax'))

它可以运行,但我得到了 50% 的准确度结果。使用sigmoid,我的准确率提高了 99%。 (我正在使用一个非常人为的数据集来调试我的模型,并且期望非常高的准确性。另外,它是一个非常小的数据集,并且会过度拟合,但目前还可以。)

所以我希望我应该能够在编译函数中使用“from_logits”参数。但它不识别该参数。

我还想知道为什么它可以与sigmoid 激活而不是softmax 激活一起使用,以及如何让它与softmax 激活一起使用。

谢谢,

乔恩。

【问题讨论】:

你的keras.__version__tf.__version__是什么?您引用的文档适用于 tf.__version__=='1.13.1' 【参考方案1】:

要在损失函数中使用from_logits,您必须将其传递给BinaryCrossentropy 对象初始化,而不是在模型编译中。

你必须改变这个:

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

到这里:

model.compile(optimizer=optimizer,
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),  
              metrics=['accuracy'])

但是,如果您在网络的最后一层使用 softmax 或 sigmoid,您确实不需要需要from_logits=True。 Softmax 和 sigmoid 输出 [0, 1] 之间的归一化值,在这种情况下被认为是概率。

有关更多信息,请参阅此问题:What is the meaning of the word logits in TensorFlow?


现在要解决您使用 softmax 的 50% 准确率问题,请更改以下代码:

model.add(Dense(1, activation='softmax'))

到这里:

model.add(Dense(2, activation='softmax'))  # number of units = number of classes

请记住,当您使用 softmax 时,您输出的是示例属于每个类的概率。出于这个原因,您需要为每个可能的类设置一个单位,在二进制分类上下文中为 2 个单位。

【讨论】:

这个答案为我节省了很多时间,谢谢你最好的!

以上是关于如何为 binary_crossentropy、activation=sigmoid 和 activation=softmax 指定 model.compile?的主要内容,如果未能解决你的问题,请参考以下文章

python 神经网络损失 = 'categorical_crossentropy' vs 'binary_crossentropy' isse

用于多类分类时 binary_crossentropy 损失的重要性?

Binary_crossentropy 和 Categorical_crossentropy 之间的混淆

为啥对于 Keras 中的多类分类, binary_crossentropy 比 categorical_crossentropy 更准确?

如何为具有生命周期'a的结构实现具有'静态生命周期的特征?

自定义 Keras binary_crossentropy 损失函数不起作用