6.4. 活性化関数レイヤの実装

6.4.1. ReLU

\(x>0\)のとき、\(y = x\) なので x>0

\(x \leq 0\)のとき、\(y = 0\)なので x<=0

[1]:
import sys, os
sys.path.append(os.path.abspath(os.path.join('..', 'sample')))
import numpy as np
from common.functions import *
from common.util import im2col, col2im


class Relu:
    def __init__(self):
        """
        順伝播の入力xに対する、0であればTrue、0以外をFalseを保持するマスクを初期化します
        Attributes
        ----------
        mask : numpy.array
            入力xが0以下なのか
        """
        self.mask = None

    def forward(self, x):
        """
        順伝播の計算をします

        Parameters
        ----------
        x : numpy.array
            入力1

        Returns
        -------
        out : numpy.array
            計算結果
        """
        self.mask = (x <= 0)
        out = x.copy()
        out[self.mask] = 0

        return out

    def backward(self, dout):
        """
        逆伝播の計算をします(乗算)

        Parameters
        ----------
        dout : int
            逆伝播で上流から伝わってきた微分

        Returns
        -------
        dx : int
            入力2の微分
        dy : int
            入力1の微分
        """
        dout[self.mask] = 0
        dx = dout

        return dx

True/Falseの値をnumpy.arrayにいれることができる

[2]:
x = np.array([[1.0, -0.5], [-2.0, 3.0]])
print(x)
[[ 1.  -0.5]
 [-2.   3. ]]
[3]:
mask = (x <= 0)
print(mask)
[[False  True]
 [ True False]]

6.4.2. Sigmoidレイヤ

Sigmoid

つまり、Sigmoidレイヤの逆伝搬は\(\frac{\partial L} {\partial y} y^2\exp(-x)\)ですが、これをさらに展開します。

\[\begin{split}\frac{\partial L} {\partial y} y^2\exp(-x) = \frac{\partial L} {\partial y} \frac{1}{(1 + \exp(-x))^2} \exp(-x) \\ = \frac{\partial L} {\partial y} \frac{1}{1 + \exp(-x)} \frac{\exp(-x)}{1 + \exp(-x)} \\ = \frac{\partial L} {\partial y} \frac{1}{1 + \exp(-x)} \frac{\exp(-x) + 1 - 1}{1 + \exp(-x)} \\ = \frac{\partial L} {\partial y} \frac{1}{1 + \exp(-x)} (\frac{\exp(-x) + 1}{1 + \exp(-x)} - \frac{1}{1 + \exp(-x)})\\ = \frac{\partial L} {\partial y} y(1-y)\end{split}\]
[4]:
class Sigmoid:
    def __init__(self):
        """
        順伝播の入力xに対する、0であればTrue、0以外をFalseを保持するマスクを初期化します
        Attributes
        ----------
        mask : numpy.array
            入力xの結果y
        """
        self.out = None

    def forward(self, x):
        """
        順伝搬の計算をします

        Parameters
        ----------
        x : numpy.array
            入力1

        Returns
        -------
        dx : int
            入力2の微分
        """
        out = sigmoid(x)
        self.out = out
        return out

    def backward(self, dout):
        """
        逆伝播の計算をします(乗算)

        Parameters
        ----------
        dout : double
            逆伝播で上流から伝わってきた微分

        Returns
        -------
        dx : int
            入力1の微分
        """
        dx = dout * (1.0 - self.out) * self.out

        return dx