令y = Relu(Wx)其中W是表示x,矢量的线性变换的2d矩阵。同样,令m = Zy,其中Z是表示y上的线性变换的2d矩阵。如何以编程方式计算相对于W的Loss = sum(m ^ 2)的梯度,其中幂表示得到的向量的元素幂,sum表示将所有元素加在一起?
我可以通过假设,将它全部乘以,然后逐个元素取导数来构造梯度,从数学上缓慢地解决这个问题,但我无法找出编写程序的有效方法一旦神经网络层变为> 1。
说,对于一个图层(m = Zy,采用渐变wrt Z)我可以说
Loss = sum(m^2)
dLoss/dZ = 2m * y
其中*是向量的外积,我猜这有点像普通的微积分,它有效。现在为2层+激活(渐变wrt W),如果我尝试这样做"正常"微积分并应用我得到的链规则:
dLoss/dW = 2m * Z * dRelu * x
其中dRelu是Relu(Wx)的衍生物,除了在这里我不知道在这种情况下*意味着什么才能使它工作。
有没有一种简单的方法可以数学方式计算这个梯度,而基本上不需要将它全部乘以并导出渐变中的每个单独元素?我真的不熟悉矩阵演算,所以如果有人也可以给出一些数学直觉,如果我的尝试完全错误,那将是值得赞赏的。
答案 0 :(得分:1)
为了方便起见,我们暂时忽略ReLU。你有一个输入空间X(某个大小[dimX])映射到一个中间空间Y(某种大小[dimY])映射到输出空间m(某种大小[dimM])你有,然后,W:X →Y形状矩阵[dimY,dimX]和Z:Y→形状矩阵[dimM,dimY]。最后,您的损失只是将M空间映射到标量值的函数。
让我们向后走。正如你所说的那样,你想要计算w.r.t W损失的导数,为此你需要一直应用链规则。然后你有:
dL / dW = dL / dm * dm / dY * dY / dW
修改:
然后得到的张量收缩是形状[dimY,dimX]的矩阵,可用于更新W权重。我们之前忽略的ReLU很容易被抛入混合中,因为ReLU:1→1是在Y上逐个元素应用的标量函数。
总结一下,您的代码将是:
W_gradient = 2m * np.dot(Z, x) * np.e**x/(1+np.e**x))
答案 1 :(得分:0)
我刚从C ++开始实现了几个乘法神经网络(MLP)[1],我想我知道你的痛苦是什么。相信我,你甚至不需要任何第三方矩阵/张量/自动微分(AD)库来进行矩阵乘法或梯度计算。你应该注意三件事:
*
,则会陷入困境。 dimension compatibility
,不要忘记检查尺寸。假设您想进行二元分类,神经网络为input -> h1 -> sigmoid -> h2 -> sigmoid -> loss
,其中输入层有1个样本,每个样本有2个特征,h1有7个神经元,h2有2个神经元。然后:
前进:
Z1(1, 7) = X(1, 2) * W1(2, 7)
A1(1, 7) = sigmoid(Z1(1, 7))
Z2(1, 2) = A1(1, 7) * W2(7, 2)
A2(1, 2) = sigmoid(Z2(1, 2))
Loss = 1/2(A2 - label)^2
向后传递:
dA2(1, 2) = dL/dA2 = A2 - label
dZ2(1, 2) = dL/dZ2 = dA2 * dsigmoid(A2_i) -- element wise
dW2(7, 2) = A1(1, 7).T * dZ2(1, 2) -- matrix multiplication
注意最后一个等式,W2
的渐变尺寸应与W2
匹配,即(7, 2)
。获得(7, 2)
矩阵的唯一方法是转置输入A1
并将A1
与dZ2
相乘,即维度兼容性[2]。
向后传球继续:
dA1(1, 7) = dZ2(1, 2) * A1(2, 7) -- matrix multiplication
dZ1(1, 7) = dA1(1, 7) * dsigmoid(A1_i) -- element wise
dW1(2, 7) = X.T(2, 1) * dZ1(1, 7) -- matrix multiplication
[1]代码为here,你可以看到隐藏的层实现,朴素矩阵实现和那里列出的引用。
[2]我省略了矩阵推导部分,实际上很简单但很难输出方程式。我强烈建议你阅读this paper,本文列出了你应该知道的关于DL中矩阵推导应该知道的每一个细节。
[3]在上面的例子中使用了一个作为输入的样本(作为向量),你可以用任何批号替换1(变成矩阵),并且方程仍然成立。