---
title: 【ゼロから作るDeep Learning】4.5~4.6
tags: 
author: [京都大学人工知能研究会KaiRA](https://convert.docswell.com/user/kyoto-kaira)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/GE8NW5857D.jpg?width=480
description: 【ゼロから作るDeep Learning】4.5~4.6 by 京都大学人工知能研究会KaiRA
published: June 03, 24
canonical: https://convert.docswell.com/s/kyoto-kaira/ZYWP7V-2024-06-03-231156
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/GE8NW5857D.jpg)

2024年度前期輪読会#5
４章ニューラルネットワークの学習
システムエンジニア（Web系）義積
京都大学理学部物理学科（凝縮系理論専攻）卒
0


# Page. 2

![Page Image](https://bcdn.docswell.com/page/LELPNYR37R.jpg)

4.5 学習アルゴリズムの実装
・タスク：数字（０〜９）の分類問題 （データセット：MNIST）
・モデル：２層ニューラルネットワーク
・損失関数：交差エントロピー
・手法：勾配降下法
1


# Page. 3

![Page Image](https://bcdn.docswell.com/page/4JM4XNRM7W.jpg)

4.5 学習アルゴリズムの実装
２層ニューラルネットワーク
+
x
b1
=
→
a1
z1
w1
+
z1
b2
=
a2
→
y
w2
sigmoid
x・w1 + b1 = a1 → z1
softmax
z1・w2 + b2 = a2 → y
正規化
2


# Page. 4

![Page Image](https://bcdn.docswell.com/page/PJRWNDRL79.jpg)

4.5 学習アルゴリズムの実装
概要
準備
{ xn, tn }
60000 抽出
→ 100 = N
{w, b} 初期値, eta
i = 1, …, 10000
学習 = 最適な w, b を得ること
損失関数（尤度）
勾配（尤度を最大）
パラメータの更新
（ i : 隠れ層 ）
精度
損失関数の減少
（学習）
学習した結果の
パラメータ
{ W, b }
汎化能力の測定
3


# Page. 5

![Page Image](https://bcdn.docswell.com/page/PEXPN1Y67X.jpg)

4.5 学習アルゴリズムの実装
準備（インプット、初期条件、計算の制限、など）
準備
{ xn, tn }
60000 抽出
→ 100 = N
{w, b} 初期値, eta
i = 1, …, 10000
学習
損失関数
勾配
パラメータの更新
（ i : 隠れ層 ）
精度
（学習）
学習した結果の
パラメータ
{ W, b }
4


# Page. 6

![Page Image](https://bcdn.docswell.com/page/3EKDN23GJD.jpg)

4.5 学習アルゴリズムの実装
準備（インプット、初期条件、計算の制限、など）
準備
train_nueralnet.py
{ xn, tn }
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
60000 抽出
→100=N
{w, b} 初期値, eta
network = TwoLayerNet(
input_size=784, hidden_size=50, output_size=10, weight_init_std=0.01
)
iters_num = 10000 # 繰り返しの回数を適宜設定する
【初期値】ref. 6.2
wmn: ガウス分布
train_size = x_train.shape[0]
= 60,000
batch_size = 100
learning_rate = 0.1
bn : 0
【ハイパーパラメータ】ref. 6.5
class TwoLayerNet:
・学習率
def __init__(self, input_size, hidden_size, output_size, weight_init_std):
eta = 0.1
・隠れ層ニューロン数
ノード数（１層、２層）:50
【ミニバッチ数】
・訓練データ60,000からランダムにサンプリング→100
・訓練制度測定はステップ数/エポック数%0の時だけ実施
# 重みの初期化
self.params = {}
random.randn（行列サイズ）：標準分布に従うラン
ダムな成分を持つ行列を生成
self.params[&quot;W1&quot;] = weight_init_std * np.random.randn(input_size, hidden_size)
self.params[&quot;b1&quot;] = np.zeros(hidden_size)
self.params[&quot;W2&quot;] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params[&quot;b2&quot;] = np.zeros(output_size)
※エポック数 = 訓練データ数／ミニバッチのサイズ = 60,000／100 = 600
→10000/600〜16回
5


# Page. 7

![Page Image](https://bcdn.docswell.com/page/L73RV4G5J5.jpg)

4.5 学習アルゴリズムの実装
損失関数
準備
{ xn, tn }
60000 抽出
→ 100=N
{w, b} 初期値, eta
i = 1, …, 10000
学習
損失関数
勾配
パラメータの更新
（ i : 隠れ層 ）
精度
（学習）
学習した結果の
パラメータ
{ W, b }
6


# Page. 8

![Page Image](https://bcdn.docswell.com/page/87DY8Q1Y7G.jpg)

4.5 学習アルゴリズムの実装
損失関数
def predict(self, x):
W1, W2 = self.params[&quot;W1&quot;], self.params[&quot;W2&quot;]
損失関数
b1, b2 = self.params[&quot;b1&quot;], self.params[&quot;b2&quot;]
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
y = softmax(a2)
return y
N=100（ミニバッチ）
def cross_entropy_error(y, t):
今はyを各数字の確率のベクトルとして
いるが、解き方によっては直接数字
を格納している場合もあって、たぶんそ
の場合に流用したいから
if y.ndim == 1:
t = t.reshape(1, t.size)
交差エントロピー
def loss(self, x, t):
y = self.predict(x)
1次元配列→2次元配列
y = y.reshape(1, y.size)
今は(100, 10)の形で入っている
# 教師データが one-hot-vectorの場合、正解ラベルのインデックスに変換
if t.size == y.size:
t = t.argmax(axis=1)
return cross_entropy_error(y, t)
おそらくこれも流用を意図
t には、正解の数字を格納する
（元々、正解の数字が格納されている場
合がある（上と同じ））
axis=0：行方向、axis=1：列方向
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7))
batch_size
7


# Page. 9

![Page Image](https://bcdn.docswell.com/page/VJP68LQ2E8.jpg)

4.5 学習アルゴリズムの実装
損失関数
定義式通りに計算
テキスト
sum2 = 0
def cross_entropy_error(y, t):
for k in range(0, batch_size - 1):
sum2 += -np.dot(np.log(y[k] + 1e-7), t[k]) / batch_size
１人で開発する場合、汎用性もたせるのは分かるけど、
if y.ndim == 1:
複数人で開発するシステムなんかの場合、本気で保守し
t = t.reshape(1, t.size) ずらい. 分けた方が不具合起こしにくい
y = y.reshape(1, y.size)
# 教師データが one-hot-vectorの場合、正解ラベルのインデックスに変換
if t.size == y.size:
t = t.argmax(axis=1)
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7))
batch_size
8


# Page. 10

![Page Image](https://bcdn.docswell.com/page/2EV3NQ5X7Q.jpg)

4.5 学習アルゴリズムの実装
勾配
準備
{ xn, tn }
60000 抽出
→ 100 = N
{w, b} 初期値, eta
i = 1, …, 10000
学習
N=100回 * 10000
〜40000回 * 10000
損失関数
勾配
パラメータの更新
（ i : 隠れ層 ）
最も計算負荷かかる工程
※バッチ単位で処理できない
精度
（学習）
学習した結果の
パラメータ
{ W, b }
9


# Page. 11

![Page Image](https://bcdn.docswell.com/page/57G3KW6RJL.jpg)

4.5 学習アルゴリズムの実装
勾配
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
勾配
grad = np.zeros_like(x)
it = np.nditer(x, flags=[&quot;multi_index&quot;], op_flags=[&quot;readwrite&quot;])
配列xの全要素に対して演算
while not it.finished:
idx = it.multi_index
初期値が、
tmp_val = x[idx]
input_size=784, hidden_size=50
x[idx] = tmp_val + h
fxh1 = f(x) # f(x+h)
だったので、
１ステップごとに、
W1: 784 * 50 = 39200回
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
grad[idx] = (fxh1 - fxh2) / (2 * h)
x[idx] = tmp_val # 値を元に戻す
b1: 50
W2: 50 * 10 = 500
b2: 10
合計 39,760回ループする
これが多いのかよく分からないが、
実際計算してみると…めっちゃ重い！
it.iternext()
return grad
10


# Page. 12

![Page Image](https://bcdn.docswell.com/page/4EQ5N34YJP.jpg)

4.5 学習アルゴリズムの実装
勾配
勾配法
def gradient(self, x, t):
W1, W2 = self.params[&quot;W1&quot;], self.params[&quot;W2&quot;]
b1, b2 = self.params[&quot;b1&quot;], self.params[&quot;b2&quot;]
・numerical_gradient()
grads = {}
（黎明期の方法？）
batch_num = x.shape[0]
⇨以下、
・gradient()
逆伝播誤差法（計算グラフ）
を用いる
# forward
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
y = softmax(a2)
# backward
dy = (y - t) / batch_num
grads[&quot;W2&quot;] = np.dot(z1.T, dy)
grads[&quot;b2&quot;] = np.sum(dy, axis=0)
dz1 = np.dot(dy, W2.T)
da1 = sigmoid_grad(a1) * dz1
grads[&quot;W1&quot;] = np.dot(x.T, da1)
grads[&quot;b1&quot;] = np.sum(da1, axis=0)
return grads
11


# Page. 13

![Page Image](https://bcdn.docswell.com/page/KJ49G1QZ71.jpg)

4.5 学習アルゴリズムの実装
パラメータの更新
準備
{ xn, tn }
60000 抽出
→ 100 = N
{w, b} 初期値, eta
i = 1, …, 10000
学習
損失関数
勾配
パラメータの更新
（ i : 隠れ層 ）
精度
（学習）
学習した結果の
パラメータ
{ W, b }
12


# Page. 14

![Page Image](https://bcdn.docswell.com/page/LE1KDGPDJG.jpg)

4.5 学習アルゴリズムの実装
パラメータの更新
# パラメータの更新
パラメータ更新
for key in (&quot;W1&quot;, &quot;b1&quot;, &quot;W2&quot;, &quot;b2&quot;):
a -= b は、a = a - b
network.params[key] -= learning_rate * grad[key]
（ i : 隠れ層 ）
13


# Page. 15

![Page Image](https://bcdn.docswell.com/page/GEWDYK28J2.jpg)

4.5 学習アルゴリズムの実装
学習の精度
準備
{ xn, tn }
60000 抽出
→ 100 = N
{w, b} 初期値, η
i = 1, …, 10000
学習
損失関数
勾配
パラメータの更新
（ i : 隠れ層 ）
精度
（学習）
学習した結果の
パラメータ
{ W, b }
14


# Page. 16

![Page Image](https://bcdn.docswell.com/page/47ZGXZD9E3.jpg)

4.5 学習アルゴリズムの実装
学習の精度
・O(0.1) &lt; O(0.01) &lt; O(1)
・winiの大きさによって、収束性が影響を受ける
・O(1)だと10000回ステップ後も収束しない
・ηと同程度にすればいい？
・勾配法（テキスト）→逆伝播誤差法（左図）によっ
て精度が上昇している
・分布の仕方の影響も大きいらしい（６章）
図： 損失関数の推移
15


# Page. 17

![Page Image](https://bcdn.docswell.com/page/YJ6Y4Z1D7V.jpg)

4.5 学習アルゴリズムの実装
学習した結果のパラメター {w, b}
準備
{ xn, tn }
60000 抽出
→ 100 = N
{w, b} 初期値, eta
i = 1, …, 10000
学習
損失関数
勾配
パラメータの更新
（ i : 隠れ層 ）
精度
（学習）
学習した結果の
パラメータ
{ W, b }
{ 60000回+10000回} * 16 〜 110000回
16


# Page. 18

![Page Image](https://bcdn.docswell.com/page/GJ5GQW48J4.jpg)

4.5 学習アルゴリズムの実装
学習した結果のパラメター {w, b}
汎化能力の測定
学習した結果の
パラメータ
{ W, b }
目的
過学習になっていないか、を調べる
方法
訓練データで得られた{W, B}を用いて、
・訓練データに対する認識精度と
・テストデータに対する精度
def accuracy(self, x, t):
y = self.predict(x)
y = np.argmax(y, axis=1)
t = np.argmax(t, axis=1)
を比較する
・ステップごとに計算すると負荷が大きいので、
エポックごとに測定する
accuracy = np.sum(y == t) / float(x.shape[0])
（10000/600〜16回）
return accuracy
p114 def accuracy(self, x, t):
（誤）y = predict(x) （正）y = self.predict(x)
17


# Page. 19

![Page Image](https://bcdn.docswell.com/page/9E2YPQVVER.jpg)

4.5 学習アルゴリズムの実装
学習した結果のパラメター {w, b}
学習精度の収束が、初期値に依存
していた割に、
データの違いに対して、認識精度が
合いすぎているように思える…
（p.193とかp.194みたいなのを期待し
ていた）
図：訓練データでの認識精度と、テストデータの認識精度
18


# Page. 20

![Page Image](https://bcdn.docswell.com/page/D7YG5W3Q7M.jpg)

4.6 まとめ
まとめ
まとめ１
まとめ２
データセットは、訓練データとテストデータに分ける → 汎化能力を評価
ニューラルネットワークの学習は、損失関数を指標として、この値が小さくな
るように重みパラメータ{W, b}を更新する
まとめ３
その解法の一つに、勾配降下法（数値微分）がある
（が、これは使い物にならない）
まとめ
４
誤差逆伝播法を用いると、高速に勾配を求めることができる
19


