目次
- 深層学習(前編・day 1)
- Section1 入力層~中間層
- Section2 活性化関数
- Section3 出力層
- Section4 勾配降下法
- Section5 誤差逆伝播法
導入
なぜ、ほかでもできるのにニューラルネットワークでやるのか?
次元数が増えた時に対応できる
###【確認テスト】
Q.ディープラーニングは、結局何をやろうとしているのか2行以内で述べよ。
A.誤差を最小化するパラメータを発見すること。
Q.また、次の中のどの値の最適化が最終目的か。全て選べ。
A.重み[W]、バイアス[b]
Q.次のネットワークを紙にかけ。
A.
入力層:2ノード1層
中間層:3ノード2層
出力層:1ノード1層
Section1 入力層~中間層
###【考察】
###【実装演習結果】
順伝播(単層・単ユニット)
# 重み
W = np.array([[0.1], [0.2]])
## 試してみよう_配列の初期化
#W = np.zeros(2)
#W = np.ones(2)
#W = np.random.rand(2)
#W = np.random.randint(5, size=(2))
print_vec("重み", W)
# バイアス
b = 0.5
## 試してみよう_数値の初期化
#b = np.random.rand() # 0~1のランダム数値
#b = np.random.rand() * 10 -5 # -5~5のランダム数値
print_vec("バイアス", b)
# 入力値
x = np.array([2, 3])
print_vec("入力", x)
# 総入力
u = np.dot(x, W) + b
print_vec("総入力", u)
# 中間層出力
z = functions.relu(u)
print_vec("中間層出力", z)
*** 重み ***
[[0.1]
[0.2]]
*** バイアス ***
0.5
*** 入力 ***
[2 3]
*** 総入力 ***
[1.3]
*** 中間層出力 ***
[1.3]
###【確認テスト】
Q.この図式に動物の分類の実例を入れてみよう。
A.動物種類分類ネットワーク
Q.この数式をPythonで書け。(Numpyを用いること)
A.
Q.全結合NN - 単層・複数ノードにおいて、1_1_forward_propagation.ipynb のファイルから中間層出力を定義しているソースを抜き出せ。
A.
# 中間層出力
z = functions.relu(u)
###【演習問題】
なし
Section2 活性化関数
-
活性化関数
-
ステップ関数
-
シグモイド関数
-
ReLU 関数
-
ステップ関数
-
人間の脳を模したのに機械的
-
線形分離可能なものしか学習できない
-
シグモイド関数
-
勾配消失問題がある
-
RNN では一番いい
-
ReLU 関数
-
勾配消失問題の回避可
-
スパース化に貢献
-
必ずしも使うものではない、固執しすぎない
###【考察】
###【実装演習結果】
順伝播(単層・複数ユニット)
# 重み
W = np.array([
[0.1, 0.2, 0.3],
[0.2, 0.3, 0.4],
[0.3, 0.4, 0.5],
[0.4, 0.5, 0.6]
])
## 試してみよう_配列の初期化
#W = np.zeros((4,3))
#W = np.ones((4,3))
#W = np.random.rand(4,3)
#W = np.random.randint(5, size=(4,3))
print_vec("重み", W)
# バイアス
b = np.array([0.1, 0.2, 0.3])
print_vec("バイアス", b)
# 入力値
x = np.array([1.0, 5.0, 2.0, -1.0])
print_vec("入力", x)
# 総入力
u = np.dot(x, W) + b
print_vec("総入力", u)
# 中間層出力
z = functions.sigmoid(u)
print_vec("中間層出力", z)
*** 重み ***
[[0.1 0.2 0.3]
[0.2 0.3 0.4]
[0.3 0.4 0.5]
[0.4 0.5 0.6]]
*** バイアス ***
[0.1 0.2 0.3]
*** 入力 ***
[ 1. 5. 2. -1.]
*** 総入力 ***
[1.4 2.2 3. ]
*** 中間層出力 ***
[0.80218389 0.90024951 0.95257413]
###【確認テスト】
Q.線形と非線形の違いを図にかいて簡易に説明せよ。
A.
- 線形
- 非線形
Q.全結合NN - 単層・複数ノードで以下の数式を1_1_forward_propagation.ipynb のファイルから該当する箇所を抜き出せ。
A.
# 中間層出力
z = functions.sigmoid(u)
###【演習問題】
なし
Section3 出力層
3-1 誤差関数
分類問題では平均二乗誤差は使わない
3-2 出力層の活性化関数
###【考察】
###【実装演習結果】
順伝播(3層・複数ユニット)
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
network = {}
#試してみよう
#_各パラメータのshapeを表示
#_ネットワークの初期値ランダム生成
network['W1'] = np.array([
[0.1, 0.3, 0.5],
[0.2, 0.4, 0.6]
])
network['W2'] = np.array([
[0.1, 0.4],
[0.2, 0.5],
[0.3, 0.6]
])
network['W3'] = np.array([
[0.1, 0.3],
[0.2, 0.4]
])
network['b1'] = np.array([0.1, 0.2, 0.3])
network['b2'] = np.array([0.1, 0.2])
network['b3'] = np.array([1, 2])
print_vec("重み1", network['W1'] )
print_vec("重み2", network['W2'] )
print_vec("重み3", network['W3'] )
print_vec("バイアス1", network['b1'] )
print_vec("バイアス2", network['b2'] )
print_vec("バイアス3", network['b3'] )
return network
# プロセスを作成
# x:入力値
def forward(network, x):
print("##### 順伝播開始 #####")
W1, W2, W3 = network['W1'], network['W2'], network['W3']
b1, b2, b3 = network['b1'], network['b2'], network['b3']
# 1層の総入力
u1 = np.dot(x, W1) + b1
# 1層の総出力
z1 = functions.relu(u1)
# 2層の総入力
u2 = np.dot(z1, W2) + b2
# 2層の総出力
z2 = functions.relu(u2)
# 出力層の総入力
u3 = np.dot(z2, W3) + b3
# 出力層の総出力
y = u3
print_vec("総入力1", u1)
print_vec("中間層出力1", z1)
print_vec("総入力2", u2)
print_vec("出力1", z1)
print("出力合計: " + str(np.sum(z1)))
return y, z1, z2
# 入力値
x = np.array([1., 2.])
print_vec("入力", x)
# ネットワークの初期化
network = init_network()
y, z1, z2 = forward(network, x)
*** 入力 ***
[1. 2.]
##### ネットワークの初期化 #####
*** 重み1 ***
[[0.1 0.3 0.5]
[0.2 0.4 0.6]]
*** 重み2 ***
[[0.1 0.4]
[0.2 0.5]
[0.3 0.6]]
*** 重み3 ***
[[0.1 0.3]
[0.2 0.4]]
*** バイアス1 ***
[0.1 0.2 0.3]
*** バイアス2 ***
[0.1 0.2]
*** バイアス3 ***
[1 2]
##### 順伝播開始 #####
*** 総入力1 ***
[0.6 1.3 2. ]
*** 中間層出力1 ***
[0.6 1.3 2. ]
*** 総入力2 ***
[1.02 2.29]
*** 出力1 ***
[0.6 1.3 2. ]
出力合計: 3.9
多クラス分類(2-3-4ネットワーク)
# 2-3-4ネットワーク
# !試してみよう_ノードの構成を 3-5-4 に変更してみよう
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
#試してみよう
#_各パラメータのshapeを表示
#_ネットワークの初期値ランダム生成
network = {}
network['W1'] = np.array([
[0.1, 0.3, 0.5],
[0.2, 0.4, 0.6]
])
network['W2'] = np.array([
[0.1, 0.4, 0.7, 1.0],
[0.2, 0.5, 0.8, 1.1],
[0.3, 0.6, 0.9, 1.2]
])
network['b1'] = np.array([0.1, 0.2, 0.3])
network['b2'] = np.array([0.1, 0.2, 0.3, 0.4])
print_vec("重み1", network['W1'] )
print_vec("重み2", network['W2'] )
print_vec("バイアス1", network['b1'] )
print_vec("バイアス2", network['b2'] )
return network
# プロセスを作成
# x:入力値
def forward(network, x):
print("##### 順伝播開始 #####")
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
# 1層の総入力
u1 = np.dot(x, W1) + b1
# 1層の総出力
z1 = functions.relu(u1)
# 2層の総入力
u2 = np.dot(z1, W2) + b2
# 出力値
y = functions.softmax(u2)
print_vec("総入力1", u1)
print_vec("中間層出力1", z1)
print_vec("総入力2", u2)
print_vec("出力1", y)
print("出力合計: " + str(np.sum(y)))
return y, z1
## 事前データ
# 入力値
x = np.array([1., 2.])
# 目標出力
d = np.array([0, 0, 0, 1])
# ネットワークの初期化
network = init_network()
# 出力
y, z1 = forward(network, x)
# 誤差
loss = functions.cross_entropy_error(d, y)
## 表示
print("\n##### 結果表示 #####")
print_vec("出力", y)
print_vec("訓練データ", d)
print_vec("誤差", loss)
##### ネットワークの初期化 #####
*** 重み1 ***
[[0.1 0.3 0.5]
[0.2 0.4 0.6]]
*** 重み2 ***
[[0.1 0.4 0.7 1. ]
[0.2 0.5 0.8 1.1]
[0.3 0.6 0.9 1.2]]
*** バイアス1 ***
[0.1 0.2 0.3]
*** バイアス2 ***
[0.1 0.2 0.3 0.4]
##### 順伝播開始 #####
*** 総入力1 ***
[0.6 1.3 2. ]
*** 中間層出力1 ***
[0.6 1.3 2. ]
*** 総入力2 ***
[1.02 2.29 3.56 4.83]
*** 出力1 ***
[0.01602796 0.05707321 0.20322929 0.72366954]
出力合計: 1.0
##### 結果表示 #####
*** 出力 ***
[0.01602796 0.05707321 0.20322929 0.72366954]
*** 訓練データ ***
[0 0 0 1]
*** 誤差 ***
0.3234202933601941
回帰(2-3-2ネットワーク)
# !試してみよう_ノードの構成を 3-5-4 に変更してみよう
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
network = {}
network['W1'] = np.array([
[0.1, 0.3, 0.5],
[0.2, 0.4, 0.6]
])
network['W2'] = np.array([
[0.1, 0.4],
[0.2, 0.5],
[0.3, 0.6]
])
network['b1'] = np.array([0.1, 0.2, 0.3])
network['b2'] = np.array([0.1, 0.2])
print_vec("重み1", network['W1'] )
print_vec("重み2", network['W2'] )
print_vec("バイアス1", network['b1'] )
print_vec("バイアス2", network['b2'] )
return network
# プロセスを作成
def forward(network, x):
print("##### 順伝播開始 #####")
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
# 隠れ層の総入力
u1 = np.dot(x, W1) + b1
# 隠れ層の総出力
z1 = functions.relu(u1)
# 出力層の総入力
u2 = np.dot(z1, W2) + b2
# 出力層の総出力
y = u2
print_vec("総入力1", u1)
print_vec("中間層出力1", z1)
print_vec("総入力2", u2)
print_vec("出力1", y)
print("出力合計: " + str(np.sum(z1)))
return y, z1
# 入力値
x = np.array([1., 2.])
network = init_network()
y, z1 = forward(network, x)
# 目標出力
d = np.array([2., 4.])
# 誤差
loss = functions.mean_squared_error(d, y)
## 表示
print("\n##### 結果表示 #####")
print_vec("中間層出力", z1)
print_vec("出力", y)
print_vec("訓練データ", d)
print_vec("誤差", loss)
##### ネットワークの初期化 #####
*** 重み1 ***
[[0.1 0.3 0.5]
[0.2 0.4 0.6]]
*** 重み2 ***
[[0.1 0.4]
[0.2 0.5]
[0.3 0.6]]
*** バイアス1 ***
[0.1 0.2 0.3]
*** バイアス2 ***
[0.1 0.2]
##### 順伝播開始 #####
*** 総入力1 ***
[0.6 1.3 2. ]
*** 中間層出力1 ***
[0.6 1.3 2. ]
*** 総入力2 ***
[1.02 2.29]
*** 出力1 ***
[1.02 2.29]
出力合計: 3.9
##### 結果表示 #####
*** 中間層出力 ***
[0.6 1.3 2. ]
*** 出力 ***
[1.02 2.29]
*** 訓練データ ***
[2. 4.]
*** 誤差 ***
0.9711249999999999
2値分類(2-3-1ネットワーク)
# !試してみよう_ノードの構成を 5-10-1 に変更してみよう
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
network = {}
network['W1'] = np.array([
[0.1, 0.3, 0.5],
[0.2, 0.4, 0.6]
])
network['W2'] = np.array([
[0.2],
[0.4],
[0.6]
])
network['b1'] = np.array([0.1, 0.2, 0.3])
network['b2'] = np.array([0.1])
return network
# プロセスを作成
def forward(network, x):
print("##### 順伝播開始 #####")
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
# 隠れ層の総入力
u1 = np.dot(x, W1) + b1
# 隠れ層の総出力
z1 = functions.relu(u1)
# 出力層の総入力
u2 = np.dot(z1, W2) + b2
# 出力層の総出力
y = functions.sigmoid(u2)
print_vec("総入力1", u1)
print_vec("中間層出力1", z1)
print_vec("総入力2", u2)
print_vec("出力1", y)
print("出力合計: " + str(np.sum(z1)))
return y, z1
# 入力値
x = np.array([1., 2.])
# 目標出力
d = np.array([1])
network = init_network()
y, z1 = forward(network, x)
# 誤差
loss = functions.cross_entropy_error(d, y)
## 表示
print("\n##### 結果表示 #####")
print_vec("中間層出力", z1)
print_vec("出力", y)
print_vec("訓練データ", d)
print_vec("誤差", loss)
##### ネットワークの初期化 #####
##### 順伝播開始 #####
*** 総入力1 ***
[0.6 1.3 2. ]
*** 中間層出力1 ***
[0.6 1.3 2. ]
*** 総入力2 ***
[1.94]
*** 出力1 ***
[0.87435214]
出力合計: 3.9
##### 結果表示 #####
*** 中間層出力 ***
[0.6 1.3 2. ]
*** 出力 ***
[0.87435214]
*** 訓練データ ***
[1]
*** 誤差 ***
0.13427195993720972
###【確認テスト】
Q.なぜ、引き算ではなく二乗するか述べよ
A.値を正にするため
A.微分を簡単にするため
Q.①~③の数式に該当するソースコードを示し、一行ずつ処理を説明せよ。
ベクトル前提
①:def softmax(x):
配列の全要素について指数関数の値を計算している。
②:np.exp(x)
配列の全要素について指数関数の値を計算している。
③:np.sum(np.exp(x), axis=0)
配列の全要素について指数関数の値を総和で割っている。
①:def cross_entropy_error(d, y):
yはNNの出力となる。
②:-np.sum(np.log(y[np.arrange(batch_size), d] + 1e-7)) / batch_size
0にならないように微小な値を加算している。
###【演習問題】
なし
Section4 勾配降下法
###深層学習の目的
- 学習を通して誤差を最小にするネットワークを作成すること
- 誤差E(w)を最小化するパラメータwを発見すること
- 勾配降下法を利用してパラメータを最適化
###勾配降下法
- 勾配降下法
- バッチ勾配降下法(最急降下法)
- 確率的勾配降下法(SGD)
- ミニバッチ勾配降下法
###【考察】
###【実装演習結果】
import numpy as np
from common import functions
import matplotlib.pyplot as plt
def print_vec(text, vec):
print("*** " + text + " ***")
print(vec)
#print("shape: " + str(x.shape))
print("")
# サンプルとする関数
#yの値を予想するAI
def f(x):
y = 3 * x[0] + 2 * x[1]
return y
# 初期設定
def init_network():
# print("##### ネットワークの初期化 #####")
network = {}
nodesNum = 10
network['W1'] = np.random.randn(2, nodesNum)
network['W2'] = np.random.randn(nodesNum)
network['b1'] = np.random.randn(nodesNum)
network['b2'] = np.random.randn()
# print_vec("重み1", network['W1'])
# print_vec("重み2", network['W2'])
# print_vec("バイアス1", network['b1'])
# print_vec("バイアス2", network['b2'])
return network
# 順伝播
def forward(network, x):
# print("##### 順伝播開始 #####")
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
u1 = np.dot(x, W1) + b1
z1 = functions.relu(u1)
## 試してみよう
#z1 = functions.sigmoid(u1)
u2 = np.dot(z1, W2) + b2
y = u2
# print_vec("総入力1", u1)
# print_vec("中間層出力1", z1)
# print_vec("総入力2", u2)
# print_vec("出力1", y)
# print("出力合計: " + str(np.sum(y)))
return z1, y
# 誤差逆伝播
def backward(x, d, z1, y):
# print("\n##### 誤差逆伝播開始 #####")
grad = {}
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
# 出力層でのデルタ
delta2 = functions.d_mean_squared_error(d, y)
# b2の勾配
grad['b2'] = np.sum(delta2, axis=0)
# W2の勾配
grad['W2'] = np.dot(z1.T, delta2)
# 中間層でのデルタ
#delta1 = np.dot(delta2, W2.T) * functions.d_relu(z1)
## 試してみよう
delta1 = np.dot(delta2, W2.T) * functions.d_sigmoid(z1)
delta1 = delta1[np.newaxis, :]
# b1の勾配
grad['b1'] = np.sum(delta1, axis=0)
x = x[np.newaxis, :]
# W1の勾配
grad['W1'] = np.dot(x.T, delta1)
# print_vec("偏微分_重み1", grad["W1"])
# print_vec("偏微分_重み2", grad["W2"])
# print_vec("偏微分_バイアス1", grad["b1"])
# print_vec("偏微分_バイアス2", grad["b2"])
return grad
# サンプルデータを作成
data_sets_size = 100000
data_sets = [0 for i in range(data_sets_size)]
for i in range(data_sets_size):
data_sets[i] = {}
# ランダムな値を設定
data_sets[i]['x'] = np.random.rand(2)
## 試してみよう_入力値の設定
# data_sets[i]['x'] = np.random.rand(2) * 10 -5 # -5〜5のランダム数値
# 目標出力を設定
data_sets[i]['d'] = f(data_sets[i]['x'])
losses = []
# 学習率
learning_rate = 0.07
# 抽出数
epoch = 1000
# パラメータの初期化
network = init_network()
# データのランダム抽出
random_datasets = np.random.choice(data_sets, epoch)
# 勾配降下の繰り返し
for dataset in random_datasets:
x, d = dataset['x'], dataset['d']
z1, y = forward(network, x)
grad = backward(x, d, z1, y)
# パラメータに勾配適用
for key in ('W1', 'W2', 'b1', 'b2'):
network[key] -= learning_rate * grad[key]
# 誤差
loss = functions.mean_squared_error(d, y)
losses.append(loss)
print("##### 結果表示 #####")
lists = range(epoch)
plt.plot(lists, losses, '.')
# グラフの表示
plt.show()
###【確認テスト】
1_2_back_propagation.ipynb フォイルより
network[key] -= learning_rate * grad[key]
grad = backward(x, d, z1, y)
Q.オンライン学習とは何か2行でまとめよ
A.新しく入ってきたユーザーのデータのみで学習をさせていく。既存のモデルを更に学習させていく。
###【演習問題】
なし
Section5 誤差逆伝播法(Back Propagation)
算出された誤差を、出力層側から順に微分し、前の層へと伝播。
最小の計算で各パラメータでの微分値を解析的に計算する手法
- 計算リソースをくわれないようにする。
###【考察】
###【実装演習結果】
import numpy as np
from common import functions
import matplotlib.pyplot as plt
def print_vec(text, vec):
print("*** " + text + " ***")
print(vec)
#print("shape: " + str(x.shape))
print("")
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
network = {}
network['W1'] = np.array([
[0.1, 0.3, 0.5],
[0.2, 0.4, 0.6]
])
network['W2'] = np.array([
[0.1, 0.4],
[0.2, 0.5],
[0.3, 0.6]
])
network['b1'] = np.array([0.1, 0.2, 0.3])
network['b2'] = np.array([0.1, 0.2])
print_vec("重み1", network['W1'])
print_vec("重み2", network['W2'])
print_vec("バイアス1", network['b1'])
print_vec("バイアス2", network['b2'])
return network
# 順伝播
def forward(network, x):
print("##### 順伝播開始 #####")
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
u1 = np.dot(x, W1) + b1
z1 = functions.relu(u1)
u2 = np.dot(z1, W2) + b2
y = functions.softmax(u2)
print_vec("総入力1", u1)
print_vec("中間層出力1", z1)
print_vec("総入力2", u2)
print_vec("出力1", y)
print("出力合計: " + str(np.sum(y)))
return y, z1
# 誤差逆伝播
def backward(x, d, z1, y):
print("\n##### 誤差逆伝播開始 #####")
grad = {}
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
# 出力層でのデルタ
delta2 = functions.d_sigmoid_with_loss(d, y)
# b2の勾配
grad['b2'] = np.sum(delta2, axis=0)
# W2の勾配
grad['W2'] = np.dot(z1.T, delta2)
# 中間層でのデルタ
delta1 = np.dot(delta2, W2.T) * functions.d_relu(z1)
# b1の勾配
grad['b1'] = np.sum(delta1, axis=0)
# W1の勾配
grad['W1'] = np.dot(x.T, delta1)
print_vec("偏微分_dE/du2", delta2)
print_vec("偏微分_dE/du2", delta1)
print_vec("偏微分_重み1", grad["W1"])
print_vec("偏微分_重み2", grad["W2"])
print_vec("偏微分_バイアス1", grad["b1"])
print_vec("偏微分_バイアス2", grad["b2"])
return grad
# 訓練データ
x = np.array([[1.0, 5.0]])
# 目標出力
d = np.array([[0, 1]])
# 学習率
learning_rate = 0.01
network = init_network()
y, z1 = forward(network, x)
# 誤差
loss = functions.cross_entropy_error(d, y)
grad = backward(x, d, z1, y)
for key in ('W1', 'W2', 'b1', 'b2'):
network[key] -= learning_rate * grad[key]
print("##### 結果表示 #####")
print("##### 更新後パラメータ #####")
print_vec("重み1", network['W1'])
print_vec("重み2", network['W2'])
print_vec("バイアス1", network['b1'])
print_vec("バイアス2", network['b2'])
##### ネットワークの初期化 #####
*** 重み1 ***
[[0.1 0.3 0.5]
[0.2 0.4 0.6]]
*** 重み2 ***
[[0.1 0.4]
[0.2 0.5]
[0.3 0.6]]
*** バイアス1 ***
[0.1 0.2 0.3]
*** バイアス2 ***
[0.1 0.2]
##### 順伝播開始 #####
*** 総入力1 ***
[[1.2 2.5 3.8]]
*** 中間層出力1 ***
[[1.2 2.5 3.8]]
*** 総入力2 ***
[[1.86 4.21]]
*** 出力1 ***
[[0.08706577 0.91293423]]
出力合計: 0.9999999999999999
##### 誤差逆伝播開始 #####
*** 偏微分_dE/du2 ***
[[ 0.08706577 -0.08706577]]
*** 偏微分_dE/du2 ***
[[-0.02611973 -0.02611973 -0.02611973]]
*** 偏微分_重み1 ***
[[-0.02611973 -0.02611973 -0.02611973]
[-0.13059866 -0.13059866 -0.13059866]]
*** 偏微分_重み2 ***
[[ 0.10447893 -0.10447893]
[ 0.21766443 -0.21766443]
[ 0.33084994 -0.33084994]]
*** 偏微分_バイアス1 ***
[-0.02611973 -0.02611973 -0.02611973]
*** 偏微分_バイアス2 ***
[ 0.08706577 -0.08706577]
##### 結果表示 #####
##### 更新後パラメータ #####
*** 重み1 ***
[[0.1002612 0.3002612 0.5002612 ]
[0.20130599 0.40130599 0.60130599]]
*** 重み2 ***
[[0.09895521 0.40104479]
[0.19782336 0.50217664]
[0.2966915 0.6033085 ]]
*** バイアス1 ***
[0.1002612 0.2002612 0.3002612]
*** バイアス2 ***
[0.09912934 0.20087066]
###【確認テスト】
Q.誤差逆伝播法では不要な再帰的処理を避ける事が出来る。既に行った計算結果を保持しているソースコードを抽出せよ。
A.以下の 1_2_back_propagation.ipynb のファイルの delta2
# 誤差逆伝播
def backward(x, d, z1, y):
print("\n##### 誤差逆伝播開始 #####")
grad = {}
W1, W2 = network['W1'], network['W2']
b1, b2 = network['b1'], network['b2']
# 出力層でのデルタ
delta2 = functions.d_sigmoid_with_loss(d, y)
# b2の勾配
grad['b2'] = np.sum(delta2, axis=0)
# W2の勾配
grad['W2'] = np.dot(z1.T, delta2)
# 中間層でのデルタ
delta1 = np.dot(delta2, W2.T) * functions.d_relu(z1)
# b1の勾配
grad['b1'] = np.sum(delta1, axis=0)
# W1の勾配
grad['W1'] = np.dot(x.T, delta1)
print_vec("偏微分_dE/du2", delta2)
print_vec("偏微分_dE/du2", delta1)
print_vec("偏微分_重み1", grad["W1"])
print_vec("偏微分_重み2", grad["W2"])
print_vec("偏微分_バイアス1", grad["b1"])
print_vec("偏微分_バイアス2", grad["b2"])
return grad
# 出力層でのデルタ
delta2 = functions.d_mean_squared_error(d, y)
delta2 = functions.d_mean_squared_error(d, y)
# W2の勾配
grad['W2'] = np.dot(z1.T, delta2)
###【演習問題】