中学生にもわかるTensorFlow入門　その３　deepじゃないlearning - パーセプトロン

#はじめに
[前回](http://qiita.com/EtsuroHONDA/items/212ca0ece3e5bacf89e9 )、[前々回](http://qiita.com/EtsuroHONDA/items/02635dc3026e29f3cb41 )と数学的な準備をしてきましたが、ここではパーセプトロンというニューラルネットワークの一種について説明します

ニューラルネットワークには様々な種類があります。分類に関してはウキペディア（https://ja.m.wikipedia.org/wiki/ニューラルネットワーク ）を見て頂くとして、このシリーズでは、一般にはパーセプトロンと呼ばれ、先のウキペディアの記事では「フィードフォワードニューラルネット (順伝播型ニューラルネットワーク、英: Feedforward Neural Network, FFNN)」に分類されているものについて考えてみたいと思います

このニューラルネットワークは教師あり学習に分類されるもので、つまり、学習の際に答え合わせをして間違っていれば、ネットワーク間の重みを調節することによって学習すると言い換えることができるでしょう


#人工ニューロン（Artificial neuron）

英語版のウキペディアの記事（https://en.wikipedia.org/wiki/Artificial_neuron ）を参考にしながら簡単な歴史からお話しします。人工的な脳の神経細胞（ニューロン）のモデルが研究され始めたときに初めに考え出されたのは、1943年に神経生理学者・外科医であるウォーレン・マカロックと論理学者・数学者であるウォルター・ピッツが発表した形式ニューロンもしくは Threshold Logic Unitなどとと呼ばれるものでした。下の図を見て下さい（下図と式１はhttps://en.wikipedia.org/wiki/Artificial_neuron より引用）この神経細胞のモデルはこれからニューラルネットワークを考える際に基本になるものです。

![Artificial_neuron.png](https://qiita-image-store.s3.amazonaws.com/0/123035/0fdb76ce-fe57-b84f-0d7f-27ee89e5fcbc.png)


ここでは$v_k$が神経細胞（ニューロン）に相当し複数の入力($x_0～x_m)$があり、それらの入力に対しニューロン$v_k$はそれぞれ重み$ｗ_j(0\le j\le m）$を持ちます。出力$y_k$は、入力x$_i$に、それに相当する重み$w_i$を掛け、それらのすべての値の和になんらかの関数φで写像したものとなります（式１）また、これにバイアス(bias)を付けたものもよく使われます(式２）

```math
{ y }_{ k }=\varphi \left( \sum _{ j=0 }^{ m }{ { w }_{ kj } } { x }_{ j } \right)  　　　　　　...(式1)
```
```math
{ y }_{ k }=\varphi \left( \sum _{ j=0 }^{ m }{ { w }_{ kj } } { x }_{ j }+b_k \right)  　　　　　　...(式2)
```


##形式ニューロン

形式ニューロンの場合、

- 入力xjは０か１
- 入力に対する重み付け$w_{ki}$は実数
- 出力に使われる関数は、閾値を$θ$としたとき
- $H(x-θ)$　
（$H(x$）はヘヴィサイドの階段関数と呼ばれ$0 \le x$のとき$1$、$x＜0$のとき$0$となる）

すなわち、形式ニューロンの基本的な出力$y_k$は

```math
{ y }_{ k }=H\left( \sum _{ j=0 }^{ m }{ { w }_{ kj } } { x }_{ j }-\theta  \right) 　　　　　　（式３）
```

で表されます。重みと閾値を適切に定めることにより、適切な出力が決定されるという構造になっています。これは多層構造を持つことでによってチューリングマシンと同等の計算能力をもち、なおかつ非線形の問題にも対応しています（参考：https://ja.wikipedia.org/wiki/形式ニューロン ）

##パーセプトロン

1949年にヘップの法則が提唱されました。これを分かりやすく言うと、神経細胞同士の間の回路（これを司るものをシナプスという）はよく使うものほど強化され、使わなくなると徐々に結合が弱くなるというものです。ウキペディアの記事(https://ja.wikipedia.org/wiki/ニューラルネットワーク )より引用しましょう

>教師信号によるニューラルネットワークの学習は心理学者ドナルド・ヘッブが1949年に提唱したシナプス可塑性についての法則、「ヘッブの法則」に基づく。神経細胞間のネットワークの繋がりが太くなり、その結果、特定の細胞への情報伝達経路が作られる(情報が流れやすくなる)、これを学習とする

つまり、このようなヘップの法則を形式ニューロンのような神経回路モデルにあてはめることができないかということから考え出されたのがパーセプトロンでした。

###単純パーセプトロン

単純パーセプトロンは、1957年に心理学者・計算機科学者のフランク・ローゼンブラットによって考案され、1958年に論文が発表されています（参照：https://ja.wikipedia.org/wiki/パーセプトロン ）

この単純パーセプトロンは、形式ニューロンを発展させたさせたものですが、形式ニューロンと違う点としては

 + 入力は実数

ということのほかに、**学習という過程があります**。つまりトレーニングデータを複数を用意することによって、間違った答えを出力した場合、ある計算式に従って重み$w_{kj}$やバイアス$b_k$の値を変化させます。

注意点としては、形式ニューロンと同じく**単純パーセプトロンの出力も0か1の２値**であるということでしょうか

###多層化とバックプロパゲーション
上記の単純パーセプトロンは、基本的には線型分離可能な問題しか解くことができないという欠点があります。これでもかなりのことができるのですが、人間が扱うような問題、例えば人の顔を識別するなどの問題は非線形な問題であり、人間の脳の機能を説明するには不十分でした。

その問題を解決したのが、パーセプトロンの多層化と重みやバイアスの修正に最急降下法をを用いるという誤差逆伝搬法（バックプロパゲーション）の手法です。このあたりの歴史は少々複雑で、ウキペディアの記事（https://ja.wikipedia.org/wiki/バックプロパゲーション ）より引用すると

>「 バックプロパゲーション（英: Backpropagation）または誤差逆伝播法（ごさぎゃくでんぱほう）[1]は、機械学習において、ニューラルネットワークを学習させるための教師あり学習のアルゴリズムである。1986年にbackwards propagation of errors（後方への誤差伝播）の略からデビッド・ラメルハートらによって命名された[2]。
>
>隠れ層のない2層のニューラルネットワークでの出力誤差からの確率的勾配降下法は1960年にB. Widrow と M.E. Hoff, Jr. らが Widrow-Hoff 法（デルタルール）という名称で発表した[3][4]。隠れ層のある3層以上の物は、1967年に甘利俊一が発表した[5][6]。その後、何度も再発見され、1969年にアーサー・E・ブライソン（英語版）（Arthur E. Bryson）と何毓琦（英語版）が多段動的システム最適化手法として提案した[7][8]。ニューラルネットワークでの応用の物として、1974年のポール・ワーボス（英語版）[9]がある。1986年のデビッド・ラメルハート、ジェフリー・ヒントン、ロナルド・J・ウィリアムス（英語版）[10][2]らの再発見により定着し、特に1986年の発表以降ニューラルネットワーク研究が注目を浴び再活性化することになった。

とあります

実はこのバックプロパゲーションを用いる多層化したパーセプトロンの学習は非常に扱いが難しく、特に４層以上の多層化したいわゆる深層学習（ディープラーニング）において有効な学習方法が理解され始め、そのめざましい効果によってはっきり注目されてきたのは２０１０年代に入ってからのことになります

上の参照記事を見て頂くと分かりますが、ディープラーニングも様々な種類があり、それぞれに専門的な知見も必要となってきます。この「中学生にも分かるTensorFlow」のシリーズでは、あまり深入りはせず、今回の記事で単純パーセプトロンを説明し、その後、「MNIST For ML Beginners」で使われているニューラルネットワークのモデルについて説明するに留めます


#単純パーセプトロンの基礎

パーセプトロンに分類されるもののなかで最も基礎的な単純パーセプトロンについて説明します

単純パーセプトロンが線型のデータならば学習可能であるということを収束するといったりしますが、それについては数学的に証明されておりNovikoffの定理（もしくは収束定理など）と呼ばれています。これについては一度詳しく説明したことがありますので、リンク先のブログ[「パーセプトロンが線型分離可能であるということ」](http://perceptron-basic.blogspot.jp/ )をご参考下さい

ここでは、線型分離がどのようなことであるかということと、具体的な学習のアルゴリズムについて簡単に説明します

##線型分離

下図２のパーセプトロンの学習のイメージ図をご覧下さい

![図2　パーセプトロンの学習データ　イメージ図.png](https://qiita-image-store.s3.amazonaws.com/0/123035/0fc3bc8c-0776-e9bd-a35c-02483eba8a47.png)


○や×で表しているのが、データです。ここでは２次元のデータで表現していますが、実際には**a**$(a_1,a_2,....,a_n)$のn次元ベクトルで表されるデータです。そのデータを分割している直線は三次元であれば平面となり、それ以上の次元では超平面と呼ばれます。数学的には、

```math
y= \sum _{ j=0 }^{ m }{ { w }_{ kj } } { x }_{ j }+b_{ k } 　　　　　　...（式4）
```
という関数で表されます。

この超平面の上側または下側にあるかどうかと言うことを表す式は、すぐ後で説明する階段状関数f(x)を用いて

```math
{ y }_{ k }=f\left( \sum _{ j=0 }^{ m }{ { w }_{ kj } } { x }_{ j }+b_{ k } \right) 　　　　　　...（式5）
```

と表されます。この$f(x)$のことを**活性化関数**（伝達関数とも言う）と言いますが、一般に単純パーセプトロンで用いられるのは以下で表される形式ニューロンと同様の階段状関数です
<div style="text-align: center;">
![step function.png](https://qiita-image-store.s3.amazonaws.com/0/123035/4dcac901-c7a8-e01d-31b4-406af5f1f1ad.png)
</div>



つまり、様々なデータを図２のように二つに分けるというものが単純パーセプトロンというものです。そして、この二つに分けるときの境界を超平面といいます。これは、データの次数が二次元なら直線、三次元なら平面になることから類推され、データが四次元以上の場合われわれには想像しづらいものであるので平面から類推されるものとして超平面という言葉が使われていると考えて頂ければ良いと思います。したがって、単純パーセプトロンはしばしば**線型分類器**などという言い方もされます


##単純パーセプトロンの学習のアルゴリズム

まず、図3を見て下さい。

![図3　パーセプトロンの超平面.jpg](https://qiita-image-store.s3.amazonaws.com/0/123035/23796fd8-4ea5-af53-4ba4-e5a82f7cc679.jpeg)


図3では、原点からトレーニングデータ（教師データ）を二分する超平面までの距離$R$が実は求めたいバイアス$b$、同じように、超平面に垂直なベクトル（これを（超）平面の法線ベクトルと言います）が重みベクトル**w**$(w_1,w_2,...,w_m)$に相当するのが分かります。

単純パーセプトロンの学習においては、このような重みベクトル**w**とバイアス$b$を次のようなアルゴリズムで修正していくことによって学習を行います($η$は学習率と呼ばれる定数)

```
	もし　教師信号と異なる結果が出力された　ならば
	   現在の学習中の超平面とトレーニングデータとの距離を計算しewという変数に代入する
	   現在の学習中の超平面と原点との距離を計算しebという変数に代入する

	   さらに

	   もし　本当は超平面の下側にあるデータが上側であると判定された　ならば
	      すべての重みデータを記憶している変数wiに対して wi<=wi-η×ew　とする
	      バイアスデータを記憶している変数bに対して b<=b-η×eb　とする
	   そうではなく　もし　本当は超平面の上側にあるデータが下側であると判定された ならば
	      すべての重みデータを記憶している変数wiに対して wi<=wi+η×ew　とする
	      バイアスデータを記憶している変数bに対して b<=b+η×eb　とする
```

もちろん教師データは線形分離可能でなくてはなりません。こうして得られた学習結果により、様々な値を二つに分類することが可能となるのが単純パーセプトロンというものになります


#「MNIST For ML Beginners」のニューラルネットワークモデル

##「MNIST For ML Beginners」では何をしているのか

「MNIST For ML Beginners」では単純パーセプトロンに近い比較的簡単なニューラルネットワークで０から９までの手書き文字の画像を判定をさせています。この初心者向けの比較的簡単なプログラムでも91％を越える認識ができるそうです

[MNIST](http://yann.lecun.com/exdb/mnist/)というのは、画像認識の機械学習などで標準的に用いられている手書き文字の画像データベースです。トレーニングデータが60000セット、テスト用データが10000セット存在します。もともとは、アメリカ国立標準技術研究所（National Institute of Standards and Technology, NIST）で研究されている手書き文字のデータベースのサブセットにあたるようです

##ネットワークとアルゴリズムの概説
まず下の図を見て下さい[「MNIST For Beginners」](https://www.tensorflow.org/versions/r0.7/tutorials/mnist/beginners/index.html )にあるニューラルネットワークのモデルです

![softmax-regression-scalargraph.png](https://qiita-image-store.s3.amazonaws.com/0/123035/ae6036c6-5317-6ede-537a-9dada48ed79b.png)


これは、よく見ると下図のように、入力が同じではありますが単純パーセプトロンが三つあるように見えませんか。
![softmax-regression-scalargraphを書き直したもの.png](https://qiita-image-store.s3.amazonaws.com/0/123035/68e08972-e005-0d25-4c64-c17b9e9888e7.png)



つまり、「MNIST For ML Beginners」は基本的には単純パーセプトロンに非常に近いニューラルネットワークで手書き文字を判定していることになります

以下、このニューラルネットワークが単純パーセプトロンと異なる点を見ていきましょう。

###活性化関数

まず、出力の関数（活性化関数）φ（ｘ）の部分にsoftmax関数というものが使われています。単純パーセプトロンでは出力は一つで０か１かを単に出力するだけでしたが、今回は0から9までのどの文字かが出力になります。今回のニューラルネットワークでは出力が10個あり、それぞれが0から9までのどれかに対応するようになっています。そういうわけで、0が答えである場合0に相当する出力の値は1に近く他の出力は0に近い値になって欲しい。そうして、それらを確率としてみるならば、出力の値の合計は1になっていて欲しいということがあります。それで選ばれたのがsoftmax関数となります。ここでは、内容は分からなくてもいいので次のような関数になっているとだけ覚えておいて下さい

```math
\varphi \left( { u }_{ k } \right) =\frac { { e }^{ { u }_{ k } } }{ \sum _{ j=1 }^{ K }{ { e }^{ u_{ j } } }  } 
```
###誤差を判定する（コスト関数）

パーセプトロンでは出力が正しくなければ重みを修正するのでした。ところで単純パーセプトロンは出力が一つで値は二値でしたからまだ話は簡単でしたが、今回のようにたくさんの出力がある場合、どのようにしたら欲しい答えと現在の出力が判定できるでしょうか

これには下に書かれている交差エントロピーという関数を用います。これを用いればコストと呼ばれる、理想的な出力(下の式では${ d }_{ n,k }$）と現実の出力の差を計算することができます

```math
E\left( \varpi  \right) =-\sum _{ n=1 }^{ N }{ \sum _{ k=1 }^{ K }{ { d }_{ n,k } }  } \log { { y }_{ k } } 
```

###重みを修正する

重みの修正に関してはバックプロパゲーション（誤差逆伝達法）を用います。これについては先に少しふれてはいますが、少し難しいので今回は説明を省略したいと思います。いったんプログラムの説明を終えてから補足として解説の記事を書くかもしれませんが、ここでは下のような関数を利用して、重みベクトル**ｗ** $_k$やバイアス$ｂ_k$を修正していると理解して下さい

```math
\frac { \partial { E }_{ n }\left( \varpi  \right)  }{ \partial { u }_{ k } } ={ y }_{ n,k }-{ d }_{ n,k }
```

（以上式はウキペディア：https://ja.wikipedia.org/wiki/活性化関数 のものを引用した ）

#終わりに
今回で前置きは終わりです。[次回](https://qiita.com/EtsuroHONDA/items/79844b78655ccb3a7ae6)は、いよいよ「MNIST For ML Beginners」で説明されているプログラムをこれ以上ないと言うほど分かりやすく説明するつもりです