Keras softmax 激活,category_crossentropy 损失。但输出不是 0, 1

Posted

技术标签:

【中文标题】Keras softmax 激活,category_crossentropy 损失。但输出不是 0, 1【英文标题】:Keras softmax activation, category_crossentropy loss. But output is not 0, 1 【发布时间】:2018-02-01 20:51:48 【问题描述】:

我只用很少的数据训练了一个 epoch 的 CNN 模型。我使用 Keras 2.05。

这是 CNN 模型的(部分)最后 2 层,number_outputs = 201。训练数据输出是一个热编码的 201 输出。

model.add(Dense(200, activation='relu', name='full_2'))
model.add(Dense(40, activation='relu',  name='full_3'))
model.add(Dense(number_outputs, activation='softmax'))

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

模型保存为 h5 文件。然后,使用与上述相同的模型加载保存的模式。 batch_image 是一个图片文件。

prediction = loaded_model.predict(batch_image, batch_size=1)

我得到这样的预测:

ndarray: [[ 0.00498065  0.00497852  0.00498095  0.00496987  0.00497506  0.00496112
   0.00497585  0.00496474  0.00496769  0.0049708   0.00497027  0.00496049
   0.00496767  0.00498348  0.00497927  0.00497842  0.00497095  0.00496493
   0.00498282  0.00497441  0.00497477  0.00498019  0.00497417  0.00497654
   0.00498381  0.00497481  0.00497533  0.00497961  0.00498793  0.00496556
   0.0049665   0.00498809  0.00498689  0.00497886  0.00498933  0.00498056

问题:

    预测数组应该是1, 0?为什么我会得到像输出激活为 sigmoid 的输出,而损失是 binary_crossentropy。怎么了?我想再次强调,该模型并没有真正用数据训练好。它几乎只是用随机权重初始化。

    如果我没有很好地训练网络(还没有收敛),比如只是用随机数初始化权重,那么预测是否仍然是1, 0

    如果我想得到预测的概率,然后,我决定如何解释它,CNN训练好后如何得到概率预测输出?

【问题讨论】:

np.argmax(preds, axis=1) 是你的朋友。 【参考方案1】:

您的输出数量为 201,这就是为什么您的输出为 (1,201) 而不是 (1,0)。您可以轻松仅通过使用 np.argmax 来获取哪个类具有最高值,并且该类是您的模型给定输入的输出。

事实上,即使你只训练了 1 个 epoch,你的模型也学到了一些可能很蹩脚的东西,但它仍然学到了一些东西,并基于此预测了输出。

你在最后一层使用了 softmax 作为你的激活。它以非线性方式对您的输出进行归一化,以便所有类的输出之和等于 1。因此,您为每个类获得的值可以解释为该类作为给定输入的输出的概率由模型决定。(为了更清楚,您可以查看 softmax 函数的工作原理)

最后,每个类都有 0.0049 或类似的值,因为模型不确定您的输入属于哪个类。所以它计算每个类的值,然后 softmax 对其进行归一化。这就是为什么您的输出值在 0 到 1 范围内的原因。

例如,假设我有四个班级,因此其中一个可能的输出可以是 [0.223 0.344 0.122 0.311],最后我们将其视为每个班级的置信度分数。通过查看每个类的置信度分数,我们可以说预测的类是 2,因为它的置信度分数最高,为 0.344。

【讨论】:

感谢您的回复。其实我是想弄清楚为什么数组的值不是1或者0。比如[0, 0, 1, .....0, 0], list length= 201 现在好像是0.00498809。我知道总输出数是 201。但是,价值不是我所期望的。 这是因为模型不确定您的输入属于哪个类。所以它计算每个类的值,然后 softmax 对其进行归一化。这就是为什么您的输出值在 0 到 1 范围内的原因。例如,假设我有四个类别,因此其中一个可能的输出可能类似于 [0.223 0.344 0.122 0.311],最终我们将其视为每个类别的置信度分数.通过查看每个类的置信度得分,我们可以说预测的类是 2,因为它的置信度得分最高,为 0.344。 我明白了! 0.005(数组项值)*201 大约是 1。输出是置信度分数,我必须决定如何解释它。 0.005 是由于模型尚未训练。【参考方案2】:

softmax 层的输出不是 0 或 1。它实际上是一个归一化层加起来为 1。如果你将所有系数相加,它们就会加起来。要获得预测,您应该获得具有最高值的预测。即使技术上没有,您也可以将它们解释为概率。 https://en.wikipedia.org/wiki/Softmax_function 用于定义。

该层用于训练过程,以便能够比较分类分类的预测和真实标签。

优化是必需的,因为优化是在可导出函数(具有梯度)上完成的,并且 0,1 输出将不可导出(甚至不是连续的)。之后对所有这些值进行优化。

一个有趣的例子如下:如果你的真实目标是[0 0 1 0],而你的预测输出是[0.1 0.1 0.6 0.2],即使预测正确,它仍然可以学习,因为它仍然给出非零概率到其他类,您可以在其上计算梯度。

【讨论】:

另一个问题有点偏离原始问题。对于样本 [0 0 1 0],图像 1 输出为 [0.1 0.1 0.6 0.2],图像 2 输出为 [0.25 0.3 0.2 0.25]。图像 1 是“接近”地面实况图像的图像。图像 2 并不“接近”地面实况图像。实际上,我希望 CNN 给我这样的预测,而且我知道模型根本没有信心,我可以把第二个预测扔掉。以自动驾驶汽车为例,图 1 是道路。图 2 是汽车已经在草地上的图像,我还没有训练它在草地上行驶,汽车应该停下来。我知道 CNN 并没有给我好的结果。请评论.thx【参考方案3】:

为了得到类形式的预测输出而不是概率,使用:

model.predict_classes(x_train,batch_size)

【讨论】:

【参考方案4】:

我的理解是,Softmax 表示价值落在 201 个桶中的那个桶的可能性。确定第一个桶你会得到[1,0,0,0,0........]。由于发生的训练/学习/权重调整很少,因此 201 个值都约为 0.00497,总和为 1。 一个像样的description on developers.Google of SoftMax 在这里

输出被指定为“number_outputs”,因此您得到 201 个输出,每个输出都告诉您预测为 THAT 输出的可能性(作为 0 到 1 之间的值)。

【讨论】:

以上是关于Keras softmax 激活,category_crossentropy 损失。但输出不是 0, 1的主要内容,如果未能解决你的问题,请参考以下文章

在 tf.keras 中使用 softmax 作为顺序层和使用 softmax 作为密集层的激活函数有啥区别?

如何在 Keras 模型中使用 TensorFlow 的采样 softmax 损失函数?

如果可以激活多个输出,softmax 层的替换是啥?

如何使用 Keras 创建自定义激活函数?

深度学习Keras框架笔记之激活函数详解

如何在一个 Keras 层中使用不同的激活函数?