#1.ニューラルネットワークの全体像
[確認テスト]
ディープラーニングは、結局何をやろうとしているか2行以内で述べよ。
また、次の中のどの値の最適化が最終目的か。全て選べ。
選択肢
①入力値[X] ②出力値[Y] ③重み[W] ④バイアス[b] ⑤総入力[u]
⑥中間層入力[z] ⑦学習率[p]
[回答]
明示的なプログラムの代わりに多数の中間層を持つニューラルネットワークを用いて、
入力値から目的とする出力値に変換する数学モデルを構築すること
選択肢:③、④
○詳しく見ていくと、xという値を受け取り、yという値を出力していく。
重要なのは、入力層⇨中間層⇨出力層にかけて、必ず何かしらの入力と出力がある変換機である。
○yの出力ができたら、d(正解ラベル)と比較を行い、誤差を求める。
誤差を元に、パラメータw、bを更新し、より分類できるように学習していく。
[確認テスト]
次のネットワークをかけ。
入力層:2ノード1層
中間層:3ノード2層
出力層:1ノード1層
○連続する実数値をとる関数の近似
【主な手法】
・線形回帰
・回帰木
・ランダムフォレスト
・ニューラルネットワーク(NN)
●分類
■猫写真の判別
■手書き文字認識
■花の種類分類
○性別(男あるいは女)や動物の種類など離散的な結果を予想するための分析
【主な手法】
・ベイズ分類
・ロジスティック回帰
・決定木
・ランダムフォレスト
・ニューラルネットワーク(NN)
●深層学習の実用例
・自動売買(トレード)
・チャットボット
・翻訳
・音声解釈
・囲碁、将棋AI
#2.入力層〜中間層
●x(入力)の値をw(重み)で掛けた値 + b(バイアス)を全て足すことで、uを求めることができる。
○xに掛けられるwはグラフで表すときの傾き度合いを制御する。
そのため、各xの値がどれほど重要なのかがwによって決まる。
○bはグラフで表すときの切片を制御する。
切片を制御することによって、直線の位置をずらすことができる。
[確認テスト1]
上の図式に動物分類の実例を入れる。
[確認テスト2]
上図にある、計算式をpythonでかけ
\begin{eqnarray}
u &=& w_1 x_1 + w_2 x_2 + w_3 x_3 + w_4 x_4 + b \\
&=& \boldsymbol{W} \boldsymbol{x} + b
\end{eqnarray}
u = np.dot(x, W) + b
[確認テスト3]
上図の中間層を定義している、ソースを抜き出せ
# 2層の総入力
u2 = np.dot(z1, W2) + b2
# 2層の総出力
z2 = functions.relu(u2)
○線形な関数:y=axのように直線で表されるような関数
○非線形な関数:直線で表せず、曲線で表されるような関数
●活性化関数は先程の、u=Wx+bで求めた、uの値を入力とする。
Wやxでは線形な関数になるが、活性化関数を通すことによって、非線形な関数となり、
様々なバリエーションを作成できることが、重要である。
f(x) =
\left\{
\begin{array}{ll}
1 & (x \geqq 0) \\
0 & (x < 0 )
\end{array}
\right.
・サンプルコード
def step_function(x):
if x > 0:
return 1
else:
return 0
・グラフ
●シグモイド関数
○0〜1の間に緩やかに変化する関数で、ステップ関数ではON/OFFしかない状態に対し、
信号の強弱をつけられるようになり、予想ニューラルネットワークの普及のきっかけとなった。
■課題:大きな値では出力の変化が微小なため、勾配消失問題を引き起こすことがあった。
・数式
f(u) = \frac{1}{1 + e^{-u}}
・サンプルコード
def sigmoid(x):
return 1 / (1 + np.exp(-x)))
・グラフ
●RELU関数
○今最も使われている活性化関数
○勾配消失問題の回避とスパース化に貢献することで、良い成果をもたらしている。
・数式
f(x) =
\left\{
\begin{array}{ll}
x & (x > 0) \\
0 & (x \leqq 0)
\end{array}
\right.
・サンプルコード
def relu(x):
return np.maximum(0,x)
・グラフ
[確認テスト]
配布されたソースコードより、z=f(u)に該当する箇所を抜きだせ
# 1層の総出力
z1 = functions.relu(u1)
# 2層の総出力
z2 = functions.relu(u2)
#3.出力層
E_n(W) = \frac{1}{2} \sum_{j=1}^{J} (y_j - d_j)^2 = \frac{1}{2}
|| y - d||^2
[確認テスト]
・二乗誤差ではなぜ引き算ではなく二乗するかを述べよ
引き算を行なってしまうと、誤差に負の値が出てきてしまう可能性があり、
誤差を求める上で、都合が悪いため
・1/2はどういう意味を持つか述べよ
後に微分を求める際に$ ||y - d||^2 $ の二乗と打ち消しあうため
⇨中間層と出力層では利用される活性化関数が異なってくる。
回帰 | ニ値分類 | 多クラス分類 | |
活性化関数 | 恒等写像 | シグモイド関数 | ソフトマックス関数 |
誤差関数 | 二乗誤差 | 交差エントロピー |
●活性化関数
○シグモイド関数
・数式
f(u) = \frac{1}{1 + exp^{(-u)}}
・サンプルコード
def sigmoid(x):
return 1 / (1 + np.exp(-x))
○ソフトマックス関数
・数式
f(i, u) = \frac{e^{u_i}}{\sum_{k=1}^{K} e^{u_k}}
・サンプルコード
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))
[確認テスト]
ソフトマックス関数のソースコードを配布データから抜き出し、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))
●誤差関数
○二乗誤差
・数式
E_n(W) = \frac{1}{2} \sum_{j=1}^{J} (y_j - d_j)^2 = \frac{1}{2}
|| y - d||^2
・サンプルコード
#平均二乗誤差
def mean_squared_error(d, y):
return np.mean(np.squared(d - y)) / 2
○交差エントロピー
・数式
E_n(W) = - \sum_{i=1}^{I} 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
[確認テスト]
交差エントロピーのソースコードを配布データから抜き出し、1行ずつ説明せよ。
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]
#本質的な計算は以下の文
#1e-7は対数関数で、0の時ー∞に飛ぶため、0に落ちないように掛けてある
#yは0か1が並んでいる
#dはニューラルネットワークが正解と選んだ場所
return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size
#4 勾配降下法
・数式
$$ w^{(t+1)} = w^{(t)} - \varepsilon \nabla E $$
[確認テスト]
上の数式に該当するソースコードを探せ
network[key] -= learning_rate * grad[key]
grad = backward(x, d, z1, y)
●学習率の値によって学習の効率が大きく異なる
○学習率が大きすぎた場合、最小値にいつまでもたどり着かず発散してしまう。
○学習率が小さい場合発散することはないが、小さすぎると収束するまでに時間がかかってしまう。
●勾配降下法の学習率の決定、収束性向上のためのアルゴリズムについては様々な手法がある。
・Momentum
・AdaGrad
・Adadelta
・Adam
●全体を通してみると
入力層から中間層を経て、出力層に値が出力され、
出力値と訓練データの誤差を誤差関数を使用して、学習しパラメータを更新していく
この1連の流れを何回も行い、誤差を小さくしていく。
1連の流れのことをエポックと呼ぶ。
●メリット
○データが冗長な場合の計算コストを軽減
○望まない局所極小解に収束するリスクを軽減
○オンライン学習ができる
オンライン学習とは徐々に集まってくるデータに対し、学習を行うことができる。
反対に、あらかじめ全ての学習データを準備することをバッチ学習という。
[確認テスト]
オンライン学習とは何か2行で説明せよ
オンライン学習とは徐々に集まってくるデータに対し、学習を行うことができる。
反対に、あらかじめ全ての学習データを準備することをバッチ学習という。
●ミニバッチ勾配降下法は、ランダムに分割した、データの集合(ミニバッチ)
$D_t$に属するサンプルの平均誤差を利用し、学習を行う。
●メリット
○確率的勾配降下法のメリットを損なわず、計算機の計算資源を有効利用できる
⇨CPUを利用したスレッド並列化やGPUを利用した、SIMD並列化
・数式
$$ w^{(t+1)} = w^{(t)} - \varepsilon \nabla E $$
$$ E_t = \frac{1}{N_t} \sum_{n \in D_t} En $$
$$ N_t = |D_t| $$
[確認テスト]
・$ w^{(t+1)} = w^{(t)} - \varepsilon \nabla E $ の式の意味を図に書いて説明せよ。
\nabla E = \frac{\partial E}{\partial w} =
\Big[ \frac{\partial E}{\partial w_1} \cdots \frac{\partial E}{\partial w_M}
\Big]
●重みはニューラルネットワークの中で大量に出てくる。
Eの情報をもとに各重みを計算していく必要がある。
その計算方法として微分を使う。
○【数値微分】
プログラムで微小な数値を生成し、擬似的に微分を計算する手法
\frac{\partial E}{\partial w_m} \approx
\frac{E(w_m + h) - E(w_m - h)}{2h}
数値微分である重みの場所(上の式でいうm番目)の重みの間違いがどれくらいか数値微分する場合、
重みをわずかに(h)増やした時と減らした時の誤差関数を計算し、差し引いた後僅かな値(h)の2倍で割る。
■数値微分のデメリット
・各パラメータ $w_m$ それぞれについて $E(w_m + h)$ や $E(w_m - h)$ を計算するために、
順伝播の計算を繰り返し行う必要があり、負荷が大きい
⇨解決策:誤差逆伝播法を利用する
○誤差逆伝播法
算出された誤差を、出力層側から順に微分し、前の層前の層へと伝播。
最小限の計算で、各パラメータでの微分値を解析的に計算する手法。
■計算結果(=誤差)から微分を逆算することで、不要な再帰的計算を避けて微分を算出できる
[確認テスト]
誤差逆伝播法では不要な再帰的処理を避ける事が出来る。
既に行った計算結果を保持しているソースコードを抽出せよ。
# 出力層でのデルタ
delta2 = functions.d_mean_squared_error(d, y)
●誤差勾配の計算式
誤差関数=二乗誤差関数
E(y) = \frac{1}{2} \sum_{j=1}^{J} (y_j - d_j)^2
= \frac{1}{2} || y-d ||^2
出力層の活性化関数=恒等写像
$$ y = u^{(L)} $$
総入力の計算
$$ u^{(l)} = 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)}}
\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
\begin{eqnarray}
\frac{\partial u(w)}{\partial w_{ji}} &=& \frac{\partial}{\partial w_{ji}}
\big( w^{(l)} z^{(l-1)} + b^{(l)} \big) \\
&=& \frac{\partial}{\partial w_{ji}}
\begin{pmatrix}
\begin{bmatrix}
w_{11} z_1 + & \cdots +& w_{1i} z_i + & \cdots w_{1I} z_I \\
& & \vdots \\
w_{j1} z_1 + & \cdots +& w_{ji} z_i + & \cdots w_{jI} z_I \\
& & \vdots \\
w_{J1} z_1 + & \cdots +& w_{Ji} z_i + & \cdots w_{JI} z_I \\
\end{bmatrix}
+
\begin{bmatrix}
b_1 \\
\vdots \\
b_j \\
\vdots \\
b_J
\end{bmatrix}
\end{pmatrix} \\
&=&
\begin{bmatrix}
0 \\
\vdots \\
z_i \\
\vdots \\
0
\end{bmatrix}
\end{eqnarray}
\frac{\partial E}{\partial y} \frac{\partial y}{\partial u}
\frac{\partial u}{\partial w_{ji}^{(2)}} = (y - d) \cdot
\begin{bmatrix}
0 \\
\vdots \\
z_i \\
\vdots \\
0
\end{bmatrix}
= (y_j - d_j) z_i
[確認テスト]
$$ \frac{\partial E}{\partial y} \frac{\partial y}{\partial u} $$
の式をソースコードから抜き出せ、また、
$$ \frac{\partial E}{\partial y} \frac{\partial y}{\partial u}
\frac{\partial u}{\partial w_{ji}^{(2)}} $$
の式もソースコードから抜き出せ。
delta1 = np.dot(delta2, W2.T) * functions.d_sigmoid(z1)
grad['W1'] = np.dot(x.T, delta1)