#はじめに
① https://qiita.com/yohiro/items/04984927d0b455700cd1
② https://qiita.com/yohiro/items/5aab5d28aef57ccbb19c
③ https://qiita.com/yohiro/items/cc9bc2631c0306f813b5
の続き
- 参考教材:Udemy みんなのAI講座 ゼロからPythonで学ぶ人工知能と機械学習
- 課題設定:緯度・経度を与えると、東京・神奈川のどちらに属するかを判定するプログラムを作成する.
- 判定方法:入力層2つ・中間層2つ・出力層1つのニューラルネットワークで判定する。
#バックプロパゲーションによる機械学習
出力層のニューロンの重みは、出力と正解の誤差を元に調整する。
また、出力層のニューロンの重みを元に、中間層のニューロンの重みを調整する。
#中間層-出力層の重みの調整
中間層-出力層の重みの調整は以下の式で得られる
\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]]
東京・神奈川どちらに分類されるかを判定できていることがわかる