1. 入力層~中間層
入力: $x_i$
重み: $w_i$
バイアス: $b$
総入力: $u = w_1x_1 + w_2x_2 + ... w_nx_n + b = Wx + b$
活性化関数: $f$
2. 活性化関数
活性化関数: $ f^{(l)}(u^{(l)}) = [f^{(l)}(u_1^{(l)}...u_j^{(l)})]$
中間層で用いられる活性化関数
ステップ関数
def step_function(x):
if x > 0:
return 1
else:
return 0
0~1の間を表現できず、線形分離可能なものしか学習しなかった
シグモイド関数
def sigmoid(x):
return 1/1(+np.exp(-x))
ステップ関数では表現できない0~1の値を表すことができ、NN普及のひっかけとなった
大きな値では出力の変化が微弱なため、勾配消失問題を引き起こすことがあった
RELU関数
def relu(x):
return np.maximum(0,x)
昨今最も使われている活性化関数
勾配消失問題の回避とスパース化に貢献することで良い結果をもたらしてくれる
3. 出力層
誤差関数
平均二乗誤差
$En(w) = \frac{1}{2}\sum_{j=1}^l(y_j-d_j)^2 = \frac{1}{2}||(y-d)||^2$
# 平均二乗誤差
def mean_squared_error(d, y):
return np.mean(np.square(d - y)) / 2
交差エントロピー
$ En(w) = \ \sum_{i=1}^l d_i\log y_i$
# クロスエントロピー
def cross_entropy_error(d, y):
if y.ndim == 1:
d = d.reshape(1, d.size)
y = y.reshape(1, y.size)
# 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
if d.size == y.size:
d = d.argmax(axis=1)
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size
活性化関数
出力層と中間層との違い
-
値の強弱
- 中間層:閾値の前後で信号の強弱を調整
- 出力層: 信号の大きさ(比率)はそのままに変換
-
確率出力
- 分類問題の場合は出力層の出力は0~1の範囲に限定し、総和を1にする
ソフトマックス関数
使い分け
# ソフトマックス関数
def softmax(x):
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0)
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T
x = x - np.max(x) # オーバーフロー対策
return np.exp(x) / np.sum(np.exp(x))
4. 勾配降下法
勾配降下法
$w^{(t+1)} = w^{(t)} - \epsilon \nabla E$
$\nabla E=\frac{\partial E}{\partial w} = [ \frac{ \partial E}{ \partial w_1}...\frac{ \partial E}{ \partial w_M}]$
学習率
学習が小さい場合発散することは無いが、小さすぎると収束するまでに時間がかかる
以下のようなアルゴリズムがある
- Momentum
- AdaGrda
- Adadelta
- Adam ←よく利用される
確率的勾配降下法
ランダムに抽出したサンプルの誤差を求める
$w^{(t+1)} = w^{(t)} - \epsilon \nabla E_n$
メリット
- データが冗長な場合の計算コストの削減
- 望まない局所極小解に収束するリスク削減
- オンライン学習ができる
ミニバッチ勾配降下法
オンライン学習の考えを取り入れ、分割してバッチ学習を行う
$w^{(t+1)} = w^{(t)} - \epsilon \nabla E_n$
$E_t = \frac{1}{N_t} \sum_{n \in D_t}^{} E_n$
$N_t = |D_t|$
ランダムに分割したデータの集合(ミニバッチ) Dtに属するサンプルの平均誤差を求める
メリット
- 確率的勾配降下法のメリットを損なわず、計算機の計算資源を有効活用できる
- 並列での学習が可能
誤差勾配の計算
どう計算する?
$ \nabla E = \frac{\partial E}{\partial w} = [ \frac{\partial E}{\partial w_1} ... \frac{\partial E}{\partial w_M}]$
数値微分
プログラムで微小な数値を生成し、疑似的に微分を計算する一般的な手法
$\frac{\partial E }{\partial w_m} \approx \frac{E(w_m+h)-E(w_m -h)}{2h}$
5. 誤差逆伝播法
誤差逆伝播法
算出された誤差を、出力層側から順に微分し、前の層前の層へと伝播。最小限の計算で各パラメータの微分値を解析的に計算する手法
誤差関数: $ E(y) = \frac{1}{2} \sum_{j=1}^l(y_j-d_j)^2 = \frac{1}{2}||y-d||^2$
出力層の活性化関数: $y=u^{(t)}$
総入力の計算: $u^{(t)} = w^{(l)}z^{(l-1)}+b^{(l)}$
$\frac{\partial E}{\partial w_{ji}^{(2)}} = \frac{\partial E}{\partial y} \frac{\partial y}{\partial u} \frac{\partial u}{\partial w_{ji}^{(2)}} = (y_j-d_j)z_j$
$\frac{\partial E(y)}{\partial y} = \frac{\partial}{\partial y} \frac{1}{2} || y -d ||^2 = y-d $
$ \frac{\partial y(u)}{\partial u} = \frac{\partial u}{\partial u} = 1$
# 誤差逆伝播
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
確認テスト
確認テスト1-1
Q. ディープラーニングはなにをしようとしているか。
A. プログラムの代わりにニューラルネットワークを利用し、入力値から目的値を求めるモデルを作成する
補足: 重み[w]やバイアス[b]を求める
確認テスト1-2
Q. 次のネットワークを紙にかけ
入力層: 2ノード1層
中間層: 3ノード2層
出力層: 1ノード1層
A.
確認テスト1-3
Q. この図式に動物分類の実例を入れてみよう
A.
x1: 体の大きさ
x2: 体の長さ
x3: 耳の大きさ
x4:しっぽの大きさ
確認テスト1-4
Q. この数式をPythonで書け
$ u = w_1x_1+w_2x_2+w_3x_3 = b$
A. u = np.dot(x, W) + b
確認テスト1-5
Q.1-1のファイルから中間層の出力を定義しているソースを抜き出せ
# 2層の総入力
u2 = np.dot(z1, W2) + b2
# 2層の総出力
z2 = functions.relu(u2)
補足: 中間層が今回は1つ
確認テスト2-1
Q.線形と非線形の違いを図にかいて簡易に説明せよ
左図 線形: 直線で表せることができるもの
右図 非線形: 表せないもの
[補足]
線形な関数は以下を満たす
- 加法性: f(x+y) = f(x) + f(y)
- 斉次性: f(kx) = kf(x)
確認テスト2-2
Q.
$z = f(u) ... (1.5)$
配布されたソースコードより該当する箇所を抜き出せ
# 1層の総出力
z1 = functions.relu(u1)
[補足]
from common import functions
という形でimportされているので関数自体は別ファイルに定義されている
def relu(x):
return np.maximum(0, x)
確認テスト3-1
$ En(w) = \frac{1}{2}\sum_{j=1}^l(y_j-d_j)^2 = \frac{1}{2}||(y-d)||^2$
Q.なぜ引き算ではなく二乗するのか
A.必ず正の値になるように調整するため
Q.1/2はどういう意味をもつのか
A.誤差逆伝搬の計算で微分を行う際に計算が簡単になる
補足:1/2に本質的な意味はない
確認テスト3-2
ソフトマックス関数の①~③に該当するソースコードを示し、説明せよ
def softmax(x):
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0)
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T
x = x - np.max(x) # オーバーフロー対策
return np.exp(x)② / np.sum(np.exp(x)③) ・・・①
9行目 return の箇所が実際の数式に該当する箇所である
補足: 3行目からの分岐はミニバッチで利用する処理
その他の処理はプログラムを安定させるための記述
確認テスト3-3
Q. ①~②の数式に該当するソースコードを示し、一行ずつ処理の説明をせよ。
def cross_entropy_error(d, y):
if y.ndim == 1:
d = d.reshape(1, d.size)
y = y.reshape(1, y.size)
# 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
if d.size == y.size:
d = d.argmax(axis=1)
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7))(②) / batch_size ・・・①
A. 11行目 returnの文が該当
補足: 1e-7は対数関数を∞に飛ばした時、0になってしまうことを防ぐために利用している
確認テスト4-1
Q.オンライン学習とは何か
A.データをリアルタイムで読み取り、パラメータを更新する方法
補足: バッチ学習は一度にすべての学習データを使ってパラメータ更新を行う
確認テスト4-2
Q.この数式の意味を図に書いて説明せよ
$ w^ {(t+1)} = w^ {(t)} - \epsilon \nabla E_n$
A.
〇 -> 〇 -> 〇
t -> t+1 -> t+2
重みが $-\epsilon \nabla En $ずつ加えられていくイメージ
確認テスト5-1
Q.誤差逆伝播法では不要な再帰的処理を割けることができる。既に行った計算結果を保持しているソースコードを抽出せよ
A.
# 出力層でのデルタ
delta2 = functions.d_mean_squared_error(d, y)