我正在实施一个卷积神经网络,我似乎无法理解损失函数如何影响实现。
到目前为止,我有基本层,如卷积,池等。我也有密集(完全连接的层,没有隐藏层),没有激活功能,因为我实现了激活功能作为一个单独的层放在后完全连接的层,但也可以放在卷积层之后。在某些实现中我已经看到了。
激活层在前向传播期间简单地计算激活函数(例如sigmoid,relu,softmax等),在向后传播期间,进入的梯度只是乘以输出的导数并传递。
sigmoid激活层的示例:
Forward propagation = 1.0 / (1.0 + exp(-input)
Backward propagation = outputValue * (1 - outputValue) * inputGradient
我认为到目前为止这是正确的。如果我弄错了,请纠正我。
由于我使用均方误差,最后我只计算每个输出和预期输出(outputVector [i] - expectedVector [i])之间的差异,并将其传递给反向传播作为渐变。它首先通过激活层进行修改,并将其传递给完全连接。因此它可以作为普通的神经网络,没有隐藏层,可以直接应用激活函数。
现在我想实现更多的损失函数 - 交叉熵是准确的。我已经查看了一些简单神经网络的代码,没有隐藏层,它们具有直接计算的激活函数,它们将梯度传递为
(outputValue - expectedValue)
在Mean Squared Error中,他们将其作为
传递(outputValue - expectedValue) * derivativeOfActivationFuction(outputValue )
由于我将激活层分开(正如我在其他实现中所见),因此无法通过激活函数的导数来计算从外部传递的内容。我当然可以使用反向操作或将标志传递给最后一个激活层,该激活层表示不应该进行乘法运算。但这似乎并不普遍或正确。
有人能指出我正确的方向吗?将激活功能实现为单独的层是错误的吗?或者只是我缺少的东西,我只需要改变计算传递到最后一层的渐变的方式?
答案 0 :(得分:1)
让我直截了当。您是从头开始编写卷积层和渐变传播?好样的!我赞扬你不必要的挣扎。
据说,渐变实际上只是链规则的长版本。因此,对于你的均值平方误差的例子,我们可以将输出的MSE函数编写为MSE(F(w)),其中F是导致该点的网络,w是你的权重&#39 ; (让我们假设你只有一个让事情变得更容易)。
我们想要的是MSE相对于w的衍生物,所以d / dw(MSE(F(w))。根据链规则,这是MSE'(F(w))* F&#39 ;(w)。对于MSE的定义是((F(w) - y)^ 2)/ 2.这个关于w的导数是(F(w) - y)。所以插入并且你得到你写的:(F(w) - y)* F'(w)。
现在,您想要的是进行交叉熵而不是均方误差。这样做完全没问题,但会采取不同的形式。代替MSE(F(w)),您将拥有CE(F(w)),其中CE =交叉熵。渐变将同样不同,其中它将是CE'(F(w))* F'(w)而不是MSE'(F(w))* F'( W)。 F'(w)是相同的,但现在你有交叉熵乘以它的导数。
因此,无论您的激活功能是什么,您都需要将F'(w)乘以激活函数的导数,以获得完整的渐变。希望能够清除它。我不能在细节方面提供更多帮助,因为我没有看到你的代码,因此不知道你是如何实际实现的。