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个问题:

  1. 买5斤水果,每斤10元,共需多少元?
  2. 每斤多卖1元,最后需比原来多付多少钱?
  3. 多买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,   x0
对ReLU函数求偏导:
∂ y ∂ x = { 1 ,     x > 0 0 ,     x ≤ 0 \frac{\partial y}{\partial x} = \begin{cases}1,~~~x>0\\0,~~~x≤0\end{cases} xy={1,   x>00,   x0
观察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+ex1
对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) xL=yLxy=yLy2ex=yLy(1y)

用计算图表示为:

在这里插入图片描述

代码如下:

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
posted @ 2020-07-26 16:41  aJream  阅读(107)  评论(0编辑  收藏  举报