#Level5.深層学習 DAY1
##5-1.ニューラルネットワークの全体像
●クライアントの人からすれば、インプットで何を使って、アウトプットで何が出るかしか気にしない。
エンジニアは特に中間層を意識する必要がある。
☆確認テスト☆
5-1-1 ディープラーニングは、結局何をやろうとしているか2行以内で述べよ。
また、次の中のどの値の最適化が最終目的か。
①入力値[X] ②出力値[Y] ③重み[W] ④バイアス[b]
⑤総入力[u] ⑥中間層入力[z] ⑦学習率[ρ]
(確認テストって前に勉強してからその確認なのじゃないだろうかと思いつつ・・・)
【自分の回答】
予測値と正解の値からパラメータを更新し、人間の頭脳のように学習させること。
最適化する値は、③重み[W]と④バイアス[b]
【解答】誤差を最小化するパラメータを発見すること。
③重み[W]、④バイアス[b]
☆確認テスト☆
5-1-2 次のネットワークを紙にかけ。
入力層:2ノード1層
中間層:3ノード2層
出力層:1ノード1層
##5-2.ニューラルネットワーク(NN)でできること
【回帰】
●結果予測 ・・・ 売上予想、株価予想
●ランキング・・・ 競馬順位予想、人気順位予想
【分類】
●猫写真の判別
●手書き文字認識
●花の種類分類
※Amazonの売上データなどは、入力にして売上予想をしているのだろうな。
ちょっとした回帰予測はやってみたい。
また、顔の判別はスタンダードであるが、やってみたい。
ラズベリーパイと組み合わせて、動作する機能を作りたい。
##5-3.回帰
●連続する実数値を取る関数の近似
・線形回帰
・回帰木
・ランダムフォレスト
・ニューラルネットワーク(NN)
##5-4.分類
●性別(男女)や動物の種類など離散的な結果を予想するための分析
・ベイズ分類
・ロジスティック回帰
・決定木
・ランダムフォレスト
・ニューラルネットワーク(NN)
※複雑な入り組んだ情報から予想するための分析。
##5-5.深層学習の実用例
●自動売買(トレード)
良いモデルがあってもあまりオープンにならない。
情報はあるので、自分なりのアルゴリズムに収束させる。
●チャットボット
コールセンターの自動化など、現在のニーズに合うもの。
FAQシステムも人件費の削減になる。
●翻訳
Google翻訳等がある。
精度を上げるのに重要度を用いたり、アテンションメカニズム等がある。
●音声解釈
AmazonEchoやGoogleHomeのようなスピーカー。
ドラゴンスピーチ(音声解釈の分野で発達している)
AIを使う部分と使わない部分がある。
自分でプロダクトを作ろうとした時に、精度を上げるために必要な音声のデータが必要。
莫大なデータを集めることになるが、それに見合った精度が出せるか分からない。
制度を上げるのに音声の圧縮など、試行錯誤による努力も必要。
●囲碁・将棋AI
AlphaGo(囲碁)、Ponanza(将棋)など
⇒ディープラーニングの技術が密接に繋がっている。
強化学習とCNNのハイブリッドなど
※毎日、新聞に載るようなことが多く、
翌日から記事はちゃんと読もうと思った。(笑)
##5-6.Section1「入力層~中間層」
☆確認テスト☆
5-6-1 この図式に動物分類の実例を入れてみよう。
☆確認テスト☆
5-6-2 この数式をPython(numpyのライブラリ)で書け。
$u=w_1x_1+w_2x_2+w_3x_3+w_4x_4+b =Wx+b$
【自分の回答】$u = np.dot(x,W) + b$
【解答】$u_1 = np.dot(x, W_1) + b_1$
##5-7.ソースコード解説
☆確認テスト☆
5-7-1 1-1のファイルから中間層の出力を定義しているソースを抜き出せ。
(= 1_1_forward_propagation)
【自分の回答】画像のとおり。
【解答】z = functions.relu(u)
##5-8.Jupyter演習
☆確認テスト☆
5-8-1 "1_1_forward_propagation.ipynb"の順伝播(単層・単ユニット)で、
重み・バイアスの“試してみよう~”を使って動作確認をする。
※処理を動かすのに特定のディレクトリに移動しておくとよい。(備忘録)
⇒何かと好きなランダム数値を入れてみることにしました。
重みも、バイアスについても。
##5-9.Section2「活性化関数」
●活性化関数とは
ニューラルネットワークにおいて、次の層への出力の大きさを決める非線形の関数。
入力値の値によって、次の層への信号のON/OFFや強弱を定める働きをもつ。
⇒電気総量の強弱をつけて、より人間に近い判断ができるようにする。
☆確認テスト☆
5-9-1 線形と非線形の違いを図にかいて簡易に説明せよ。
●中間層用の活性化関数
・ReLU関数
・シグモイド関数(ロジスティック関数)
・ステップ関数(Deeplearningの元になった関数)
●出力層用の活性化関数
・ソフトマックス関数
・恒等写像
・シグモイド関数(ロジスティック関数)
●ステップ関数
以下の課題があった。
・0-1間の中間を表現できない。(ONとOFFしか表現できない)
・線形分離可能なものしか学習できなかった。
【数式】
$f(x) = 1(x≧0) or 0(x<0)$
●シグモイド関数(ロジスティック関数)
・0~1の間を緩やかに変化する関数。
・信号の強弱を伝えられるようになり、
予想ニューラルネットワーク普及のきっかけとなった。
ただし、以下の課題がある。
・大きな値では出力の変化が微小なため、勾配消失問題を引き起こすこと。
【数式】
$f(u) = \frac{1}{1+e^{-u}}$
●ReLU関数
・現在、最も使われている活性化関数。
・勾配消失問題の回避と、
スパース化に貢献することで良い成果をもたらしている。
・ReLUに固執せず、構成によってさまざまな関数を利用すると良い。
シグモイド関数の方が良い成果が出ることもある。
【数式】
$f(x) = x(x>0) or 0(x≦0)$
●全結合NN 単層・複数ノード
・中間層が複数ノードになるもの。
・重み・バイアスが増えるため、計算量も増えて負荷がかかる。
・単層・単ノードを拡張したもの。
☆確認テスト☆
配布されたソースコードより該当する箇所を抜き出せ。
$z = f(u)$
【自分の回答】
$z = functions.sigmoid(u)$!
【解答】
$z = functions.sigmoid(u)$
配布ソースを利用して、各活性化関数の動作を確認。
シグモイド関数も、ステップ関数もちゃんと動きました。
##5-10.Section3「出力層」
●出力層の役割
・関数により人間が知得できる形に変換する。
・クライアントに見せる際に重要になる。
●誤差関数
・事前に用意するデータとして、
「入力データ」「訓練データ(正解値)」が必要。
・各分類の結果として出力される値「〇〇の確率 ××%」等。
・ある予測が100%となった場合は、少し疑うことが必要。
・算出した値と訓練データの誤差を関数を使って定量的に取っていく。
・分類では「二乗誤差」は使わない。
☆確認テスト☆
5-10-1 なぜ、引き算でなく二乗するか述べよ
【自分の回答】
誤差が±となるため、絶対値を取りたいが、
計算が難しくなるため二乗して誤差を取るようにしている。
【解答】
値を正にするため。
5-10-2 下式の1/2はどういう意味を持つか述べよ
【自分の回答】
誤差の二乗した合計を微分する際に簡単にできる。
【解答】
微分を簡単にするため。
●出力層の活性化関数
・出力層と中間層の違い
中間層:しきい値の前後で信号の強弱を調整
出力層:信号の大きさ(比率)はそのままに変換
・確率出力
分類問題の場合、出力層の出力は0~1の範囲に限定し、
総和を1とする必要がある。
⇒出力層と中間層で利用される活性化関数が異なる。
【回帰】
活性化関数・・・恒等写像
誤差関数 ・・・二乗誤差
【二値分類】
活性化関数・・・シグモイド関数
誤差関数 ・・・交差エントロピー
【多クラス分類】
活性化関数・・・ソフトマックス関数
誤差関数 ・・・交差エントロピー
【シグモイド関数(数式)】
$f(u) = \frac{1}{1+e^{-u}}$
☆確認テスト☆
【ソフトマックス関数(数式)】
f(i,u) = \frac{e^{u_{i}}} {\sum^k_{k=1} e^{u_{k}}}
①~③の数式に該当するソースコードを示し、
一行ずつ処理の説明をせよ。
【自分の回答】
①y.T ・・・ ソフトマックスで演算した結果
②np.exp(x) ・・・ xをシグモイド関数で演算する
③np.sum(np.exp(x),axis=0) ・・・ xをシグモイド関数で演算した値の合計。
【解答】
前提として、多次元のものは使えない。
xの転置した値の中で、max値をどんどん減算していく。
<ちょっと勉強>
出典:NumPyでのaxis指定(https://qiita.com/shuetsu@github/items/2bf8bba233c5ecc7a0ad)
・数値計算ライブラリNumPyを利用した、行列に対してaxis(軸)を指定して集計を行う
●平均二乗誤差
【数式】
E_n(W) = \frac{1}{2} \sum^I_{i=1}(y_n - d_n)^2
def mean_squared_error(d, y):
return np.mean(np.square(d - y)) / 2
☆確認テスト☆
【交差エントロピー(数式)】
E_n(W) = -\sum^I_{i=1} d_i logy_i
①~②の数式に該当するソースコードを示し、
一行ずつ処理の説明をせよ。
【自分の回答】
①return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size
②return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size
⇒log値で0になってしまうことがあるため、
分子が0にならないように微小な値1e-7を足している。
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
##5-11.Section4「勾配降下法」
●勾配降下法
・深層学習の目的
学習と通して誤差を最小にするネットワークを作成すること。
⇒誤差$E(w)$を最小化するパラメータ$w$を発見すること。
⇒勾配降下法を利用してパラメータを最適化
【勾配降下法】
w^{(t+1)}=w^{(t)} - ε∇E\\
∇E = \frac{\partial E}{\partial w} = \biggl \{\frac{\partial E}{\partial w_1} ・・・ \frac{\partial E}{\partial w_M} \biggr \}
☆確認テスト☆
該当するソースコードを探してみよう。
【自分の回答】
パラメータ ・・・ network[key] -= learning_rate * grad[key]
$∇E$ ・・・ grad = backward(x, d, z1, y)
【解答】
パラメータ ・・・ network[key] -= learning_rate * grad[key]
$∇E$ ・・・ grad = backward(x, d, z1, y)
※$∇E$は、誤差をパラメータで微分したもの。
【$ε$:学習率】
・学習率が大きい:上手く収束できず発散してしまう。
・学習率が小さい:発散することはないが、収束までの時間がかかる。
・大域的極小解・・・全体で見て極小になる点
●勾配降下法のアルゴリズム
学習率の決定、収束性向上のためのアルゴリズムについて、
複数の論文が公開され、よく利用されている。
・Momentum
・AdaGrad
・Adadelta
・Adam
●確率的勾配降下法(SGD)
・確率的勾配降下法のメリット
・データが冗長な場合の計算コストの軽減
・望まない局所極小解に収束するリスクの軽減
・オンライン学習ができる
【確率的勾配降下法】
w^{(t+1)}=w^{(t)} - ε∇E_n
【勾配降下法】
w^{(t+1)}=w^{(t)} - ε∇E
☆確認テスト☆
オンライン学習とは何か。
2行でまとめよ。
【自分の回答】
リアルタイムで予測処理をしている最中でも、
誤差から重みやバイアスの更新ができる。
【解答】
例としてFacebookなどで、
常に新しく登録してきたユーザの情報だけを使って学習できる。
●ミニバッチ勾配降下法
・ランダムに分割したデータの集合(ミニバッチ)$D_t$
に属するサンプルの平均誤差
・確率的勾配降下法のメリットを損なわず、
計算機の計算資源を有効利用できる。
⇒CPUを利用したスレッド並列化やGPUを利用したSIMD並列化
【ミニバッチ勾配降下法】
w^{(t+1)}=w^{(t)} - ε∇E_t\\
E_t = \frac{1}{N_t}\sum_{n \in{D_t}}E_n\\
N_t = |D_t|
【確率的勾配降下法】
w^{(t+1)}=w^{(t)} - ε∇E_n
☆確認テスト☆
【ミニバッチ勾配降下法】 w^{(t+1)}=w^{(t)} - ε∇E_t
この数式の意味を図に書いて説明せよ。
【自分の回答】
ランダムに分割したデータの集合(ミニバッチ)$D_t$とあったので、
適当なサンプルをグループ化してそれぞれに計算して、
最終的に全体の誤差を求める。(図示はできなかった・・・。)
●誤差勾配の計算
どう計算するか。
∇E = \frac{\partial E}{\partial w} = \biggl \{\frac{\partial E}{\partial w_1} ・・・ \frac{\partial E}{\partial w_M} \biggr \}
【数値微分】
プログラムで微小な数値を生成し、疑似的に微分を計算する一般的な手法。
\frac{\partial E}{\partial w_m} \approx \frac{E(w_m + h)- E(w_m - h)}{2h}
しかし、大きなデメリットがある。
・各パラメータ$w_m$それぞれについて$E(w_m + h)$や$E(w_m-h)$を計算するため、
順伝播の計算を繰り返し行う必要があり負荷が大きくなってしまう。
⇒誤差逆伝播法を利用する
●ディープラーニングの開発環境
・ローカル : CPU、GPU
・クラウド : AWS、GCP
※サーバの環境のバージョンの違いで使用できないこともあるので、
組み合わせについては注意が必要である。
##5-12.Section5「誤差逆伝播法」
●誤差勾配の計算
どう計算するか。
∇E = \frac{\partial E}{\partial w} = \biggl \{\frac{\partial E}{\partial w_1} ・・・ \frac{\partial E}{\partial w_M} \biggr \}
【誤差逆伝播法】
算出された誤差を、出力層側から順に微分し、前の層、前の層へと伝播。
最小限の計算で各パラメータでの微分値を解析的に計算する手法。
計算結果(=誤差)から微分を逆算することで、必要な再帰的計算を避けて、
微分を算出できる。
⇒連鎖律を利用する。
☆確認テスト☆
誤差逆伝播法では、不要な再帰的処理を避ける事が出来る。
既に行った計算結果を保持しているソースコードを抽出せよ。
【自分の回答】
# 誤差逆伝播
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
【解答】
同じ・・・なのかな?
●誤差逆伝播法
\begin{align}
&E(y) = \frac{1}{2}\sum^J_{j=1}(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^{(2)}_{ji}}=\frac{\partial E}{\partial y}\frac{\partial y}{\partial u}\frac{\partial u}{\partial w^{(2)}_{ji}}\\\\
&\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\\
\end{align}
\frac{\partial u(w)}{\partial w_{ji}} = \frac{\partial}{\partial w_{ji}}(w^{(l)}z^{(l-1)}+b^{(l)})=\frac{\partial}{\partial w_{ji}} \left(
\begin{bmatrix} w_{11}z_1 + ・・・ + w_{1i}z_i + ・・・ w_{1I}z_I \\
\vdots\\
w_{j1}z_1 + ・・・ + w_{ji}z_i + ・・・ w_{jI}z_I\\
\vdots\\
w_{J1}z_1 + ・・・ + w_{Ji}z_i + ・・・ w_{JI}z_I \end{bmatrix}
+\begin{bmatrix} b_1\\
\vdots\\
b_j\\
\vdots\\
b_J \end{bmatrix}
=\begin{bmatrix} 0\\
\vdots\\
z_i\\
\vdots\\
0 \end{bmatrix}
\right)
##5-13.Jupyterで解説(1_3_stochastic_gradient_descent)
●ソースコードを使用して演習してみる。
①活性化関数をReLU関数に設定する。
☆確認テスト☆
2つの空欄に該当するソースコードを探せ
\frac{\partial E}{\partial y}
⇒delta2 = functions.d_mean_squared_error(d, y)
\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^{(2)}_{ji}}
⇒?
【自分の回答】
理解が少し足りない。
普通に動画を見ているだけだと難しい。
【解答】
・恒等写像のため、y=uである。
$\frac{\partial E}{\partial y}\frac{\partial y}{\partial u} = \frac{\partial E}{\partial y}\frac{\partial u}{\partial u}$
そのため、delta2 = functions.d_mean_squared_error(d, y)
・内積値を取ってくる。
delta2に渡した値と、中間層の活性化関数を微分したものを転置したものの内積値。
grad ['W2'] = np.dot(z1.T, delta2)
##5-14.論文解説
実装するため、設計に必要な知識を論文から得る。
早めに実験結果のグラフなどを確認し、視覚的に理解する。