ラビットチャレンジ - 深層学習 Day1 Section3 出力層

# 0．概要
本記事は日本ディープラーニング協会認定の講座プログラムである「ラビット・チャレンジ」が提供している科目の1つである深層学習のレポートである。
記事タイトルに記載のとおり、Day1 Section3の出力層について以下にまとめる。

# 1．出力層
分類であれば各クラスに属する確率等、人が欲しい最終的な結果を出力する。
学習において、この出力層の結果と目的変数の値を比較し、どれくらい合っているか、ズレているか算出するため誤差関数を用いる。

# 2．誤差関数
例えば分類の場合、各クラスが属する確率とOne-hotベクトルで表現されている各クラスの正解値をもとにどれだけ合っているか、ズレているか算出する。
ズレているほど値は大きくなる。

2値分類ならクロスエントロピー関数、他クラス分類ならカテゴリカルクロスエントロピー関数、回帰なら平均二乗誤差や平均絶対誤差等が用いられる。

## 2.1．平均二乗誤差
平均二乗誤差はこれまで同様。

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

np.squareは2乗を表す。

## 2.2．交差エントロピー関数

```math
E_{n}(w)=-\sum_{i=1}^{I}{d_{i}log\ y_{i}}
```

```Python
def cross_entropy_error(d, y):
  if y.ndim == 1:
    d = d.reshape(1, d.size)
    y = y.reshape(1, y.size)

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

# 3．活性化関数
中間層の場合は入力値の信号の強弱を調整(重み付け)するために用いられるが、出力層の場合は信号の大きさはそのままに分類の確率や回帰の連続値等に変換する。

## 3.1．シグモイド関数
Section2と書いた式、コードを参照。
ロジスティック回帰で用いる時と同じで2値分類で1のクラスに該当する確率を出力する。
1のクラスに該当する確率、1のクラスに該当しない確率(0のクラスに該当する確率)を合計すると1となる。

## 3.2．ソフトマックス関数
各クラスに該当する確率を出力する。
クラス数$K$の全ての確率を合計すると1となる。
他クラス分類(3クラス以上)に用いられる。

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

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

# 4．確認テスト

## 4.1．確認テスト1
今回用いていた誤差関数、平均二乗誤差においてなぜ予測と目的変数を引き算だけでなく2乗するか。

回答：
正の方向にズレているか負の方向にズレているかの2パターンが考えられるが、正負の値が混在していると総和をした時に正しく誤差が合計できないため。
分散と同じ考え方。

## 4.2．確認テスト2
平均二乗誤差においてなぜ1/2しているか。

回答：
式の単純化のため。
2乗部分は微分すると2が前に出るため1/2を置くことで打ち消すことができる。
誤差という意味では変わらないので1/2があってもいいしなくても良い。機械学習の講座であったように$n$で割って平均にしても良い。

## 4.3．確認テスト3
ソフトマックス関数の数式に該当するコードについて1行ずつ処理の説明をせよ。

回答：

```Python:
def softmax(x):
  if x.ndim == 2:    # 2次元の場合。
    x = x.T          # xを転置
    x = x - np.max(x, axis=0)  # xから列方向(縦に見て)取った最大値を引く。スケーリング？
    y = np.exp(x) / np.sum(np.exp(x), axis=0) # xの指数関数の値(数式の分子)を指数関数の総和(数式の分母)で割って確率としている。

    return y.T

  x = x - np.max(x)  # オーバーフロー対策
  return np.exp(x) / np.sum(np.exp(x))
```

## 4.4．確認テスト4
交差エントロピー関数の数式に該当するコードについて1行ずつ処理の説明をせよ。

回答：

```Python
def cross_entropy_error(d, y):
  if y.ndim == 1:    # 1次元の場合。例えば(3,)みたいな形状。
    d = d.reshape(1, d.size)    # (1, 全要素数)のベクトルに変形
    y = y.reshape(1, y.size)    # (1, 全要素数)のベクトルに変形

  # 教師データが one-hot-vector の場合、正解ラベルのインデックスに変換
  if d.size == y.size:
    d = d.argmax(axis=1)  # argmaxで最大値(予測の最も確からしいクラス)のインデックスを取得

  batch_size = y.shape[0] # この場合は行の形状なので1
  # 「/ batch_size」までが上記の式に該当(左記の部分は使い勝手を良くするためのもの)
  # np.arangeでバッチサイズ分取り出して対数関数に与えている。
  # 「1e-7」は対数関数の結果が0になることを回避するために極めて小さい値を与えている。
  return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7) / batch_size
```

# X．ラビットチャレンジとは
ラビットチャレンジとは、日本ディープラーニング協会認定の講座プログラムの1つ。
E資格を受験するためにはこのラビットチャレンジ等、いずれかの講座プログラムを修了しなければならない。

ラビットチャレンジの特徴は「現場で潰しが効くディープラーニング講座」の通学講座録画ビデオを編集した教材を使用した自習スタイルであるという点。
サポートは他の講座より少なく、受け身ではなく自主的に学んでいく姿勢でなければ進められないが、その分、他の講座に比べると安価であり、手が出しやすい。
ある程度知識がある人、自力で頑張るぞというガッツのある人向けではないかと感じる。

![bnr_jdla.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389699/bce66671-a2f5-a7f9-de6f-3f87e15c253b.png)