コードで確認するニューラルネットワーク・アルゴリズム
17316 ワード
はじめに
本記事は、下記コース受講の一環として、(併せて提供される「超AI入門講座」に含まれる動画および資料を)学習した内容について、理解を深めるため、かつ備忘として整理したものです。
コード自体は本記事単体のみにて完結したものとなるよう整理してありますが(ただし入力データは構造のみを記述)、事前の知見のない方へ向けての解説・説明とはなっていません。知識確認の参考としていただくか、必要に応じ上記コース等ほかの情報と併せてご活用ください。
前提
学習するデータとネットワークとの関係
- 1レイヤー2次元配列(白黒画像)
- 縦横28(px)のデータを、
784
個の入力値として扱う - 誤差の算出には二乗誤差を用いる
- 学習係数 $\eta$ は用いない
利用ライブラリ
import numpy as np
ネットワーク定義
シグモイド関数
def sigmoid(a):
return 1 / (1 + np.exp(-a))
重みWの定義
w1 = np.random.normal(0.0, 1.0, (10, 784))
w2 = np.random.normal(0.0, 1.0, (2, 10))
W = [w1, w2]
バイアスBの定義
b1 = np.ones((10, 1))
b2 = np.ones((2, 1))
B = [b1, b2]
ネットワーク更新のための関数定義
パラメータ更新式公式
wの更新式
w = w - \frac{\partial E}{\partial w} = w - \frac{\partial E}{\partial y} \frac{\partial y}{\partial a} \frac{\partial a}{\partial w}
誤差関数Eのbによる偏微分の公式
\frac{\partial E}{\partial b_j^l} = g_j^l
誤差関数Eのwによる偏微分の公式
\frac{\partial E}{\partial w_{kj}^l} = g_i^{l} x_k^{l}
更新式の公式g
最終レイヤー
g_j^l = (y_j - t_j)f'(a_j^l)
最終レイヤー以外
g_j^l = \sum_{i=1}^{m} (g_i^{l+1} w_ji^{l+1})f'(a_j^l)
活性化関数fの微分
def f(a):
return (1 - sigmoid(a)) * sigmoid(a)
更新式の公式gの実装
def g(l, j):
if max_layer == l:
return (y[j] - t[j]) * f(A[l - 1][j])
else:
output = 0
m = A[l].shape[0]
for i in range(m):
output += g(l + 1, i) * W[l][i, j] * f(A[l - 1][j])
return output
誤差関数の微分
パラメーターwによる微分
def diff_w(j, k, l):
return g(l, j) * X[l - 1][k]
パラメーターbによる微分
def diff_b(j, l):
return g(l, j)
データ
入力
import numpy as np
シグモイド関数
def sigmoid(a):
return 1 / (1 + np.exp(-a))
重みWの定義
w1 = np.random.normal(0.0, 1.0, (10, 784))
w2 = np.random.normal(0.0, 1.0, (2, 10))
W = [w1, w2]
バイアスBの定義
b1 = np.ones((10, 1))
b2 = np.ones((2, 1))
B = [b1, b2]
ネットワーク更新のための関数定義
パラメータ更新式公式
wの更新式
w = w - \frac{\partial E}{\partial w} = w - \frac{\partial E}{\partial y} \frac{\partial y}{\partial a} \frac{\partial a}{\partial w}
誤差関数Eのbによる偏微分の公式
\frac{\partial E}{\partial b_j^l} = g_j^l
誤差関数Eのwによる偏微分の公式
\frac{\partial E}{\partial w_{kj}^l} = g_i^{l} x_k^{l}
更新式の公式g
最終レイヤー
g_j^l = (y_j - t_j)f'(a_j^l)
最終レイヤー以外
g_j^l = \sum_{i=1}^{m} (g_i^{l+1} w_ji^{l+1})f'(a_j^l)
活性化関数fの微分
def f(a):
return (1 - sigmoid(a)) * sigmoid(a)
更新式の公式gの実装
def g(l, j):
if max_layer == l:
return (y[j] - t[j]) * f(A[l - 1][j])
else:
output = 0
m = A[l].shape[0]
for i in range(m):
output += g(l + 1, i) * W[l][i, j] * f(A[l - 1][j])
return output
誤差関数の微分
パラメーターwによる微分
def diff_w(j, k, l):
return g(l, j) * X[l - 1][k]
パラメーターbによる微分
def diff_b(j, l):
return g(l, j)
データ
入力
w1 = np.random.normal(0.0, 1.0, (10, 784))
w2 = np.random.normal(0.0, 1.0, (2, 10))
W = [w1, w2]
b1 = np.ones((10, 1))
b2 = np.ones((2, 1))
B = [b1, b2]
ネットワーク更新のための関数定義
パラメータ更新式公式
wの更新式
w = w - \frac{\partial E}{\partial w} = w - \frac{\partial E}{\partial y} \frac{\partial y}{\partial a} \frac{\partial a}{\partial w}
誤差関数Eのbによる偏微分の公式
\frac{\partial E}{\partial b_j^l} = g_j^l
誤差関数Eのwによる偏微分の公式
\frac{\partial E}{\partial w_{kj}^l} = g_i^{l} x_k^{l}
更新式の公式g
最終レイヤー
g_j^l = (y_j - t_j)f'(a_j^l)
最終レイヤー以外
g_j^l = \sum_{i=1}^{m} (g_i^{l+1} w_ji^{l+1})f'(a_j^l)
活性化関数fの微分
def f(a):
return (1 - sigmoid(a)) * sigmoid(a)
更新式の公式gの実装
def g(l, j):
if max_layer == l:
return (y[j] - t[j]) * f(A[l - 1][j])
else:
output = 0
m = A[l].shape[0]
for i in range(m):
output += g(l + 1, i) * W[l][i, j] * f(A[l - 1][j])
return output
誤差関数の微分
パラメーターwによる微分
def diff_w(j, k, l):
return g(l, j) * X[l - 1][k]
パラメーターbによる微分
def diff_b(j, l):
return g(l, j)
データ
入力
w = w - \frac{\partial E}{\partial w} = w - \frac{\partial E}{\partial y} \frac{\partial y}{\partial a} \frac{\partial a}{\partial w}
\frac{\partial E}{\partial b_j^l} = g_j^l
\frac{\partial E}{\partial w_{kj}^l} = g_i^{l} x_k^{l}
g_j^l = (y_j - t_j)f'(a_j^l)
g_j^l = \sum_{i=1}^{m} (g_i^{l+1} w_ji^{l+1})f'(a_j^l)
def f(a):
return (1 - sigmoid(a)) * sigmoid(a)
def g(l, j):
if max_layer == l:
return (y[j] - t[j]) * f(A[l - 1][j])
else:
output = 0
m = A[l].shape[0]
for i in range(m):
output += g(l + 1, i) * W[l][i, j] * f(A[l - 1][j])
return output
def diff_w(j, k, l):
return g(l, j) * X[l - 1][k]
def diff_b(j, l):
return g(l, j)
入力
1レイヤー2次元配列(白黒画像)
inputs.npy`
[
[
[0.0 0.0 0.0 ... 0.0 ]
...
],
...
]
教師データ
2クラス分類
true_values.npy`
[
[
[0],[1]
],
...
]
xs = np.load('inputs.npy')[0:101]
ts = np.load('true_values.npy')[0:101]
実行
for x, t in zip(xs, ts):
# 入力層
x1 = x.flatten().reshape(784, 1)
# 中間層入力
a1 = W[0].dot(x1) + b1
# 中間層出力
x2 = sigmoid(a1)
# 出力層入力
a2 = W[1].dot(x2) + b2
# 出力値
y = sigmoid(a2)
# 正否(本格的な実装としては結果保存・学習終了判定が行われる部分)
if np.argmax(y) == np.argmax(t):
print("正解")
else:
print("不正解")
# パラメーター更新に用いる変数
X = [x1, x2]
A = [a1, a2]
# ネットワークのレイヤーサイズ
max_layer = len(X)
# パラメーターw, bの更新
for l in range(len(X)):
for j in range(W[l].shape[0]):
for k in range(W[l].shape[1]):
W[l][j, k] = W[l][j, k] - diff_w(j, k, l + 1)
B[l][j] = B[l][j] - diff_b(j, l + 1)
np.save("w1.npy", W[0])
np.save("w2.npy", W[1])
np.save("b1.npy", B[0])
np.save("b2.npy", B[1])
for x, t in zip(xs, ts):
# 入力層
x1 = x.flatten().reshape(784, 1)
# 中間層入力
a1 = W[0].dot(x1) + b1
# 中間層出力
x2 = sigmoid(a1)
# 出力層入力
a2 = W[1].dot(x2) + b2
# 出力値
y = sigmoid(a2)
# 正否(本格的な実装としては結果保存・学習終了判定が行われる部分)
if np.argmax(y) == np.argmax(t):
print("正解")
else:
print("不正解")
# パラメーター更新に用いる変数
X = [x1, x2]
A = [a1, a2]
# ネットワークのレイヤーサイズ
max_layer = len(X)
# パラメーターw, bの更新
for l in range(len(X)):
for j in range(W[l].shape[0]):
for k in range(W[l].shape[1]):
W[l][j, k] = W[l][j, k] - diff_w(j, k, l + 1)
B[l][j] = B[l][j] - diff_b(j, l + 1)
np.save("w1.npy", W[0])
np.save("w2.npy", W[1])
np.save("b1.npy", B[0])
np.save("b2.npy", B[1])
Author And Source
この問題について(コードで確認するニューラルネットワーク・アルゴリズム), 我々は、より多くの情報をここで見つけました https://qiita.com/yoshiyuki_kono/items/e7cd4ed29809ec854152著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .