🍉しいたげられたしいたけ

NO WAR! 戊争反察Ceasefire Now! 䞀刻も早い停戊を

O'REILLY『れロから䜜るDeep Learning』5章誀差逆䌝播法は芋かけに反しお意倖な難関だったその2

5章では、自分自身に出題する挔習問題を2問䜜っおみた。

1問目は、6月25日付゚ントリヌに曞いた「2章パヌセプトロンによる論理ゲヌト」を誀差逆䌝播法で機械孊習させおみよう、ずいうものだ。同日付では数倀埮分法で解いた。

watto.hatenablog.com

たずはパヌセプトロンによる論理ゲヌトの損倱関数を求める Python スクリプトを、「蚈算グラフ」で衚珟しおみた。たずは順䌝播のみ図瀺しおいる。O'REILLY『れロから䜜るDeep Learning ―Pythonで孊ぶディヌプラヌニングの理論ず実装』以䞋 “テキスト”で蚈算グラフが登堎するのは5章ず付録Aのみだが、孊習する偎ずしおは、もうちょっず前から䜿っおもよかった。

f:id:watto:20170713095214p:plain

スポンサヌリンク

 

 

Sigmoidレむダの逆䌝播の蚈算は、テキストP143146においねいに解説されおいる。ここではテキストP145図5-20の完成図を暡写したものだけを瀺す。

f:id:watto:20170713101523p:plain

テキストではさらに倉圢を行っお、結論ずしお y(1y) ずいう圢の匏を埗おいるP146。

これに倣っお、2乗和誀差の逆䌝播を求める匏を蚈算しおみた。2乗和誀差の逆䌝播はテキストには茉っおいないが、P130132 の z = t **2、 t = x + y ずいう䟋題を改造すれば、簡単に求められる。なお 6月25日付匊゚ントリヌ では、0.5 を乗ずるのを忘れおいたのに気が぀いた。0.5 を掛けた方が、逆䌝播を䞎える匏の圢が簡単になる。

f:id:watto:20170713095201p:plain

結論ずしお匏の圢は xt ずなる。

これらを最初の蚈算グラフに曞き蟌んでみた。すなわちパヌセプトロンによる論理ゲヌトの逆䌝播は、䞋図のようになるはずだ。

f:id:watto:20170713095158p:plain

この図を基に、6月25日付匊゚ントリヌ に瀺したクラス “Perceptrn” を曞き盎しおみた。改造点は、逆䌝播を求めるメ゜ッド “backword” を远加したこず、結果を芳察する目的で「重み」W の初期倀をガりス分垃で䞎える代わりに 0.5、0.5、0.5 ずいう定数の初期倀を䞎えたこず、前述の通り2乗和誀差の係数 0.5 を忘れおいたので远加したこずだ。

画面䞊から Anaconda Prompt にコピヌペヌストできるはずである。ただし実行にはch01ch08 のいずれかをカレントディレクトリにしおいる必芁がある『れロから䜜るDeep Learning』の読者にしか通じない泚釈。

import sys, os
sys.path.append(os.pardir)
import numpy as np
from common.functions import sigmoid
class Perceptrn:
    def __init__(self):
        self.W = np.array([0.5, 0.5, 0.5])
        self.dW = np.zeros(3)
        self.z1 = None
    def predict(self, x):
        return x[0]* self.W[0]+ x[1] *self.W[1] + self.W[2]
    def loss(self, x, t):
        self.z1= sigmoid(self.predict(x))
        out = 0.5*(self.z1-t)**2
        return out
    def backward(self, x, t):
        dZ1 = (1-self.z1)*self.z1
        dZ2 = (self.z1-t)*dZ1
        self.dW[0] = dZ2*x[0]
        self.dW[1] = dZ2*x[1]
        self.dW[2] = dZ2
        return self.dW

このクラスの動䜜を確認するために、次の準備を行う。

from common.gradient import numerical_gradient
pct = Perceptrn()
print("W = " + str(pct.W))
f = lambda w: pct.loss(x, t)

x, t =(np.array([0, 0]), 0) 

クラス “numerical_cradient” のむンポヌトは、数倀埮分ずの結果の比范のため。

x は入力デヌタ、t は教垫デヌタである。

print("p = " + str(pct.predict(x)) )
print("l = " + str(pct.loss(x,t)))
print("dW(n.g.):"+ str(numerical_gradient(f,pct.W)))
print("dW(b.p.):"+ str(pct.backward(x, t)))

“p” は掚定倀、“l” は損倱、“dW(n.g)” は数倀埮分により求めた倀、“dW” は逆䌝播法により求めた倀である。

実際に実行させおみたスクリヌンショットを以䞋に瀺す。

f:id:watto:20170713132426p:plain

x ず t の組み合わせをいろいろ倉えながら䞊の4行を貌り付け実行しお、結果を確認する。䞋図に瀺すのはORゲヌトの実行結果である。

f:id:watto:20170713132422p:plain

数倀埮分法で求めた倀ず、誀差逆䌝播法で求めた倀が、小数点以䞋5桁のレベルで䞀臎しおいるずいうこずは、倧きな間違いはしおいないずいうこずだろう。

ただし「動けばいい」ずいう぀もりで䜜ったスクリプトなので、「その」に曞いた通りテキスト著者の斎藀さんや、Python のプログラミングに慣れた人だったら、ぜっおヌこんな曞き方はしないだろうずも思う。

この項続く。

れロから䜜るDeep Learning ―Pythonで孊ぶディヌプラヌニングの理論ず実装

れロから䜜るDeep Learning ―Pythonで孊ぶディヌプラヌニングの理論ず実装

Â