5.2. 損失関数¶
ニューラルネットワークでは、一つの指標を手掛かりに最適なパラメータを探索する
ニューラルネットワークの指標は 損失関数 (loss function)
損失関数は、ニューラルネットワークの性能の悪さを示す
5.2.1. 2乗和誤差 (mean squared error)¶
\[E = \frac{1}{2} \sum_{k}^{} (y_k-t_k)^2\]
[1]:
import numpy as np
def mean_squared_error(y, t):
return 0.5 * np.sum((y-t)**2)
[2]:
# 「2」を正解とする
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
# 「2」の確立が最も高い場合
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
mean_squared_error(np.array(y), np.array(t))
[2]:
0.09750000000000003
[3]:
# 「7」の確率が最も高い場合
y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
mean_squared_error(np.array(y), np.array(t))
[3]:
0.5975
この値から、一つ目の損失関数が小さいことがわかる
5.2.2. 交差エントロピー誤差 (cross entropy error)¶
\[E = - \sum_{k}^{} t_k\log{y_k}\]
[4]:
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
delta
は、np.log(0)
の計算時に-inf
にならないための防止策
[5]:
# 「2」を正解とする
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
# 「2」の確立が最も高い場合
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
cross_entropy_error(np.array(y), np.array(t))
[5]:
0.510825457099338
[6]:
# 「7」の確率が最も高い場合
y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
cross_entropy_error(np.array(y), np.array(t))
[6]:
2.302584092994546
5.2.3. ミニバッチ学習¶
訓練データすべての損失関数の和は、交差エントロピー誤差の場合
\[E = -\frac{1}{N} \sum_{n}\sum_{k} t_{nk}\log{y_{nk}}\]
\(t_{nk}\)は\(n\)個目のデータの、\(k\)番目の値のこと
\(y_{nk}\)はニューラルネットワークの出力
\(t_{nk}\)は訓練データ
訓練データすべてを計算するには時間がかかってしまうので、データの一部を選んで「近似」として学習させることを、ミニバッチ学習という。
[7]:
import sys, os
sys.path.append(os.path.abspath(os.path.join('..', 'sample')))
import numpy as np
from dataset.mnist import load_mnist # サンプルにあるPythonモジュール
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
print(x_train.shape)
print(t_train.shape)
(60000, 784)
(60000, 10)
[8]:
def cross_entropy_error(y, t):
"""
交差エントロピー誤差を出力します
Parameters
----------
y : np.array
ニューラルネットワークの出力
t : np.array
教師データ
"""
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
# 教師データがone-hot表現のとき
# return -np.sum(t * np.log(y) / batch_size)
# 教師データがラベルの場合
return -np.sum(np.log(y[np.arange(batch_size), t])) / batch_size
5.2.4. なぜ損失関数を設定するのか¶
パラメータの微分(正確には勾配)を計算し、その値と損失関数の値を比較するため
微分の値がマイナスであれば、重みパラメータをプラスに補正する
微分の値がプラスであれば、重みパラメータをマイナスに補正する
微分の値が0であれば、損失関数の値も変化しないので更新をストップする
5.2.4.1. なぜ認識制度ではないのか¶
例えば、100枚中32枚を正しく認識できたら、認識制度が32%になる。しかし、重みパラメータの値を少し変えただけでは認識制度が32%のままになる (32/100なので、細かい変化がつかめない)。仮に認識制度が向上しても、100枚中33枚、つまり33%と、値が整数でしか測れない。
一方、損失関数は100%中何%が外れだったのか(ざ、ざっくり過ぎる説明…)がわかる