[ゼロから作るDeep Learning]sigmoidレイヤ・Reluレイヤの実装をしてみた


はじめに

この記事はゼロから作るディープラーニング 6章誤差逆伝播法を自分なりに理解して分かりやすくアウトプットしたものです。
文系の自分でも理解することが出来たので、気持ちを楽にして読んでいただけたら幸いです。
また、本書を学習する際に参考にしていただけたらもっと嬉しいです。

sigmoidレイヤの実装

class Sigmoid: # シグモイド関数のレイヤ実装
    def __init__(self):
        self.out = None # シグモイド関数の逆伝播処理では順伝播処理の出力信号が必要になる

    def forward(self, x):
        out = 1 / (1 + np.log(-x))
        self.out = out # 順伝播の出力保存

        return out

    def backward(self, dout):
        dx = dout * self.out * (1 - self.out) # シグモイド関数の逆伝播を求める処理

        return dx

順伝播処理は、sigmoid関数の公式通りに処理を行い、それをreturnで返す。
しかし、逆伝播処理で順伝播処理の結果を使用するので、インスタンス変数に保存しておく。

逆伝播処理では、普通にすると相当複雑になってしまうため、ここでは簡略式を使って微分を求める。
前の微分とインスタンス変数に保存した順伝播処理の結果を使ってsigmoidレイヤの入力値の微分を求める。

Reluレイヤの実装

class Relu: # Relu関数のレイヤ実装
    def __init__(self):
        self.mask = None # 入力信号の0以下がTrueで0より大きいものがFalseの配列が入る

    def forward(self, x):
        self.mask = (x <= 0)
        out = x.copy()
        out[self.mask] = 0 # 入力信号で0以下のものを0にする

        return out

    def backward(self, dout):
        dout[self.mask] = 0 # 順伝播が0の場合は逆伝播も0なのでここで0にする
        dx = dout # 他は前の微分を引き継ぐ

        return dx

順伝播処理は、ifを使わずに実装を行うためにまず、入力値で0を超えないものを全てTrueに0を超えるものをFalseにして、それをインスタンス変数に保存する。これはあとで使用する。

次に入力値の入った配列をコピーして、それにさっき保存したTrue,Falseの配列を使いTrueのものを全て0に変換する。そしてそれをreturnで返す。

逆伝播処理では、順伝播処理で保存したTrue,Falseの配列を使ってTrueを全て0に変換する。順伝播が0のものは逆伝播でも0のため。

そしてあとは前の微分を継承してreturnで返す。