More Related Content
Similar to 深層学習レポート Day1 (小川成) (20)
深層学習レポート Day1 (小川成)
- 1. 深層学習 Day1 レポート
小川成
深層学習 Day1
1.1 入力層、中間層
●ニューラルネットワーク
人間の脳の神経回路の仕組みを模倣したアルゴリズムで、入力層、中間層、出
力層の 3 種類の層からなる。
*ニューラルネットワークの中間層を増やしたものがディープラーニングで
ある
*確認テスト
問題 1
・ディープラーニングは結局何をやろうとしているのか 2 行以内で述べよ。
複数の隠れ層を持つ数学的なネットワーク
(ニューラルネットワーク)
を構築
して、入力値から出力値を求めること。
・ニューラルネットワークは、どの値の最適化が最終目的か?
重み、バイアス
問題 2
・次のニューラルネットワークをかけ。
入力層:2 ノード 1 層、中間層:3 ノード 2 層、出力層:1 ノード 1 層
- 2. 入力層 中間層 出力層
●入力層 中間層 出力層
入力層は入力を受け取る部分、
出力層は出力する部分である。
入力層と出力層
の間に追加されたのが中間層(隠れ層)である。
入力層に説明変数 x を入力すると、x に重み w を掛けてバイアス b を加えて中
間層に送る。
中間層では、
送られた情報を活性化関数に通して調整し次の中間層
に送る。最終的に情報は出力層に送られここ活性化関数に通され出力される。
*確認テスト
・動物分類の実例
- 3. ・次の数式を Python で書け。
u = w1x1+w2x2+w3x3+w4x4+b = Wx+b
1 import numpy as np
2 u = np.dot(x, W) + b
・
「1_1_forward_propagation.ipynb」のファイルから中間層の出力を定義している
ソースを抜き出せ
z2 = functions. relu(u2)
1.2 活性化関数
●活性化関数
ニューラルネットワークにおいて、次の層への出力の大きさを決める非線形
の関数のこと。
入力値の値によって、
次の層への信号の ON/OFF や強弱を定める
働きをもつ。
●活性化関数の種類
*中間層用の活性化関数
ステップ関数 ReLU 関数 シグモイド(ロジスティック)関数
*出力層用の活性化関数
体長
体重
さ
毛の色
足の長さ
バイアス
- 5. *確認テスト
・配布されたソースコードより z=f(u)に該当する箇所を抜き出せ。
z1 = functions.sigmoid(u)
1.3 出力層
●誤差関数
機械学習などにおいて、教師データの真値とモデルの推定値との誤差からモ
デルの精度を評価するための関数で、損失関数とも呼ばれる。
誤差関数には平均二乗誤差、
クロスエントロピー誤差などがあり、
この誤差関
数から得られた値が小さければ推定値が真値に近いと言える。
*確認テスト
・平均二乗誤差において、なぜ二乗するのか。
誤差に正や負の値が混在したままだと、合計したときに正しく誤差の総量を
計算することができないため。
・平均二乗誤差において、なぜ 1/2 しているのか。
二乗は微分すると 2 が係数として前に出てくるので、1/2 をしておくことで
- 7. def cross_entropy_error(d, y):
if y.ndim == 1:
d = d.reshape(1, d.size) # 1×d の行列に変換
y = y.reshape(1, y.size) # 1×y の行列に変換
# 教師データが one-hot-vector の場合、正解ラベルのインデックスに変換
if d.size == y.size:
d = d.argmax(axis=1) # d が最大となるインデックスを取得
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size
# 1e-7 を加えて log がマイナス無限大にならないようにしている
1.4 勾配降下法
●勾配法
現在の地点から勾配方向に一定の距離だけ進み、進んだ先でも同様に勾配を
求めさらにその勾配方向に進む、
というように、
勾配方向に進むことを繰り返す
ことで関数の値を徐々に減らす方法のこと。
最小値を探す場合を勾配降下法、
最大値を探す場合を勾配上昇法という。
一般
にディープラーニングの分野では勾配降下法として登場することが多い。
●勾配降下法
右の式で重みを調整する wt+1
= wt
− ε∇E
学習率εの値によって学習の効率が大きく異なる。学習率が大きすぎた場合、
最小値にいつまでもたどり着かず発散する。
学習率が小さい場合は、
発散するこ
とはないが、小さすぎると収束するまでに時間がかかる。
勾配降下法の学習率の決定、収束性向上のためのアルゴリズムについては、
Momentum•AdaGrad•Adadelta•Adam などがある。
●確率的勾配降下法
無作為に選びだしたデータに対して行う勾配降下法のこと。
メリットとしては、
データが冗長な場合に計算コストが軽減できること、
望ま
ない局所極小解に収束するリスクが軽減できること、オンライン学習ができる
こと等が挙げられる。
*確認テスト
オンライン学習とは何か 2 行でまとめよ
- 10. *確認テスト
・誤差逆伝播法では不要な再帰的処理を避ける事が出来る。
既に行った計算結果
を保持しているソースコードを抽出せよ。
# 出力層でのデルタ
delta2 = 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) * d_relu(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)
delta2 = functions.d_mean_squared_error(d, y)
grad['W2'] = np.dot(z1.T, delta2)
- 12. # 中間層出力
z = functions.relu(u)
print_vec("中間層出力", z)
*** 重み ***
[[0.1]
[0.2]]
shape: (2, 1)
*** バイアス ***
0.5
shape: ()
*** 入力 ***
[2 3]
shape: (2,)
*** 総入力 ***
[1.3]
shape: (1,)
*** 中間層出力 ***
[1.3]
shape: (1,)
# 順伝播(単層・複数ユニット)
# 重み
W = np.array([
[0.1, 0.2, 0.3,0],
[0.2, 0.3, 0.4, 0.5],
[0.3, 0.4, 0.5, 1],
])
## 試してみよう_配列の初期化
#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(W, x) + b
print_vec("総入力", u)
- 13. # 中間層出力
z = functions.sigmoid(u)
print_vec("中間層出力", z)
*** 重み ***
[[0.1 0.2 0.3 0. ]
[0.2 0.3 0.4 0.5]
[0.3 0.4 0.5 1. ]]
shape: (3, 4)
*** バイアス ***
[0.1 0.2 0.3]
shape: (3,)
*** 入力 ***
[ 1. 5. 2. -1.]
shape: (4,)
*** 総入力 ***
[1.8 2.2 2.6]
shape: (3,)
*** 中間層出力 ***
[0.85814894 0.90024951 0.93086158]
shape: (3,)
# 順伝播(3層・複数ユニット)
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
network = {}
input_layer_size = 3
hidden_layer_size_1=10
hidden_layer_size_2=5
output_layer_size = 4
#試してみよう
#_各パラメータのshapeを表示
#_ネットワークの初期値ランダム生成
network['W1'] = np.random.rand(input_layer_size, hidden_layer_size_1)
network['W2'] = np.random.rand(hidden_layer_size_1,hidden_layer_size_2)
network['W3'] = np.random.rand(hidden_layer_size_2,output_layer_size)
network['b1'] = np.random.rand(hidden_layer_size_1)
network['b2'] = np.random.rand(hidden_layer_size_2)
network['b3'] = np.random.rand(output_layer_size)
print_vec("重み1", network['W1'] )
print_vec("重み2", network['W2'] )
print_vec("重み3", network['W3'] )
print_vec("バイアス1", network['b1'] )
- 14. 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", z2)
print_vec("総入力2", u2)
print_vec("出力", y)
print("出力合計: " + str(np.sum(y)))
return y, z1, z2
# 入力値
x = np.array([1., 2., 4.])
print_vec("入力", x)
# ネットワークの初期化
network = init_network()
y, z1, z2 = forward(network, x)
*** 入力 ***
[1. 2. 4.]
shape: (3,)
##### ネットワークの初期化 #####
- 15. *** 重み1 ***
[[0.76788308 0.61783763 0.46908725 0.45011238 0.37530433 0.44771515
0.95779012 0.59275012 0.6607197 0.09999839]
[0.33149087 0.48725686 0.33507135 0.31762837 0.60326346 0.90829117
0.60998296 0.34103569 0.39573001 0.65150765]
[0.9640735 0.36260528 0.8890738 0.17178219 0.76980018 0.65020127
0.96973509 0.07756386 0.45165582 0.99043394]]
shape: (3, 10)
*** 重み2 ***
[[0.18508693 0.80868705 0.42764628 0.67872143 0.08380248]
[0.58278012 0.90737129 0.75590162 0.45776993 0.49405233]
[0.44212727 0.85660811 0.85468992 0.46750003 0.05253438]
[0.02797267 0.71767473 0.77172627 0.35095216 0.31303922]
[0.05704115 0.96988805 0.08828619 0.11715234 0.72272908]
[0.45832451 0.10688213 0.99840129 0.06391107 0.53389257]
[0.36128767 0.56185404 0.88769913 0.85363433 0.08763928]
[0.24942882 0.22918336 0.09413573 0.86469964 0.78310769]
[0.80048577 0.97580471 0.78843806 0.60075663 0.63357861]
[0.92199269 0.05346493 0.80463222 0.09772418 0.24382323]]
shape: (10, 5)
*** 重み3 ***
[[0.97639045 0.01428914 0.68240344 0.31508198]
[0.73321524 0.89878956 0.03410484 0.78101049]
[0.71563323 0.59940735 0.4358238 0.28356609]
[0.91505802 0.27144564 0.01282042 0.60047218]
[0.05323631 0.88377715 0.11584928 0.17547949]]
shape: (5, 4)
*** バイアス1 ***
[0.69610573 0.25964581 0.67460168 0.6645556 0.86688697 0.3282057
0.68966354 0.47533902 0.0177151 0.28174676]
shape: (10,)
*** バイアス2 ***
[0.67545814 0.45749323 0.55645954 0.69586708 0.61996458]
shape: (5,)
*** バイアス3 ***
[0.65663813 0.44797573 0.34316529 0.26238857]
shape: (4,)
##### 順伝播開始 #####
*** 総入力1 ***
[5.98326456 3.30241828 5.37012685 2.43705348 5.52791896 5.19330829
6.74635993 2.06041596 3.2765181 5.64649621]
shape: (10,)
*** 中間層出力1 ***
[5.98326456 3.30241828 5.37012685 2.43705348 5.52791896 5.19330829
6.74635993 2.06041596 3.2765181 5.64649621]
shape: (10 )
np.random.rand(3, 3)
array([[0.7873957 , 0.91583055, 0.52600902],
[0.28931722, 0.11851705, 0.39079024],
[0.07848529, 0.43169948, 0.46256512]])
- 16. # 多クラス分類
# 2-3-4ネットワーク
# !試してみよう_ノードの構成を 3-5-6 に変更してみよう
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
#試してみよう
#_各パラメータのshapeを表示
#_ネットワークの初期値ランダム生成
network = {}
input_layer_size = 3
hidden_layer_size=50
output_layer_size = 6
#試してみよう
#_各パラメータのshapeを表示
#_ネットワークの初期値ランダム生成
network['W1'] = np.random.rand(input_layer_size, hidden_layer_size)
network['W2'] = np.random.rand(hidden_layer_size,output_layer_size)
network['b1'] = np.random.rand(hidden_layer_size)
network['b2'] = np.random.rand(output_layer_size)
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
# 出力値
- 17. 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., 3.])
# 目標出力
d = np.array([0, 0, 0, 1, 0, 0])
# ネットワークの初期化
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.81664673 0.66117742 0.98494001 0.92684099 0.95198527 0.36542309
0.62526078 0.59354508 0.2302813 0.62327413 0.14483389 0.15215754
0.98251545 0.74646471 0.14256724 0.20007355 0.73726682 0.18777798
0.10798765 0.234723 0.30724402 0.22061331 0.57054401 0.19061807
0.85358103 0.84531822 0.97837369 0.23495263 0.6196084 0.34725422
0.46912108 0.16481474 0.66751087 0.57158124 0.28861189 0.68806929
0.8136607 0.67010322 0.22752684 0.51113229 0.71862915 0.22090939
0.50550733 0.41117085 0.05660434 0.87044166 0.99565195 0.15380451
0.72601104 0.85668568]
[0.60696913 0.36286744 0.99755169 0.94471112 0.81931211 0.28844445
0.72327442 0.19416267 0.75663491 0.49468682 0.93738496 0.86551935
0.88189454 0.0925937 0.41282635 0.66574596 0.25881315 0.81907834
0.64229448 0.54221278 0.63223432 0.48380537 0.15813657 0.41886699
0.25030841 0.69863132 0.91391844 0.66024884 0.18537009 0.53570131
0.09214697 0.73187118 0.18825126 0.30970908 0.62142286 0.26663463
0.82303185 0.5078077 0.57119769 0.98826844 0.82225491 0.37741844
0.94521464 0.80650207 0.55679436 0.14418292 0.91502394 0.47273298
0.36780546 0.64372357]
[0.25575347 0.80391319 0.96406595 0.72385761 0.29808324 0.95028724
0.13420243 0.60764686 0.05544959 0.40785224 0.96219423 0.77367302
0.0203607 0.21002377 0.75021304 0.59620056 0.33847571 0.13799206
- 18. 0.97440516 0.55725763 0.2102844 0.67055532 0.90879796 0.01657522
0.36511416 0.54815221 0.6595643 0.48976887 0.27490741 0.01263375
0.74271443 0.51524702 0.21294617 0.4032406 0.39611448 0.9228164
0.33901332 0.31953151 0.67139212 0.74756567 0.4402927 0.46453525
0.17853269 0.51373165 0.28427929 0.58447118 0.53212676 0.33943936
0.01324933 0.9956963 ]]
shape: (3, 50)
*** 重み2 ***
[[4.34636701e-01 9.62198509e-01 1.83784780e-01 2.45681668e-01
5.89282102e-02 3.69258705e-01]
[6.97266946e-01 9.26040954e-01 5.97729187e-01 8.16458297e-01
8.34751817e-01 4.24368523e-01]
[3.60617161e-01 3.86508397e-01 5.55459929e-01 5.00804229e-01
7.70217717e-01 6.17069173e-01]
[8.25446014e-01 5.67878313e-01 5.77487097e-01 1.93256320e-01
6.19877610e-01 7.58609568e-01]
[3.79269663e-01 7.06873523e-01 4.05945749e-01 7.90742434e-01
7.98764524e-01 6.55040955e-01]
[2.18144604e-01 3.92654077e-01 3.54676484e-03 6.70709096e-01
6.93348129e-01 8.34210516e-01]
[8.21203495e-01 3.82175275e-01 1.72760879e-02 2.39189947e-01
8.63734807e-01 5.40327383e-01]
[2.68583832e-01 1.09719582e-01 4.75371743e-01 4.32752079e-01
6.49199173e-01 3.75734028e-03]
[1.60936002e-02 9.95860311e-01 7.29052891e-01 1.41889538e-01
3.08663887e-01 2.51749268e-01]
[6.65211963e-01 9.07397564e-01 6.76113380e-01 3.61291403e-01
8.03836381e-01 7.09071864e-01]
[6.35853177e-01 7.65558840e-01 7.79219105e-04 9.79021380e-01
7.09419019e-01 1.55445704e-01]
[5.49175338e-01 9.57553884e-01 4.50186550e-01 4.74114415e-01
2.34094169e-01 3.09419564e-01]
[4.07844121e-01 9.43019746e-01 4.98756948e-01 8.39002730e-01
5.45961564e-02 4.10610328e-01]
# 回帰
# 2-3-2ネットワーク
# !試してみよう_ノードの構成を 3-5-4 に変更してみよう
# ウェイトとバイアスを設定
# ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
input_layer_size = 3
hidden_layer_size=50
output_layer_size = 2
#試してみよう
#_各パラメータのshapeを表示
#_ネットワークの初期値ランダム生成
network['W1'] = np.random.rand(input_layer_size, hidden_layer_size)
network['W2'] = np.random.rand(hidden_layer_size,output_layer_size)
network['b1'] = np.random.rand(hidden_layer_size)
- 19. network['b2'] = np.random.rand(output_layer_size)
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(y)))
return y, z1
# 入力値
x = np.array([1., 2., 3.])
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.53735385 0.11720183 0.1590663 0.75865957 0.00483563 0.4620968
0.45452085 0.66799545 0.78615021 0.58786555 0.78760677 0.32018234
0.0250694 0.45427252 0.09683763 0.73745794 0.69669923 0.70767483
0.40848892 0.0795976 0.27165638 0.58616406 0.13297729 0.1173601
- 20. 0.63098916 0.2935411 0.98770462 0.42499501 0.43806812 0.50650691
0.97614711 0.24679257 0.47918329 0.26644097 0.18194972 0.26639986
0.26836372 0.68103433 0.69398316 0.7038327 0.85100622 0.45728601
0.15628074 0.5560033 0.07028035 0.18146832 0.54520106 0.66939622
0.70257024 0.92872044]
[0.20456671 0.79028815 0.11094513 0.31536472 0.21491419 0.50246648
0.4868002 0.68934707 0.82493115 0.80492811 0.46146971 0.09274782
0.66416819 0.7752301 0.10506177 0.90938752 0.13744704 0.43245536
0.88955323 0.68670091 0.28072696 0.61813519 0.74628255 0.01323193
0.98530476 0.4067796 0.2719345 0.74887557 0.33213546 0.00232234
0.02963184 0.13021986 0.72534451 0.18153313 0.05883038 0.15715227
0.93893534 0.08317978 0.23421133 0.41914331 0.8935291 0.0548546
0.9054219 0.19716535 0.58669053 0.51031172 0.59600586 0.54496187
0.8633502 0.41276424]
[0.3047837 0.81879544 0.78685141 0.77105237 0.09420756 0.31063191
0.98684236 0.14402394 0.87725014 0.29677119 0.98405788 0.25002851
0.87213105 0.36046737 0.21587422 0.23704409 0.86212838 0.98277289
0.52869313 0.94113143 0.6473041 0.68614194 0.73548341 0.7730013
0.51223727 0.21775624 0.57727663 0.04275065 0.51407386 0.98143814
0.01701889 0.05600605 0.85453016 0.27383598 0.85581947 0.16520831
0.43216977 0.62884897 0.29324374 0.38860853 0.60446339 0.25705416
0.11566719 0.13953588 0.41769868 0.11265988 0.81819665 0.34681174
0.95995997 0.13905022]]
shape: (3, 50)
*** 重み2 ***
[[0.48160627 0.3692798 ]
[0.55357291 0.8743988 ]
[0.04393893 0.02855027]
[0.20539303 0.21630873]
[0.0143238 0.54802517]
[0.64373521 0.31045662]
[0.00768712 0.0027004 ]
[0.7545147 0.0950028 ]
[0.09843236 0.78476708]
[0.53859511 0.2284458 ]
[0.90385607 0.27239534]
[0.37694794 0.26328192]
[0.56488461 0.02454277]
[0.81641623 0.82809803]
[0.33204306 0.69160372]
[0.47333626 0.28382845]
[0.77268564 0.5235468 ]
[0.8860852 0.78932501]
[0.95340017 0.28420621]
[0.08591214 0.61246902]
[0.26130375 0.49896811]
[0.30948354 0.26279544]
[0.95176038 0.43099505]
[0.40870044 0.58556273]
[0.03034162 0.35076128]
[0 96442555 0 93822951]
# 2値分類
# 2-3-1ネットワーク
# !試してみよう_ノードの構成を 5-10-20-1 に変更してみよう
# ウェイトとバイアスを設定
- 21. # ネートワークを作成
def init_network():
print("##### ネットワークの初期化 #####")
network = {}
network['W1'] = np.array([
[0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
[0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
[0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
[0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1],
[0.1, 0.3, 0.5,0.1, 0.3, 0.5,0.1, 0.3, 0.5, 0.1]
])
network['W2'] = np.random.rand(10, 20)
network['W3'] = np.random.rand(20, 1)
network['b1'] = np.random.rand(10)
network['b2'] =np.random.rand(20)
network['b3'] =np.random.rand(1)
return network
# プロセスを作成
def forward(network, x):
print("##### 順伝播開始 #####")
W1, W2, W3 = network['W1'], network['W2'],network['W3']
b1, b2, b3 = network['b1'], network['b2'],network['b3']
# 隠れ層の総入力
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
z3 = functions.sigmoid(u3)
y = z3
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.,2.,4.,5.])
# 目標出力
d = np.array([1])
network = init_network()
- 22. 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 ***
[2.27767909 4.39940612 7.61368775 2.24836087 4.55615519 7.52848015
1.57066258 4.96675852 7.24084233 2.09570312]
shape: (10,)
*** 中間層出力1 ***
[2.27767909 4.39940612 7.61368775 2.24836087 4.55615519 7.52848015
1.57066258 4.96675852 7.24084233 2.09570312]
shape: (10,)
*** 総入力2 ***
[21.4588313 27.13780692 24.27422374 19.95123609 21.1702713 18.11509962
18.70826255 20.29017828 29.71014221 25.24938743 22.22680624 22.89437657
15.50102261 26.04897169 20.63315801 24.01966075 31.96015393 27.51417822
25.54170658 22.59841354]
shape: (20,)
*** 出力1 ***
[1.]
shape: (1,)
出力合計: 1.0
##### 結果表示 #####
*** 中間層出力 ***
[2.27767909 4.39940612 7.61368775 2.24836087 4.55615519 7.52848015
1.57066258 4.96675852 7.24084233 2.09570312]
shape: (10,)
*** 出力 ***
[1.]
shape: (1,)
*** 訓練データ ***
[1]
shape: (1,)
*** 交差エントロピー誤差 ***
-9.999999505838704e-08
shape: ()
- 24. 逆伝播
from google.colab import drive
drive.mount('/content/drive')
Mounted at /content/drive
import sys
sys.path.append('/content/drive/My Drive/DNN_code_colab_lesson_1_2')
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']
- 25. 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)
- 26. # 誤差
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]]
出力合計: 1.0
##### 誤差逆伝播開始 #####
*** 偏微分_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]]
- 27. *** 偏微分_重み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]]
- 28. 確率的勾配降下法
編集するにはダブルクリックするか Enter キーを押してください
from google.colab import drive
drive.mount('/content/drive')
Mounted at /content/drive
import sys
sys.path.append('/content/drive/My Drive/DNN_code_colab_lesson_1_2')
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("##### 順伝播開始 #####")
- 29. 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
# サンプルデータを作成
- 30. 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()