読者です 読者をやめる 読者になる 読者になる

Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

Python DeepLearningに再挑戦 13 誤差逆伝播法 実装

概要

Python DeepLearningに再挑戦 13 誤差逆伝播法 実装

参考書籍

乗算レイヤの実装

forward() = 順伝播 backward() = 逆伝播

として定義していく。

class MulLayer:#乗算レイヤー のクラス
    def __init__(self):#初期化、順伝播時の入力値を保持するために利用する。
        self.x = None
        self.y = None
    
    def forward(self, x, y):
        self.x = x #引数xをそのまま代入
        self.y = y #引数yをそのまま代入
        out = x * y # x * y をoutとして定義する。
        
        return out
    
    def backward(self, dout):#dout は、上流から伝わって来た微分
        dx = dout * self.y # xとyをひっくり返す。
        dy = dout * self.x # xとyをひっくり返す
        
        return dx, dy

実際に順伝播で使う時は以下のような感じ。

apple = 100
apple_num = 2
tax = 1.1

# ここで、レイヤーごとにインスタンスを分けるのがポイント
mul_apple_layer = MulLayer()
mul_tax_layer = MulLayer()

# forward
apple_price = mul_apple_layer.forward(apple,apple_num) # 200
price = mul_tax_layer.forward(apple_price, tax) # 220

各変数に関する微分は、backward()で求められる。

dprice = 1 # 合計部分の微分
dapple_price, dtax = mul_tax_layer.backward(dprice) # 上流から流れてくる、dpriceを引数にして、apple_price, dtax部分の微分を求める

dapple, dapple_num = mul_apple_layer.backward(dapple_price) # dapple_priceを上流の微分の引数として、代入する。

print(dapple, dapple_num, dtax) # 2.2 110 200

うーん、わかってるつもりだけど、ちょっとわかってない部分もある気がする。。 加算レイヤは以下の通り。

# 加算レイヤ
class AddLayer:
    def __init__(self):#加算では特に初期化は必要ない self.x, self.y というインスタンス変数自体出てこないから。
        pass
    
    def forward(self,x,y):
        out = x + y
        return out
    
    def backward(self, dout):
        dx = dout * 1 # 上流の微分をそのまま流す
        dy = dout * 1# 上流の微分をそのまま流す
        return dx, dy

以下は、加算レイヤと、乗算レイヤを組み合わせてみた場合。

apple = 100
apple_num = 2
orange = 150
orange_num = 3
tax = 1.1

# layer
mul_apple_layer = MulLayer() #リンゴの価格x個数
mul_orange_layer = MulLayer() # オレンジの価格x個数
add_apple_orange_layer = AddLayer() # リンゴとオレンジの合計
mul_tax_layer = MulLayer() # 合計x消費税

# forward
apple_price = mul_apple_layer.forward(apple, apple_num)
orange_price = mul_orange_layer.forward(orange, orange_num)
all_price = add_apple_orange_layer.forward(apple_price, orange_price)
price = mul_tax_layer.forward(all_price, tax)

# backward
dprice = 1 #出力の微分
dall_price, dtax = mul_tax_layer.backward(dprice)
dapple_price, dorange_price = add_apple_orange_layer.backward(dall_price)
dorange, dorange_num = mul_orange_layer.backward(dorange_price)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)

print(price)
print(dapple_num, dapple, dorange, dorange_num, dtax)

次は、活性化関数レイヤの実装か〜(^ ^)