所以我知道反向传播使用梯度并将其传递回神经网络以更新权重。但是中间层的权重是如何精确更新的。非输出层是否使用与输出层相同的梯度,或者它们具有不同的梯度来更新权重?
答案 0 :(得分:1)
在每一层中,您的神经网络都会反复生成以下中间计算:
z[l] = a[l] * w[l] + b[l]
a[l+1] = f[l](z[l])
其中a [0]是您对神经网络的原始输入。 z [l]是先前激活a [l]的加权和(记住a [0]是输入),然后第l层w [l]的权重将b [l]加为偏差向量。然后通过在先前计算的z上应用激活函数(f [l](x)-记住您可以为每个层使用不同的激活函数)来计算当前层的激活。 这是您的前传。您可以一遍又一遍地重复上述步骤,并覆盖尽可能多的图层。
要向后传播错误,您必须针对从最后到第一个的权重矩阵区分成本函数:
dw [l],dw [l-1],...,dw [1],dw [0]
让我们以一个玩具为例。您有一个具有单个隐藏层和一个输出层的神经网络,因此您的输入有a [0],z [0]作为隐藏层的权重,a [1]作为激活在隐藏层,z [1]作为输出层的加权部分,a [2]作为网络对输入的猜测。在隐藏层上的权重也有w [0],在输出层上的权重也有w [1]。最后,当然有b [0]表示隐藏,b [1]表示输出偏置。
现在,要更新体重,您必须找到:
dE / dw [1]
dE / dw [0]
第一个是输出层上的权重,第二个是隐藏层上的权重。
dE/dw[0] := dE/da[2] * da[2]/dz[1] * dz[1]/dw[1]
If, E := np.mean(np.sum(.5 * (a[2] - Y)**2, axis=1), axis=0)
then:
dE/da[2] = (a[2] - Y)
For da[2]/dz[1], remember that a[l+1] = f[l](z[1]):
da[2]/dz[1] = df[l](z[1])
Finally:
dz[1]/dw[1] = a[1]
dE/dw[0] = (a[2] - Y) * df[l](z[1]) @ a[1]
其中,*是按元素的乘法,@是标准的众所周知的矩阵乘法。现在,有不同的方法可以初始化权重矩阵并组织输入矩阵以进行小批量梯度下降,因此上述工作仍需要一些工作。通常,您必须转置a [1]和/或将a [1] .T与其余部分相乘。但是计算是这样的。 现在,对于隐藏层,事情就继续进行:
dE/dw[0] := dE/da[2] * da[2]/dz[1] * dz[1]/da[1] * da[1]/dz[0] * dz[0]/dw[0]
Where dE/da[2] * da[2]/dz[1] is common and is called d[1] a.k.a the delta for the output layer.
dz[1]/da[1] = w[1]
da[1]/dz[0] = df[0](z[0])
dz[0]/dw[0] = a[0]
dE/dw[0] = d[1] @ w[1] * df[0](z[0]) * a[0]
再一次可能需要转置w [1]和a [0],这取决于您如何设计网络,但是计算就在那里。
长话短说,这只是一遍又一遍地应用连锁规则。给定一个层[i],您将从下一层得到d [i + 1],那么您需要为当前层计算dw [i],为上一个[i-1]计算d [i] -th层:
d[i] = d[i+1] @ w[i+1] * df[i](z[i])
dw[i] = d[i] @ a[i]
并从最后到第一遍网络中的所有层重复此操作。我希望可以清除它。