机器学习入门(12)— 激活函数层 ReLU、Sigmoid 层的实现

1. ReLU 函数层

激活函数 ReLURectified Linear Unit)由下式(5.7)表示。
ReLU层
通过式(5.7),可以求出 y 关于 x 的导数,如式(5.8)所示。
激活函数求导
在式(5.8)中,如果正向传播时的输入 x 大于0,则反向传播会将上游的值原封不动地传给下游。反过来,如果正向传播时的 x 小于等于0,则反向传播中传给下游的信号将停在此处。用计算图表示的话,如图5-18 所示。

ReLU 层计算图
在神经网络的层的实现中,一般假定 forward()backward() 的参数是 NumPy 数组。如下代码所示:

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

Relu 类有实例变量 mask 。这个变量 mask 是由 True / False 构成的 NumPy 数组,它会把正向传播时的输入 x 的元素中小于等于 0 的地方保存为 True ,其他地方(大于0 的元素)保存为 False

如下例所示,mask 变量保存了由 True / False 构成的 NumPy 数组。

In [3]: x = np.array( [[1.0, -0.5], [-2.0, 3.0]] )

In [4]: x
Out[4]: 
array([[ 1. , -0.5],
       [-2. ,  3. ]])

In [5]: mask = (x<=0)

In [6]: mask
Out[6]: 
array([[False,  True],
       [ True, False]])

In [7]: 

如图 5-18 所示,如果正向传播时的输入值小于等于 0,则反向传播的值为 0。因此,反向传播中会使用正向传播时保存的 mask ,将从上游传来的 doutmask 中的元素为 True 的地方设为0。

2. Sigmoid 层

sigmoid 函数由式(5.9)表示:
激活函数公式
用计算图表示式(5.9)的话,则如图5-19 所示。
计算图

  • exp 节点会进行 y = exp(x) 的计算;
  • / 节点会进行 y = 1 x y=\frac{1}{x} y=x1 的计算;

反向传播流程:

  1. / 节点表示 y = 1 x y=\frac{1}{x} y=x1,它的导数可以解析性地表示为下式。
    式 5.10
    根据式(5.10),反向传播时,会将上游的值乘以−y2(正向传播的输出的平方乘以−1后的值)后,再传给下游。计算图如下所示。
    步骤1反向图
  2. + 节点将上游的值原封不动地传给下游。计算图如下所示。
    加法反向图
  3. exp 节点表示 y = exp(x) ,它的导数由下式表示。
    指数求导
    计算图中,上游的值乘以正向传播时的输出(这个例子中是 exp(−x))后,再传给下游。
    指数反向图
  4. × 节点将正向传播时的值翻转后做乘法运算。因此,这里要乘以 −1。
    图 5.20
    根据上述内容,图5-20的计算图可以进行 Sigmoid 层的反向传播。从图 5-20 的结果可知,反向传播的输出为 ∂ L ∂ y y 2 e x p ( − x ) \frac{\partial L}{\partial y} y^2exp(-x) yLy2exp(x),这个值会传播给下游的节点。
    这里要注意, 这个值 ∂ L ∂ y y 2 e x p ( − x ) \frac{\partial L}{\partial y} y^2exp(-x) yLy2exp(x) 只根据正向传播时的输入 x 和输出 y 就可以算出来。
    因此,图5-20的计算图可以画成图5-21的集约化的 sigmoid 节点。

简洁版
图5-20 的计算图和简洁版的图5-21 的计算图的计算结果是相同的,但是,简洁版的计算图可以省略反向传播中的计算过程,因此计算效率更高。此外,通过对节点进行集约化,可以不用在意 Sigmoid 层中琐碎的细节,而只需要专注它的输入和输出,这一点也很重要。

另外, ∂ L ∂ y y 2 e x p ( − x ) \frac{\partial L}{\partial y} y^2exp(-x) yLy2exp(x) 可以进一步整理如下。
式 5.12
因此,图5-21 所表示的 Sigmoid 层的反向传播,只根据正向传播的输出就能计算出来。
图 5-22
用代码实现结果如下:

class Sigmoid:
    def __init__(self):
        self.out = None

    def forward(self, x):
        out = sigmoid(x)
        self.out = out
        return out

    def backward(self, dout):
        dx = dout * (1.0 - self.out) * self.out

        return dx

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

参考:《深度学习入门:基于Python的理论与实现》

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值