• 误差反向传播法(激活函数层的实现)


    激活函数层的实现

    现在,我们将计算图的思路应用到神经网络中。这里,我们把构成神经网络的层实现为一个类。先来实现激活函数的ReLU层和Sigmoid层。

    ReLU层

    激活函数ReLU(Rectified Linear Unit)由下式表示:
    在这里插入图片描述
    可以求出y关于x的导数:
    在这里插入图片描述
    如果正向传播时的输入x大于0,则反向传播会将上游的值原封不动地传给下游。反过来,如果正向传播时的x小于等于0,则反向传播中传给下游的信号将停在此处。用计算图表示:

    在这里插入图片描述
    现在我们来实现ReLU层。在神经网络的层的实现中,一般假定forward()和backward()的参数是NumPy数组。Relu类有实例变量mask。这个变量mask是由True/False构成的NumPy数组,它会把正向传播时的输入x的元素中小于等于0的地方保存为True,其他地方(大于0的元素)保存为False。mask变量保存了由True/False构成的NumPy数组。ReLU层实现如下:

    class Relu:
        def __init__(self):
            self.mask = None
    
        def forward(self, x):
            self.mask = (x <= 0)
            out = x.copy()
            out[self.mask] = 0
            return out
    
        def backward(self, dout):
            dout[self.mask] = 0
            dx = dout
            return dx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ReLU层的作用就像电路中的开关一样。正向传播时,有电流通过的话,就将开关设为 ON;没有电流通过的话,就将开关设为 OFF。反向传播时,开关为ON的话,电流会直接通过;开关为OFF的话,则不会有电流通过。

    Sigmoid

    接下来,我们来实现sigmoid函数。sigmoid函数由下式表示:

    在这里插入图片描述

    用计算图表示如下:
    在这里插入图片描述
    除了“×”和“+”节点外,还出现了新的“exp”和“/”节点。“exp”节点会进行y = exp(x)的计算,“/”节点会进行y=1/x的计算。sigmoid函数的计算由局部计算的传播构成。下面我们就来进行sigmoid函数的计算图的反向传播。作为总结,我们来依次看一下反向传播的流程。

    步骤一:
    “/”节点表示 ,它的导数可以解析性地表示为下式:

    在这里插入图片描述

    反向传播时,会将上游的值乘以−y2(正向传播的输出的平方乘以−1后的值)后,再传给下游。计算图如下所示:
    在这里插入图片描述
    步骤2:
    “+”节点将上游的值原封不动地传给下游。计算图如下所示:
    在这里插入图片描述
    步骤三:
    “exp”节点表示y = exp(x),它的导数由下式表示:
    在这里插入图片描述

    计算图中,上游的值乘以正向传播时的输出(这个例子中是exp(−x))后,再传给下游:
    在这里插入图片描述
    步骤4:
    “×”节点将正向传播时的值翻转后做乘法运算。因此,这里要乘以−1:
    在这里插入图片描述

    上述计算图可以画成集约化的“sigmoid”节点:
    在这里插入图片描述

    简洁版的计算图可以省略反向传播中的计算过程,因此计算效率更高。此外,通过对节点进行集约化,可以不用在意Sigmoid层中琐碎的细节,而只需要专注它的输入和输出,这一点也很重要。结果可以进一步整理如下:
    在这里插入图片描述
    现在,我们用Python实现Sigmoid层:

    class Sigmoid:
        def __init__(self):
            self.out = None
            
        def forward(self, x):
            out = 1 / (1 + np.exp(-x))
            self.out = out
            return out
        
        def backward(self, dout):
            dx = dout * (1.0 - self.out) * self.out
            return dx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这个实现中,正向传播时将输出保存在了实例变量out中。然后,反向传播时,使用该变量out进行计算。

  • 相关阅读:
    最长的顺子
    【后端速成 Vue】初识指令(下)
    arm处理器IO口驱动代码编写与测试(bcm2835)
    asp.net课程设计旅游景点推荐系统网站
    【Linux】工具:gcc/g++ 升级 7.3 版本
    私藏!资深数据专家SQL效率优化技巧
    toPlainString()
    Mac电脑搭建前端项目环境,并适配老项目
    安全学习DAY23_Cookie&Session&Token
    基于ssm的网上药房管理系统的设计与实现(源码+LW+调试)
  • 原文地址:https://blog.csdn.net/weixin_43912621/article/details/127416064