前言
我们在感知机中采用了梯度下降的方式实现了参数的优化(手动实现感知机),但是感知机对于较为复杂的问题就显得力不从心了,所以我们需要用到多层感知机,即神经网络。此时的梯度下降就需要通过反向传递来实现了
最简单的反向传递
我们在感知机中进行的最简单的操作就是加法和乘法,这里我们先以乘法和除法为例实现最简单的反向传递
乘法层
公式
我们假设x*y=z
, 损失函数为L
,那么我们分别对z求关于x和y的偏导得
∂ z ∂ x = y \frac{ \partial z}{\partial x}=y ∂x∂z=y
∂ z ∂ y = x \frac{\partial z}{\partial y}=x ∂y∂z=x
得到结论乘法层的偏导为两个乘数互换位置
则
∂ L ∂ z ∂ z ∂ x = ∂ L ∂ z ⋅ y \frac{ \partial L}{\partial z}\frac{ \partial z}{\partial x}=\frac{ \partial L}{\partial z} \cdot y ∂z∂L∂x∂z=∂z∂L⋅y
∂ L ∂ z ∂ z ∂ y = ∂ L ∂ z ⋅ x \frac{ \partial L}{\partial z}\frac{\partial z}{\partial y}=\frac{ \partial L}{\partial z} \cdot x ∂z∂L∂y∂z=∂z∂L⋅x
代码实现
在反向传递时要遵循链式法则,所以在这里我们每个偏导都要乘以后面一层反向传递来的偏导数dout才是应该传递给上一层的偏导数,下同。
class MulLayer:
def __init__(self):
self.x = None
self.y = None
def forward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backward(self, dout):
dx = dout * self.y
dy = dout * self.x
return dx, dy
加法层
公式
我们假设x+y=z
, 损失函数为L
那么我们分别对z求关于x和y的偏导得
∂ z ∂ x = 1 \frac{ \partial z}{\partial x}=1 ∂x