Python&機械学習 勉強メモ④:バックプロパゲーションによる機械学習


はじめに

https://qiita.com/yohiro/items/04984927d0b455700cd1
https://qiita.com/yohiro/items/5aab5d28aef57ccbb19c
https://qiita.com/yohiro/items/cc9bc2631c0306f813b5
の続き

バックプロパゲーションによる機械学習

出力層のニューロンの重みは、出力と正解の誤差を元に調整する。
また、出力層のニューロンの重みを元に、中間層のニューロンの重みを調整する。

中間層-出力層の重みの調整

中間層-出力層の重みの調整は以下の式で得られる

\delta_{mo} = (出力値 - 正解値) \times 出力の微分 \\
修正量 = \delta_{mo} \times 中間層の値 \times 学習係数

シグモイド関数の微分

上記式の「出力の微分」について、今回のニューラルネットワークの活性化関数に用いているシグモイド関数$f(x) = \frac{1}{1+e^x}$の微分は以下の式で得られる。

f(x)' = f(x)\cdot(1-f(x))

参考:https://qiita.com/yosshi4486/items/d111272edeba0984cef2

ソースコード

class NeuralNetwork:
    # 入力の重み
    w_im = [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]  # [[i1-m1, i1-m2], [i2-m1, i2-m2], [bias1-m1, bias1-m2]]
    w_mo = [1.0, 1.0, 1.0]  # [m1-o, m2-o, bias2-0]
    # 各層の宣言
    input_layer = [0.0, 0.0, 1.0] # i1, i2, bias1
    middle_layer = [Neuron(), Neuron(), 1.0] # m1, m2, bias2
    ouput_layer = Neuron() # o

    def learn(self, input_data):

        # 出力値
        output_data = self.commit([input_data[0], input_data[1]])
        # 正解値
        correct_value = input_data[2]
        # 学習係数
        k = 0.3

        # 出力層 → 中間層
        delta_w_mo = (correct_value - output_data) * output_data * (1.0 - output_data)
        old_w_mo = list(self.w_mo)
        self.w_mo[0] += self.middle_layer[0].output * delta_w_mo * k
        self.w_mo[1] += self.middle_layer[1].output * delta_w_mo * k
        self.w_mo[2] += self.middle_layer[2] * delta_w_mo * k

入力層-中間層の重みの調整

入力層-中間層の重みの調整は以下の式で得られる。
後段ニューロンの調整結果をもとに前段ニューロンの重みを調整する方式にすることで、層がいくつであっても調整が可能。

\delta_{im} = \delta_{mo} \times 中間出力の重み \times 中間層出力の微分 \\
修正量 = \delta_{im} \times 入力層の値 \times 学習係数

ソースコード

class NeuralNetwork:
        ...
        # 中間層 → 入力層
        delta_w_im = [
            delta_w_mo * old_w_mo[0] * self.middle_layer[0].output * (1.0 - self.middle_layer[0].output),
            delta_w_mo * old_w_mo[1] * self.middle_layer[1].output * (1.0 - self.middle_layer[1].output)
        ]
        self.w_im[0][0] += self.input_layer[0] * delta_w_im[0] * k
        self.w_im[0][1] += self.input_layer[0] * delta_w_im[1] * k
        self.w_im[1][0] += self.input_layer[1] * delta_w_im[0] * k
        self.w_im[1][1] += self.input_layer[1] * delta_w_im[1] * k
        self.w_im[2][0] += self.input_layer[2] * delta_w_im[0] * k
        self.w_im[2][1] += self.input_layer[2] * delta_w_im[1] * k

学習結果

学習データとして以下を用意する

上記で学習させたニューラルネットワークに以下のデータを放り込むと・・・

data_to_commit = [[34.6, 138.0], [34.6, 138.18], [35.4, 138.0], [34.98, 138.1], [35.0, 138.25], [35.4, 137.6], [34.98, 137.52], [34.5, 138.5], [35.4, 138.1]]

東京・神奈川どちらに分類されるかを判定できていることがわかる