11-误差反向传播法(二)——层的实现
一、简单层的实现
乘法节点对应的层称作乘法层;加法节点对应的层称为加法层。
层的实现有2个共通的接口(或方法):
farward()
:正向传播backward()
:反向传播
乘法层的实现
例: z = x y z = xy z=xy
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 = self.y * dout
dy = self.x * dout
return dx,dy
3个问题:
- 买5斤水果,每斤10元,共需多少元?
- 每斤多卖1元,最后需比原来多付多少钱?
- 多买1斤,最后需比原来多付多少钱?
这些问题很简单,用计算图表示如下:
买5斤水果,每斤10元,共需50元;
可以看到,每斤水果多卖1元,最后需比原来多付5元;(看蓝色部分)
多买1斤,最后需比原来多付10元钱;(看蓝色部分)
用上面的乘法层来计算:
mul = MulLayer()
sum = mul.forward(10,5) #每斤10元,买5斤
dx, dy = mul.backward(1)
print('总共需要{}元'.format(sum))
print('每斤多卖1元,最后需要多付{}元'.format(dx))
print('多买1斤,最后需要多付{}元'.format(dy))
输出:
总共需要50元
每斤多卖1元,最后需要多付5元
多买1斤,最后需要多付10元
加法层的实现
例: z = x + y z=x+y z=x+y
class AddLayer:
def __init__(self):
pass
def forward(self, x, y):
return x + y
def backward(self,dout):
dx = dout * 1
dy = dout * 1
return dx, dy
二、激活函数层的实现
ReLU层
回顾一下 ReLU 函数:
y
=
{
x
,
x
>
0
0
,
x
≤
0
y=\begin{cases}x,~~~x>0\\0,~~~x≤0\end{cases}
y={x, x>00, x≤0
对ReLU函数求偏导:
∂
y
∂
x
=
{
1
,
x
>
0
0
,
x
≤
0
\frac{\partial y}{\partial x} = \begin{cases}1,~~~x>0\\0,~~~x≤0\end{cases}
∂x∂y={1, x>00, x≤0
观察ReLU函数的偏导数,可知,当正向传播x>0时,则反向传播会将上游的值原封不动地输出到下游;当x≤0时,则反向传给下游的信号将停止传递(即变为0)。
用计算图表示如下:
代码如下:
class Relu:
def __init__(self):
self.mask = None
def forward(self,x):
self.mask = x <= 0 #返回一个 bool型的array
out = x.copy()
out[self.mask] = 0 #把小于等于0的数都换成0
return out
def backward(self, dout):
dout[self.mask] = 0
dx = dout
return dx
sigmoid层
sigmoid函数:
y
=
1
1
+
e
−
x
y = \frac{1}{1+e^{-x}}
y=1+e−x1
对sigmoid函数求导,得:
∂
L
∂
x
=
∂
L
∂
y
∂
y
∂
x
=
∂
L
∂
y
e
−
x
y
2
=
∂
L
∂
y
y
(
1
−
y
)
\frac{\partial L}{\partial x} = \frac{\partial L}{\partial y}\frac{\partial y}{\partial x}=\frac{\partial L}{\partial y}\frac{e^{-x}}{y^2}=\frac{\partial L}{\partial y}y(1-y)
∂x∂L=∂y∂L∂x∂y=∂y∂Ly2e−x=∂y∂Ly(1−y)
用计算图表示为:
代码如下:
class Sigmoid:
def __init__(self):
self.y = None
def forward(self, x):
out = 1/(1+np.exp(-x))
self.y = out
return out
def backward(self,dout):
dx = dout * self.y*(1 - self.y)
return dx
本文来自博客园,作者:aJream,转载请记得标明出处:https://www.cnblogs.com/ajream/p/15383590.html