備忘録_損失関数

備忘録_損失関数
  • 損失関数を手掛かりにニューラルネットワークの最適なパラメータを探索する
  • 任意の関数を用いることができるが、一般的には2乗和誤差や交差エントロビー誤差などを用いる
  • 性能の”悪さ”を示す指標
  • 教師データに対してどれだけ適合していないか、どれだけ一致していないかを表す

2乗和誤差

数式で表すと・・・

     \[ E = \frac{1}{2}\displaystyle\sum_{k}^{}(y^{}_{k}-t^{}_{k})^2 \]

  • y^{}_{k}・・・ニューラルネットワークの出力
  • t^{}_{k}・・・教師データ
  • k・・・データの次元数

Pythonで実装すると・・・

import numpy as np

#2乗和誤差
def mean_squared_error(y, t):
    return 0.5 * np.sum((y - t) ** 2)

#「2」を正解とする
t = [0,0,1,0,0,0,0,0,0,0]

#例1:「2」の確率が最も高い場合(0.6)
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))
0.09750000000000003

#例2:「7」の確率が最も高い場合(0.6)
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))
0.5975

「a の n 乗」の形で表される数 a^n のことを「a のべき乗」と言う。Pythonではべき乗はa**n で計算できる。

例1の出力結果のほうが教師データに適合していることを2乗和誤差法は示している

交差エントロピー誤差

数式で表すと・・・

     \[ E = -\displaystyle\sum_{k}^{}t^{}_{k} log y^{}_{k} \]

  • log・・・底がeの自然体数(log^{}_{e})を表す
  • y^{}_{k}・・・ニューラルネットワークの出力
  • t^{}_{k}・・・教師データ(正解ラベル)
  • k・・・データの次元数

実質的に正解ラベルが1に対応する出力の自然対数を計算するだけである。

自然対数y=logxのグラフ


正解ラベルに対応する出力(x)が大きければ大きいほど0に近づく

Pythonで実装すると・・・

import numpy as np

#交差エントロピー誤差
def cross_entropy_error(y, t):
    delta = 1e-7
    return -np.sum(t*np.log(y+delta))

#「2」を正解とする
t = [0,0,1,0,0,0,0,0,0,0]

#例1:「2」の確率が最も高い場合(0.6)
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))
0.510825457099338

#例2:「7」の確率が最も高い場合(0.6)
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))
2.302584092994546

1e-7=0.0000001 1*10^(-7)(1かける10の-7乗)delta
np.logの計算時に微小な値であるdeltaを足して計算している。np.log(0)のような計算が発生した場合、np.log(0)はマイナスの無限大を表す-infとなり計算ができなくなる。その為の防止策として微小な値を追加して、マイナス無限大を発生させないようにしている。

こちらの結果も例1の出力結果のほうが教師データに適合していることを交差エントロピー誤差は示している

すべての訓練データの損失関数を求める

訓練データに対する損失関数を求め、その値をできるだけ小さくするようなパラメータを探し出す必要がある。その為にはすべての訓練データを対象として求める必要がある。

交差エントロピー誤差の和

1個あたりの「平均の損失関数」を求める

     \[ E = -\frac{1}{N}\displaystyle\sum_{n}^{}\sum_{k}^{}t^{}_{nk} log y^{}_{nk} \]

  • N・・・データの数(最後にNで割って正規化)
  • n・・・何個目のデータか
  • log・・・底がeの自然体数(log^{}_{e})を表す
  • y^{}_{k}・・・ニューラルネットワークの出力
  • t^{}_{k}・・・教師データ(正解ラベル)
  • k・・・データの次元数

ビックデータの学習(ミニバッチ学習)

データの中から一部のデータを無作為に選び、学習する(ミニバッチ学習)。

import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
#MINISTデータセットの読み込み
(x_train, t_train),(x_test, t_test) = load_mnist(normalize = True,one_hot_label=True)
#ランダムに10枚抜き出し
train_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
np.random.choice(60000,10) 
array([31707, 23955, 40223,  4433, 49955, 39515,  5855, 27492, 28831, 34313])

ミニバッチに対応した交差エントロピー実装

one-hot表現用

def cross_entropy_error(y, t):
    #データの形状成形
    if y.ndim ==1:
        t = t.reshape(1, t.size)
        y = t.reshape(1, y.size)
    delta = 1e-7
    batch_size = y.shape[0]
    #バッチサイズで正規化
    return -np.sum(t * np.log(y + delta)) / batch_size
  • y
    ニューラルネットワークの出力
  • t
    教師データ
  • データの形状成形
    yの次元数が1(y.ndim ==1)の場合(データひとつあたりの交差エントロピー誤差を求める場合)データの形状を成形(reshape)する
  • バッチサイズで正規化
    1個あたりの「平均の損失関数(交差エントロピー誤差)」を計算

教師データがラベルの場合用

def cross_entropy_error(y, t):
    #データの形状成形
    if y.ndim ==1:
        t = t.reshape(1, t.size)
        y = t.reshape(1, y.size)
    delta = 1e-7
    batch_size = y.shape[0]
    #バッチサイズで正規化
    return -np.sum(np.log(y[np.arange(batch_size), t] + delta)) / batch_size
  • y
    ニューラルネットワークの出力
  • t
    教師データ
  • データの形状成形
    yの次元数が1(y.ndim ==1)の場合(データひとつあたりの交差エントロピー誤差を求める場合)データの形状を成形(reshape)する
  • バッチサイズで正規化
    1個あたりの「平均の損失関数(交差エントロピー誤差)」を計算
  • t * np.log(y + delta)⇒np.log(y[np.arange(batch_size), t] + delta)
    np.arange(batch_size)・・・batch_size-1の配列を生成
    よって、各データの正解ラベルに対応するニューラルネットワークの出力を抽出する
    例 batch_sizeが5、tが[2, 7, 0, 9, 4]の場合
    np.arange(batch_size)⇒[0, 1, 2, 3, 4]のNumPy配列
    y[np.arange(batch_size), t]⇒[y[0, 2],y[1, 7],y[2, 0],y[3, 9],y[4, 4]]

損失関数を設定する理由

ニューラルネットワークの学習の際に、認識制度を”指標”にしてはいけない。その理由は、認識制度を指標にすると、パラメータの微分がほとんどの場所で0になってしまうからである。


全訓練データ数:100、正しく認識できたデータ:32の場合認識精度 32%である。パラメータを少し変更した場合認識精度は32%のままで改善されず、一定のままである。改善されたとしても、33%や34%のように不連続のとびとびの値へと変わる。一方、損失関数を指標とした場合、0.92543・・・のような値によって表され、パラメータを変えると0.93432・・・のように連続的に変化する。

認識制度はパラメータの微小な変化にはほとんど反応を示さず、もし反応があるにしても、その値は不連続いきなり変化する。