【機械学習】社内輪講 Week4 〜ニューラルネットワーク: 基本的な仕組み〜


## はじめに
[スタンフォード大学 Andrew Ng氏による機械学習の講義動画](https://www.coursera.org/learn/machine-learning)を各週社内メンバーで持ち回りで受講し、学んだことを発表、Qiitaで共有しています。

[【機械学習】社内輪講はじめました -Qiita](https://qiita.com/aoki-k/items/a25fe5e9d504f90f72f3)

これまでの講義内容

[【機械学習】社内輪講 Week1 〜 線形単回帰 〜](https://qiita.com/yyyokoy/items/3cd7caa3c2ee8ed74f3d)

[【機械学習】社内輪講 Week2 〜線形重回帰〜](https://qiita.com/i-chida/items/c88abb4520b5e1eb6765)

[【機械学習】社内輪講 Week3 〜ロジスティック回帰・正規化〜](https://qiita.com/aoki-k/items/9c4214d6b5c955b91591)

第4週は以下の内容でした。

- Neural Networks: Representation

## 目次
- ニューラルネットワークの起源
- 単層パーセプトロン
- パーセプトロン → ニューラルネットワーク
- 活性化関数
- 順伝播ニューラルネットワークの一般式

```math
\boldsymbol{u}^{(l+1)} = \boldsymbol{W}^{(l+1)} \boldsymbol{z}^{(l)} + \boldsymbol{b}^{(l+1)} \\ 
\boldsymbol{z}^{(l+1)} =f(\boldsymbol{u}^{(l+1)})
```
これらについて解説します。今回の記事では、ニューラルネットワークのパラメータ学習については触れません。

## ニューラルネットワークの起源
ニューラルネットワークは、1943年に神経生理学者のウォーレン・マカロックと数学者のウォルター・ピッツよって、神経細胞(ニューロン)を模して人工的に脳を再現するという発想から生まれた人工知能モデルのひとつである。

<img width="500" alt="スクリーンショット 2019-09-09 11.33.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/2fa884a9-a02b-5691-d83c-70e5af46a930.png">
出典：[Wikipedia: 神経細胞](https://ja.wikipedia.org/wiki/%E7%A5%9E%E7%B5%8C%E7%B4%B0%E8%83%9E)

人間の脳は無数の神経細胞の巨大なネットワークから構築され、各神経細胞は電気信号によって情報を伝えている。

<img width="600" alt="fullsizeoutput_b12.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/3f8425f3-0f10-7eb6-aa53-a7651d142c2b.jpeg">

ある神経細胞の前の神経細胞から伝わってきた電気信号の総和がある閾値を超えた場合、その神経細胞は「発火」する。そして、発火した神経細胞は次の神経細胞に電気信号を送る。

電気信号を送る強さ、神経細胞の発火しやすさを「学習」することで、人間(脳を持つ動物)は複雑なタスクをこなすことができると考えられている。

この神経細胞の仕組みを機械に置き換えることで**複雑な問題に柔軟に対応すること**を試みたのが、ニューラルネットワークの起源である。

## 単層パーセプトロン
パーセプトロンは神経細胞の仕組みを機械的に表したもののひとつである。

- 複数の入力信号 $x_i (i=1,2,\dots,n)$
- 入力信号を制御する重み $w_i (i=1,2,\dots,n)$
- 発火の閾値を制御するバイアス値 $b$
- 発火の閾値 $\theta$
- 発火したかどうかの出力信号 $y$

<img width="414" alt="スクリーンショット 2019-09-09 15.56.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/e5f3540e-ddb7-e4b7-80ae-45f9b4f39e15.png">

この図を数式で表すと、次の式になる。

```math
y = \begin{cases}
    0 & (x_1w_1+x_2w_2+ \dots+x_nw_n+b  \leqq \theta) \\
    1 & (otherwise)
\end{cases}
```

具体例として、このパーセプトロンを用いて単純な論理ゲート問題を解いてみる。今回は簡単のため $w=1, b=0$ の定数を利用する。

### ANDゲート
二つの入力値 $x_1,x_2$ のAND演算の真理値表は以下のようになる。

|$x_1$  |$x_2$  |$y$  |
|---|---|---|
|0  |0  |0  |
|0  |1  |0  |
|1  |0  |0  |
|1  |1  |1  |

これを平面グラフにプロットすると、$y$ の値はある直線によって片方の領域は $0$ 、もう片方の領域は $1$ というように分けることができる。この直線は上の数式で表すと、(だいたい) $\theta=1.5$ の時に成立する。$x_i$ の総和が 1.5 を超えたとき $y=1$ になる。これはANDゲートの特性をうまく表している。 

<img width="357" alt="スクリーンショット 2019-09-09 15.20.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/17d02498-006a-0f64-d7ce-a92cdf80701f.png">

パーセプトロンの数式を利用して表現するとこのようになる。

```math
y = \begin{cases}
    0 & (-1.5+x_1+x_2 \leqq 0) \\
    1 & (otherwise)
\end{cases}
```

### ORゲート
同様にORゲートの場合も考える。

|$x_1$  |$x_2$  |$y$  |
|---|---|---|
|0  |0  |0  |
|0  |1  |1  |
|1  |0  |1  |
|1  |1  |1  |

<img width="344" alt="スクリーンショット 2019-09-09 15.23.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/bc1d0bad-ffc8-4ed7-f3e4-ae21aafbdeae.png">

(だいたい) $\theta=0.5$ の時に成立する。$x_i$ の総和が 0.5 を超えたとき $y=1$ になる。

```math
y = \begin{cases}
    0 & (-0.5+x_1+x_2 \leqq 0) \\
    1 & (otherwise)
\end{cases}
```

### NANDゲート
念の為、NANDゲートの真理値表とグラフも記載しておく。

|$x_1$  |$x_2$  |$y$  |
|---|---|---|
|0  |0  |1  |
|0  |1  |0  |
|1  |0  |0  |
|1  |1  |0  |

<img width="318" alt="スクリーンショット 2019-09-09 18.50.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/b5975deb-3514-68e8-34b6-7141f2c3e320.png">


```math
y = \begin{cases}
    0 & (-0.5+x_1+x_2 \geqq 0) \\
    1 & (otherwise)
\end{cases}
```

### XORゲート
しかし、同様のことをXORゲートで試すと、直線を引くことができない。$0$ の領域と $1$ の領域で分けようとすると、ぐねぐねと曲がった**非線形**な曲線を引かなくてはならない。

|$x_1$  |$x_2$  |$y$  |
|---|---|---|
|0  |0  |0  |
|0  |1  |1  |
|1  |0  |1  |
|1  |1  |0  |

<img width="341" alt="スクリーンショット 2019-09-09 16.08.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/ffa8e5ef-21b5-ecd5-d0d6-1490063a7217.png">

XORゲートのように、**線形分離不可能な問題**は単層のパーセプトロンでは表現できない。これが単層パーセプトロンの欠点である。


## パーセプトロン → ニューラルネットワーク
しかし、パーセプトロンのメリットは**層を重ねることができる**点にある。ニューラルネットワークは単層パーセプトロンを多層化させ、**非線形分離問題に対応した**モデルである。それゆえ多層パーセプトロンと呼ばれることもある。

XORゲートは下の論理図のようにAND、NAND、ORをの組み合わせを使って表すことができる。

<img width="560" alt="スクリーンショット 2019-09-09 16.19.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/eaebf3d9-9bc7-385a-d987-9046790e0b3d.png">

|$x_1$  |$x_2$  |$s_1$  |$s_2$  |$y$  |
|---|---|---|---|---|
|0  |0  |1  |0  |0  |
|0  |1  |1  |1  |1  |
|1  |0  |1  |1  |1  |
|1  |1  |0  |1  |0  |

XORゲートを表現するために層を重ねたパーセプトロンの図が以下である。第0層目(のちの計算を簡単にするため、最初の層を第0層目にしている)のNANDゲート、ORゲートの出力信号 $s_1,s_2$ を第1層目で保持し、その信号をANDゲート出力することでXORゲートを実現している。

<img width="367" alt="スクリーンショット 2019-09-09 17.52.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/52654dd3-1585-7458-2d07-31a2f6ff7a84.png">

このように、パーセプトロンでは解くことのできなかったXORのような非線形な問題を解けることがわかった。**層を重ねることで**ニューラルネットワークに発展させ、より柔軟な表現が可能になったと言える。

## 活性化関数

パーセプトロンに導入した「発火したかどうか」の閾値判断は次の数式だった。

```math
y = \begin{cases}
    0 & (x_1w_1+x_2w_2+ \dots+x_nw_n+b  \leqq \theta) \\
    1 & (otherwise)
\end{cases}
```

これをより一般化させ、各ユニットの発火後の値 $z$ は $x_i\ (i=1,2,\dots,n)$ の総和 $u$ を引数とする関数 $f(u)$ によって決まると定義する。

```math
u = x_1w_1+x_2w_2+ \dots+x_nw_n+b\\
z = f(u)
```

$f(u)$ は**活性化関数**と呼ばれ、入力信号の総和が**どのように発火するか**(活性化するか)を決める役割を持っている。

<img width="368" alt="スクリーンショット 2019-09-10 11.14.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/b0b2b5b9-e5ea-cb71-74fd-e77374a58c7a.png">

活性化関数の種類はさまざまあり、それぞれ特性が異なる。

パーセプトロンに導入した活性化関数は**ステップ関数**と呼ばれ、0 を境に出力が 0 か 1 に切り替わる。グラフにプロットすると次のようになる。

<img width="400" alt="スクリーンショット 2019-09-09 16.19.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/2b392f65-3374-c517-4a65-ea49f683a4cd.png">

ニューラルネットワークでは、一般的に**シグモイド関数**が使われる。グラフにプロットすると次のようになる。

<img width="400" alt="スクリーンショット 2019-09-09 16.19.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/7a632582-1ff8-6953-3d6e-1be0ed9a44be.png">

シグモイド関数とステップ関数の違いは、グラフの形の滑らかさである。グラフが滑らかなことにより、 0 ~ 1 の間の出力値を殺し過ぎず、次の層に出力値を渡すことができる。また、式が微分可能なため、のちの計算で便利になる。

一応、シグモイド関数の式を載せておくが、数式自体にあまり大きな意味はない。数式よりもむしろグラフの形に意味がある。

```math
f(u) = \frac{1}{1+e^{-u}}
```

他にも活性化関数として ReLU関数 や tanh関数 などがある。 

## 順伝播ニューラルネットワークの一般式
最後に、最も基本的なニューラルネットワークである**順伝播ニューラルネットワーク**の一般式を段階を踏みながらまとめる。

### 第0層目 → 第1層目

<img width="384" alt="スクリーンショット 2019-09-09 18.11.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/7f4055cc-7142-ef72-6009-2c299fae9891.png">


第0層目のユニット数を4、第1層目のユニット数を3とする。

```math
u_1 = w_{11}x_1 + w_{12}x_2 + w_{13}x_3 + w_{14}x_4 + b_1\\
u_2 = w_{21}x_1 + w_{22}x_2 + w_{23}x_3 + w_{24}x_4 + b_2\\
u_3 = w_{31}x_1 + w_{32}x_2 + w_{33}x_3 + w_{34}x_4 + b_3
```

```math
z_1 = f(u_1)\\
z_2 = f(u_2)\\
z_3 = f(u_3)
```

```math
b_1=b_2=b_3
```

ここで、第0層目の数を $i\ (i=1,2,3,4)$ 第1層目の数を $j\ (j=1,2,3)$ とするとよりシンプルに記述できる。

```math
u_j = \sum^{4}_{i=1}w_{ji}x_i+b_j \\
z_j = f(u_j)
```

さらに、ベクトルと行列を用いて表記することもできる。

```math
\boldsymbol{u}=\boldsymbol{W}\boldsymbol{x}+\boldsymbol{b}\\
\boldsymbol{z} = \boldsymbol{f}(\boldsymbol{u})
```

### 第1層目 → 第2層目

第1層目、第2層目について考える。各層の $\boldsymbol{u}, \boldsymbol{W}, \boldsymbol{z}, \boldsymbol{b}$ を区別するために添字で $\boldsymbol{u}^{(l)}, \boldsymbol{W}^{(l)}, \boldsymbol{z}^{(l)}, \boldsymbol{b}^{(l)}$ と表現する。

第2層目の出力 $\boldsymbol{z}^{(2)}$ は第1層目の出力 $\boldsymbol{z}^{(1)}$ で決まるので、次の計算によって求まる。


```math
\boldsymbol{u^{(2)}}=\boldsymbol{W^{(2)}}\boldsymbol{z}^{(1)}+\boldsymbol{b^{(2)}}\\
\boldsymbol{z^{(2)}} = \boldsymbol{f}(\boldsymbol{u^{(2)}})
```

### 一般式
以上のことを踏まえて、計算を一般化する。

<img width="706" alt="スクリーンショット 2019-09-10 10.32.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469334/bd52830b-a456-19de-9605-a417d8699bbc.png">

$l+1$ 層目 $(l=0,1,\cdots,L)$ の出力 $\boldsymbol{z}^{(l+1)}$ は、一つ下の第 $l$ 層目の出力 $\boldsymbol{z}^{(l)}$から求めることができる。(便宜上、入力ベクトル $\boldsymbol{x}$ を第0層目の出力 $\boldsymbol{z^{(0)}}$ と見做す。)

```math
\boldsymbol{u}^{(l+1)} = \boldsymbol{W}^{(l+1)} \boldsymbol{z}^{(l)} + \boldsymbol{b}^{(l+1)} \\ 
\boldsymbol{z}^{(l+1)} =\boldsymbol{f}(\boldsymbol{u}^{(l+1)})
```
このように、入力 $\boldsymbol{x}$ に対し、入力側から出力側へ、上の計算を繰り返すことで情報を伝播させ、出力を計算する。そのため、**順伝播ニューラルネットワーク** (feedforward neural network)と呼ぶ。

## まとめ
Coursera の Andrew Ng 先生の講義を元に、基本的なニューラルネットワークの仕組みについて学びました。

次回、Coursera Machine Learning Week5 [ニューラルネットワークのパラメータ学習](https://qiita.com/myjm/items/74cb498b4291c876ef4d)について学んでいきます。