二进制交叉熵损失在自动编码器上如何工作?

Who*_*ami 10 machine-learning neural-network autoencoder keras cross-entropy

我只使用Dense图层编写了香草自动编码器。下面是我的代码:

iLayer = Input ((784,))
layer1 = Dense(128, activation='relu' ) (iLayer)
layer2 = Dense(64, activation='relu') (layer1)
layer3 = Dense(28, activation ='relu') (layer2)
layer4 = Dense(64, activation='relu') (layer3)
layer5 = Dense(128, activation='relu' ) (layer4)
layer6 = Dense(784, activation='softmax' ) (layer5)
model = Model (iLayer, layer6)
model.compile(loss='binary_crossentropy', optimizer='adam')

(trainX, trainY), (testX, testY) =  mnist.load_data()
print ("shape of the trainX", trainX.shape)
trainX = trainX.reshape(trainX.shape[0], trainX.shape[1]* trainX.shape[2])
print ("shape of the trainX", trainX.shape)
model.fit (trainX, trainX, epochs=5, batch_size=100)
Run Code Online (Sandbox Code Playgroud)

问题:

1)softmax提供概率分布。明白了 这意味着,我将拥有784个值的向量,概率在0到1之间。例如,[0.02,0.03 .....最多784个项目],将所有784个元素相加得出1。

2)我不明白二进制交叉熵如何与这些值一起工作。二进制交叉熵是针对两个输出值的,对吗?

tod*_*day 15

在自动编码器的上下文中,模型的输入和输出是相同的。因此,如果输入值在[0,1]范围内,则可以sigmoid用作最后一层的激活函数。否则,您需要为最后一层使用适当的激活功能(例如linear,默认激活功能)。

至于损失函数,它又回到输入数据的值。如果输入数据在零和一之间(而不是在它们之间的值之间),则binary_crossentropy可以作为损失函数。否则,您需要使用其他损失函数,例如'mse'(即均方误差)或'mae'(即均值绝对误差)。请注意,在输入值处于范围内的情况下,[0,1]可以使用binary_crossentropy,因为它通常被使用(例如Keras自动编码器教程本文)。但是,不要期望损失值变为零,因为binary_crossentropy当预测和标签都不为零或一(无论它们是否相等)时,它不会返回零。这里Hugo Larochelle的视频,他解释了自动编码器中使用的损失函数(有关使用binary_crossentropy[0,1]范围内的输入的部分始于5:30

具体而言,在您的示例中,您正在使用MNIST数据集。因此,默认情况下,MNIST的值是[0,255]范围内的整数。通常,您需要先对其进行规范化:

trainX = trainX.astype('float32')
trainX /= 255.
Run Code Online (Sandbox Code Playgroud)

现在,这些值将在[0,1]范围内。所以sigmoid可作为激活函数和任一binary_crossentropymse作为损失函数。


为什么binary_crossentropy即使真实标签值(即地面真相)在[0,1]范围内也可以使用?

请注意,我们正在尝试最小化训练中的损失函数。因此,如果在预测等于真标签时我们使用的损失函数达到了最小值(不一定等于零),那么这是一个可以接受的选择。让我们验证一下binray交叉熵的情况,其定义如下:

bce_loss = -y*log(p) - (1-y)*log(1-p)
Run Code Online (Sandbox Code Playgroud)

其中y,真正的标签p是预测值。让我们将其视为y固定值,看看p最小化此函数的值是什么:我们需要相对于导数(为了简化计算,p我假设the log是自然对数函数):

bce_loss_derivative = -y*(1/p) - (1-y)*(-1/(1-p)) = 0 =>
                      -y/p + (1-y)/(1-p) = 0 =>
                      -y*(1-p) + (1-y)*p = 0 =>
                      -y + y*p + p - y*p = 0 =>
                       p - y = 0 => y = p
Run Code Online (Sandbox Code Playgroud)

如您所见,当时y=p,即当真实标签等于预测标签时,二进制交叉熵具有最小值,这正是我们要寻找的。

  • 不完全准确;请查看 [Keras 自动编码器教程](https://blog.keras.io/building-autoencoders-in-keras.html),其中二进制交叉熵 + sigmoid 用于 MNIST 数据(像素值),这肯定是*不是*二进制... (2认同)
  • @desertnaut 我想这有点不对。因为,当预测和标签相同并且它们既不是零也不是一时,二元交叉熵不会返回零。换句话说,您预测正确,但损失不为零!在交叉验证中查看此 [answer](https://stats.stackexchange.com/a/296277/114422) 以获取更多信息。 (2认同)
  • @desertnaut非常感谢您的触发。因此,我学到了一些新东西。 (2认同)