Softmax-with-Lossレイヤを実装
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)) def cross_entropy_error(y, t): if y.ndim == 1: t = t.reshape(1, t.size) y = y.reshape(1, y.size) if t.size == y.size: t = t.argmax(axis=1) batch_size = y.shape[0] return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size class SoftmaxWithLoss: def __init__(self): self.loss = None self.y = None self.t = None def forward(self, x, t): self.t = t self.y = softmax(x) self.loss = cross_entropy_error(self.y, self.t) return self.loss def backward(self, dy=1): batch_size = self.t.shape[0] dx = (self.y - self.t) / batch_size return dx
Softmaxレイヤは入力された値を正規化し、出力の和が1になるようにします。
入力に対してSoftmaxで処理し、誤差を求める関数で、出力層に配置します。
\( y(k) = \frac{\exp(a_k)}{\sum^n_{i=1}\exp(a_i)} \)
多値の識別問題に使います。
正規化するだけなので、重みの順序は変わりません。
損失関数として交差エントロピー誤差を使います。
logの中身が0にならないよう、1e-7といった小さい値を足しておきます。
損失関数を使う事により、学習の進捗が浮動小数点で扱えるようになり、離散的な問題の最適化においても、プラトーに遭遇しにくくなるようです。
ニューラルネットワークはとにかく0, 1のような離散数を出さないようにする工夫が多いですね。