深層学習 Day 1 - Section 3 出力層 のまとめ

この記事は個人的なお勉強用のメモです。

# このお勉強の位置

深層学習 Day 1

Section 0 ニューラルネットワークの全体像
Section 1 入力層～中間層
Section 2 活性化関数
**Section 3 出力層**　←　これ
Section 4 勾配降下法
Section 5 誤差逆伝播法

# 講義

- 出力層の役割  
人間が欲しいデータを出力する。  
分類：犬の確率
- 誤差関数
- 出力層の活性化関数

### 学習の処理

1. データを用意する。
 - 入力データ  
 画像であればピクセル値。
 - 入力データに対する訓練データ（正解値）  
人間がラベルを付けておく。  
分類であれば、0（不正解）または1（正解）。

2. NNに入力データを渡す。 
重み $W$ やバイアス $b$ はランダムに決めておく。

3. 犬や猫の確率が出力層から出力される。

4. 出力された値と正解値を比較する。
これらの値の違いを「誤差」と呼ぶ。
誤差を誤差関数で計算する。
誤差関数の例：二乗和誤差

```math
E_n(w)=\frac{1}{2}\sum_{j=1}^l(y_j-d_j)^2=\frac{1}{2}||(y-d)||^2
```

$y$：正解値
$d$：NNによる出力値

### 誤差関数

誤差関数の使い分け

分類問題：クロスエントロピー誤差
回帰問題：平均二乗誤差

### 出力層の活性化関数

#### 出力層と中間層の違い

層によって利用される活性化関数が異なる。

- 中間層はしきい値の前後で信号の強弱を調整、出力層は比率そのまま。
- 分類問題の場合0から1の範囲に変換。総和は1。

分類問題では確率として出力するため。

- ソフトマックス関数
- 恒等写像
- シグモイド関数

### 活性化関数の使い分け

||回帰|二値分類|多クラス分類|
|---|---|---|---|
|出力層の活性化関数|恒等写像|シグモイド関数|ソフトマックス関数|
|誤差関数|二乗誤差|交差エントロピー|交差エントロピー|

文章で書くと、回帰の場合は妙な変換はせずに、二乗誤差で判定。
（数値なので、純粋な四則演算ができる）

分類の場合は、シグモイド関数またはソフトマックス関数で出力して、
交差エントロピーで判定。（交差エントロピーで疑似的な距離が求まるからか）

#### 恒等関数

値をそのまま出力する関数。

#### ソフトマックス関数

```math
f(i,u)=\frac{e^{u_i}}{\sum_{k=1}^K e^{u_k}}
```

i：i番目のデータ
K：クラスの個数

ソースコードは確認テストを参照。

#### 二乗誤差

```python
def mean_squared_error(d, y):
  return np.mean(np.square(d-y)) / 2
```

↑ 二乗誤差ではなく、平均二乗誤差(MSE)の関数
ベクトルでの二乗：np.square
ベクトルでの平均：np.mean


```math
E_n(w)=\frac{1}{2}\sum_{i=1}^l(y_n-d_n)^2
```

何度も登場しているので説明は省略。

#### 交差エントロピー

非常によく使う誤差関数。

```math
E_n(w)=-\sum_{i=1}^l d_i \log y_i
```

$d$：正解値 (0 or 1)
$y$：NN実行による出力値

これはまさに、情報理論で学習した交差エントロピーそのもの。
ソースコードは確認テストを参照。

# 実装演習

1_1_forward_propagation_after.ipynb
「順伝播（3層・複数ユニット）」を実行した結果。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/9f6e89f1-11b7-9c09-8919-b3d536537803.png)

3つのデータを入力値として与えると、3つの値が出力された。
出力層では何も値を変換していない（恒等写像）。

ただ、重みやバイアスをランダムに初期化して実行しただけのため
現時点では出力された値に意味はない。

次回以降の Section（勾配降下法や誤差逆伝播法）を学ぶと
出力された値の意味を知ることになるはず。

# 確認テスト

### 二乗する理由

二乗する理由はそれぞれの差分をすべて正の値（誤差）として扱うため。

模範解答
引き算を行うだけでは、各ラベルでの誤差で正負両方の値が発生し、
全体の誤差を正しく表すのに都合が悪い。
2乗してそれぞれのラベルでの誤差を正の値になるようにする。

そこまで外していない。

### 2分の1の意味

微分したときに都合がいいから。
（微分すると2が出てきて、2分の1と打ち消し合う）

模範解答
実際にネットワークを学習するときに行う誤差逆伝搬の計算で
誤差関数の微分を用いるが、その際の計算式を簡単にするため。
本質的な意味はない。

「本質的な意味はない」というのもポイントか。

### ソフトマックス関数のサンプルコード

```python
def softmax(x):
  if x.ndim == 2:
    x = x.T
    x = x - np.max(x, axis=0)
    y = np.exp(x) / np.sum(np.exp(x), axis=0)
    return y.T
  x = x - np.max(x) # オーバーフロー対策
  return np.exp(x) / np.sum(np.exp(x))
```

①～③の数式に該当するソースコードは np.exp(x) / np.sum(np.exp(x))

解説によると、if x.ndim == 2: の部分はミニバッチとのこと。
オーバーフロー対策は赤本に書いてあったので理解している。

### 交差エントロピーのサンプルコード

```python
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
```

np.sumの行が本質的なコードの場所。

講義だけでは理解できなかったが、赤本の 4.2.4 項の説明を読んで理解できた。

バッチ y は出力データが複数行になっているもの。
バッチの行と同じ数だけの値が、正解値のベクトル d に格納されている。
np.arange関数でバッチの数の数列を生成する。
正解値 d はone-hot表現になっている。
d.argmax関数によって正解値のインデックスを取得し、変数 d に書き戻す。
[np.arange(batch_size), d]は、バッチの数列と正解値のインデックスの組み合わせ。
それを y という出力データに与えて、
- バッチ内のどの行から確率を抽出するか（np.arangeの出力が行番号になっている）
- 行のどのインデックスから確率を抽出するか（d.argmaxの出力がインデックスになっている）
が決まる。

# 修了テスト～練習問題～

出力値に関する問題は見つからなかった。
代わりに赤本で勉強したこと。

赤本の 4.2.2 項に以下の交差エントロピーのソースコードが掲載されている。

```python
def cross_entropy_error(y, t):
  delta = 1e-7
  return -np.sum(t * np.log(y + delta))
```

このソースコードは数式に忠実で理解しやすい。
これをミニバッチに対応したのが、講義で出てきたソースコード。