Deep Learningを少しかじってみたので備忘録として出来損ない解説をしてみる。

本記事はKogakuin Univ Advent Calendar 2017の4日目の記事となります。

申し訳ありません3分遅刻しました。

adventar.org

ゼロから作るDeep Learningを読み終えた記念にTensorflowで機械学習をかじり、簡単な解説を自分の勉強用にやってみることにします。

内容は多くのDeep Learning入門解説サイトよりも質が劣りますのでご了承ください。

また、いまいち分かっていないところが多々あり間違ってるところがありましたらコメント等で御連絡お願い致します。

今回少しかじってみるためにTensorflowの公式サイトにあるMNISTのチュートリアルをやってみることにしました。

MNIST For ML Beginners  |  TensorFlow

こちらのチュートリアルはMNISTを使って、Softmax回帰により手書き数字認識をする機械学習モデルを作るところまでが記載されています。

このチュートリアルで作るモデルの仕組みを数式等を用いながら簡単に見ていきます。

入力データの操作

ニューラルネットワークで扱いやすくするように入力データを少々いじる必要があります。

MNISTのデータは28 x 28ピクセルの画像です。

今回の機械学習モデルはCNNではないのでそのまま平らにして要素数784の実数の行列にし、これを\displaystyle x(784,)とおきます。*1

Softmax関数と誤差関数

編集した入力データ行列\displaystyle x(784,)を与えると入力値に重み行列\displaystyle W (10,784)内積してバイアス行列\displaystyle b(10,)を加算します。

これをSoftmax関数に通したものを\displaystyle yとします。

 \displaystyle
y = softmax(Wx+b)

Softmax関数とは以下の式により与えられる関数です。

この関数により、ある\displaystyle n次元ベクトル\displaystyle zを[0,1]の領域に正規化する関数です。

Softmax関数は以下の式で与えられます。

 \displaystyle
softmax (z_j) = \frac{\mathrm{e}^{z_j}} { {\sum_{k=1}^{K} {\mathrm{e}^{z_k}} }}

yには認識した数字がどの数字であるかの確率が10個入っています。

例えば7を認識した場合、ある程度学習したモデルなら以下のようなベクトルを出力します。

[3.63427134e-05,6.19244078e-09,7.22198165e-05,1.69577205e-03,1.69851546e-06,1.73366570e-05,3.09280317e-08,9.97763395e-01,4.37792260e-05,3.69463174e-04]

7番目の要素が9.97763395e-01と他の数値よりも大きいのが分かります。

\displaystyle yをSoftmax関数の引数として入れ、交差エントロピー誤差関数で教師データ\displaystyle tとの誤差の度合いを計算します。

 \displaystyle
E = -\sum_i t_i \log (y_i)

交差エントロピー誤差は教師データがone-hot表現のときに効力を発揮します。

式の通り交差エントロピー誤差は教師データの該当インデックスが1のときにlogを出力するだけです。

 \displaystyle -\log (x)のグラフは以下の通りで入力値が小さくなるほど出力値は大きくなり、入力値が大きくなるほど出力値は小さくなります。

f:id:abc10946:20171110090414p:plain

このように誤差関数は一般的には、誤差が少ないほど数値が小さくなります。

例えば

y = [3.63427134e-05,6.19244078e-09,7.22198165e-05,1.69577205e-03,1.69851546e-06,1.73366570e-05,3.09280317e-08,9.97763395e-01,4.37792260e-05,3.69463174e-04]

t = [0,0,0,0,0,0,0,1,0,0]とすると7がどれくらいの誤差で認識されているのかを計算します。

 \displaystyle
E = -\sum_i t_i \log (y_i) = 0.002239109936695956

これにより誤差はとても小さいということが分かります。

ちなみに、もしt=[0,0,1,0,0,0,0,0,0,0]で同じ出力値を使った場合を試してみます。

教師データは2が正しい出力であることを示していますが、モデルが出力したデータでは7が一番大きい値になっています。

この場合は出力は間違っていることになるため誤差関数の値も大きくなります。

 \displaystyle
E = -\sum_i t_i \log (y_i) = 18.899936517792028

y_が教師データでyがニューラルネットの出力となり、これらを交差エントロピー誤差関数に通しています。

学習

勾配降下法という手法を用いています。

高校生の頃に微分でやった関数の最小値を求めるの問題と大差ないものです。

しかしDeep Learningで扱う関数の曲線は複雑なため、簡単に関数の最小値を求めることはできません。

Deep Learningでは少しずつ値を変えて損失関数の最小値に近づけるため以下の式で重みを変えます。

Lが損失関数の値でWが重み、 \displaystyle \etaが学習率となります。

 \displaystyle
 W = W - \eta \frac{\partial L}{\partial W}

このとき学習率は大きすぎても小さすぎてもダメです。

大きすぎると最小値を飛ばしてしまったり、小さすぎると最小値にたどり着くまで時間がかかります。

\displaystyle \etaの大きさは多くは0.5くらいにされています。

ちなみに、このとき偏微分を効率よく求めるための誤差逆伝播法という手法もありますが基本的な部分を記載するだけの記事ですので割愛させていただきます。

Deep Learningを学んで次にやること

今回、Tensorflowのチュートリアルで作った機械学習モデルは基本的なものです。

そのため精度は91.82%で、あまり高くありません。

これを99%程度に近づける畳み込みニューラルネットワーク(CNN)という手法があります。

CNNを使うことで画像関係(クラス分類、オブジェクト分類等)に関してはより高い精度が得られます。

とりあえずは、これを自力で実装できるようにして応用もできるようにしたいと思っています。

また、Deep Q Networkというネットワークも試してみたいところです。

Deep Q Networkに関しては以下のような面白い記事や動画があるので見てみることを推奨します。

Google DeepMind's Deep Q-learning playing Atari Breakout - YouTube

倒立振子で学ぶ DQN (Deep Q Network) - Qiita

倒立振子でDQNにおけるモデルの複雑さと学習内容の関係をちらっと確かめてみた系の話 - めもめも

TensorFlowで学ぶDQN

TensorFlow勉強会(4) TensorFlowで学ぶDQN - YouTube

コード

Tensorflowチュートリアルのコードに自分にとって分かるようにコメントを付け足したものです。

Tensorflow公式サイトのMNISTチュートリアルをやってみた

参考文献

*1:文字の横の括弧内の数字のペアは、代入されている行列の形状を表します。