ゼロから作る Deep Learning 2章 パーセプトロン（読書メモ）

## はじめに

### この記事はなに？

勉強会用の資料兼メモ書きです。内容の妥当性については一切保証しかねるため、引用等はお控えいただくことをおすすめします.

### 参考リンク

- [パーセプトロン - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BB%E3%83%97%E3%83%88%E3%83%AD%E3%83%B3)
- [高卒でもわかる機械学習 (2) 単純パーセプトロン | 頭の中に思い浮かべた時には](http://hokuts.com/2015/11/25/ml2_perceptron/)
- [高卒でもわかる機械学習 (3) 多層パーセプトロン | 頭の中に思い浮かべた時には](http://hokuts.com/2015/12/04/ml3-mlp/)
- [第15回　分類問題ことはじめ：機械学習 はじめよう｜gihyo.jp … 技術評論社](http://gihyo.jp/dev/serial/01/machine-learning/0015)
- [やる夫で学ぶ機械学習 - パーセプトロン - · けんごのお屋敷](http://tkengo.github.io/blog/2016/06/03/yaruo-machine-learning4/)

## 2.1 パーセプトロンとは

<img width="264" alt="perceptron.png" src="https://qiita-image-store.s3.amazonaws.com/0/5807/684fe085-00cb-4bed-321c-a65cb84db07d.png">

_2入力のパーセプトロン（「ゼロから作る Deep Learning」P.22より）_


- 複数の信号を入力として受け取り、ひとつの信号を出力するモデル
- 信号は 0 (流さない) or 1 (流す) の二値
- 各入力に固有の重み $ w^1, w^2 ... $ が乗算される（e.g. $ w^1x^1 $）
- 重みが大きいほど対象となる信号の重要性が増す
- 入力値の総和が任意の閾値 $ \theta $ を超えると 1 を出力する（「ニューロンが発火する」）

出力を $ y $ として、上記の要素を数式で表すと以下となる.

```math
y = \left\{
\begin{array}{ll}
0 & (w^1x^1 + w^2x^2 \leqq \theta) \\
1 & (w^1x^1 + w^2x^2 \gt \theta)
\end{array}
\right.
```


## 2.2 単純な論理回路

- パーセプトロンを使用することで AND / NAND /OR の論理回路を表現できる
- パーセプトロンの構造に変更を加えること無く、重みと閾値を変化させる振る舞いを変える

### 2.2.1 AND ゲート

_P.23 「図2-2 AND ゲートの真理値表」を参照_

- 2つの入力が 1 のときだけ 1 を出力し、それ以外は 0 を出力する
- 2つの入力値の総和が閾値 $ \theta $ を超えると出力をおこなうパーセプトロン

### 2.2.2.1 NAND ゲート

_P.24 「図2-3 NAND ゲートの真理値表」を参照_

- NAND = Not AND = AND ゲートと逆の振る舞い
- 両方が 1 のときだけ 0 を出力し、それ以外は 1 を出力する
- AND ゲートを実現するパラメータの値に対して、その符号を反転させると NAND ゲートになる

### 2.2.2.2 OR ゲート

- 最低でもひとつの入力が 1 であれば 1 を出力する


## 2.3 パーセプトロンの実装

### 2.3.1 簡単な実装

AND 回路を以下のように定義して実行してみましょう.

```python
def AND(x1, x2):
  w1, w2, theta = 0.5, 0.5, 0.7
  tmp = x1 * w1 + x2 * w2

  if tmp <= theta:
    return 0
  elif tmp > theta:
    return 1
```

### 2.3.2 重みとバイアスの導入

- 2.3.1 の AND 回路にバイアスを導入する.
- バイアスを $ b $ として、式 2.1 の $ \theta $ を $ -b $ に置き換える.

```math
y = \left\{
\begin{array}{ll}
0 & (w^1x^1 + w^2x^2 \leqq \theta) \\
1 & (w^1x^1 + w^2x^2 \gt \theta)
\end{array}
\right.
```

$$ ↓ $$

```math
y = \left\{
\begin{array}{ll}
0 & (b + w^1x^1 + w^2x^2 \leqq 0) \\
1 & (b + w^1x^1 + w^2x^2 \gt 0)
\end{array}
\right.
```

インタプリタで確認してみましょう.

```py
>>> import numpy as np
>>> x = np.array([0, 1]) # 入力
>>> w = np.array([0.5, 0.5]) # 重み
>>> b = -0.7 # バイアス
>>> w * x
>>> np.sum(w * x)
>>> np.sum(w * x) + b
```

### 2.3.3 重みとバイアスによる実装

前項を踏まえて AND / NAND / OR の各回路を実装してみましょう.

- AND 

```py
def AND(x1, x2):
  x = np.array([x1, x2])

  w = np.array([0.5, 0.5])
  b = -0.7

  tmp = np.sum(w * x) + b
  
  if tmp <= 0:
    return 0
  else:
    return 1
```

- NAND

```py
def NAND(x1, x2):
  x = np.array([x1, x2])

  # AND と違うのは重みとバイアスだけ
  w = np.array([-0.5, -0.5])
  b = 0.7

  tmp = np.sum(w * x) + b
  
  if tmp <= 0:
    return 0
  else:
    return 1
```

- OR

```py
def OR(x1, x2):
  x = np.array([x1, x2])

  # AND と違うのはバイアスだけ
  w = np.array([0.5, 0.5])
  b = -0.2

  tmp = np.sum(w * x) + b
  
  if tmp <= 0:
    return 0
  else:
    return 1
```

#### バイアスと重みのちがい

- 重み $ w^1, w^2 ... $ は入力信号の重要度をコントロールする
- バイアスはニューロンの発火しやすさ(1 を出力する確率)を調整する

>
バイアスという用語には、「ゲタはき」という意味があります。これは、入力が 何もないときに(入力が 0 のときに)、出力にどれだけゲタをはかせるか(値を 上乗せするか)ということを意味します。実際、式 (2.2) の b + w1 x1 + w2 x2 の計算では、入力の x1 と x2 が 0 の場合、バイアスの値だけが出力されます。

(P.27より抜粋)

## 2.4 パーセプトロンの限界

- 単層のパーセプトロンは線形な領域を分離できるが、 XOR (排他的論理和)等の非線形な領域を分離できない.


## 2.5 多層パーセプトロン

- 「層を重ねる」ことで XOR を表現することができる.
- 複数の層を重ねたパーセプトロンを**多層パーセプトロン (multi-layered perceptron)** と呼び、「$ n $層のパーセプトロン」などと表現する.

### 2.5.1 既存ゲートの組み合わせ

入力の一方が 1 でもう一方が 0 の場合に 1 を出力する XOR 回路を、既存の AND / NAND / OR を組み合わせて表現します.
もう一度各回路の振る舞いを整理します.

- AND ... 2つの入力が 1 の場合に 1 を出力し、それ以外は 0 を出力する.
- NAND ... 2つの入力が 1 の場合に 0 を出力し、それ以外は 1 を出力する.
- 2つの入力の少なくとも一方が 1 の場合に 1 を出力し、それ以外は 0 を出力する.
- XOR ... 2つの入力の一方が 1 でもう一方が 0 の場合に 1 を出力し、それ以外は 0 を出力する.

実際には以下の配線で実現できます. 初期値を $ x^1, x^2 $ とし, NAND の出力を $ s^1 $, OR の出力を $ s^2 $ とします.

<img width="675" alt="xor.png" src="https://qiita-image-store.s3.amazonaws.com/0/5807/f9f71593-de0e-c862-19fc-9dc9028c0547.png">
_P.32 図2-11_

真理値表で確認します.

<img width="672" alt="xor-chart.png" src="https://qiita-image-store.s3.amazonaws.com/0/5807/2111a8f4-e27c-afa9-dfca-a8e9b0e0eac1.png">
_P.33 図2-12 XOR ゲートの真理値表_


### 2.5.2 XOR ゲートの実装

前項を踏まえてコードに実装してみましょう.

```py
def XOR(x1, x2):
  s1 = NAND(x1, x2)
  s2 = OR(x1, x2)
  y = AND(s1, s2)
  return y
```


## 2.6 NAND からコンピュータへ


## 2.7 まとめ

- パーセプトロンは入出力を備えたアルゴリズムである。ある入力を与えた ら、決まった値が出力される。
- パーセプトロンでは、「重み」と「バイアス」をパラメータとして設定する。
- パーセプトロンを用いれば、AND や OR ゲートなどの論理回路を表現で
きる。
- XOR ゲートは単層のパーセプトロンでは表現できない。
- 2 層のパーセプトロンを用いれば、XOR ゲートを表現することができる。
- 単層のパーセプトロンは線形領域だけしか表現できないのに対して、多層
  のパーセプトロンは非線形領域を表現することができる。
- 多層のパーセプトロンは、(理論上)コンピュータを表現できる。