交差エントロピー誤差(クロスエントロピー)— 定義・情報理論・勾配・実装を完全解説

ニューラルネットワークで「この画像は猫か犬か鳥か」を分類するとき、モデルの良し悪しをどう測ればよいでしょうか。単に「当たった/外れた」の正答率だけでは、学習を進めるための滑らかな手がかりになりません。「正解にどれだけ自信を持てたか」を連続的に評価し、外れているほど大きなペナルティを与える——この役割を担うのが 交差エントロピー誤差(Cross-Entropy Loss、クロスエントロピー) です。

交差エントロピーは、画像分類・自然言語処理(言語モデルの次単語予測)・音声認識など、分類タスクのほぼ標準の損失関数として使われています。名前は仰々しいですが、中身は「正解クラスの予測確率に $-\log$ を取るだけ」とシンプルです。この記事では、その定義から情報理論的な意味、勾配の美しさ、そして「なぜ分類では二乗誤差より交差エントロピーが好まれるのか」までを、図とコードで一気に理解します。

交差エントロピー損失の形:−log(x)

先に結論の図を見ておきましょう。交差エントロピーは「正解クラスへの予測確率」が $1$ に近いほど損失ゼロ、$0$ に近いほど損失が無限大に発散します。「正解に自信を持てば報われ、自信なく外せば強く罰せられる」——この素直な性質が、分類の学習をうまく導きます。

前提知識

この記事は高校数学の $\log$ と $\sum$(シグマ)がわかれば読めます。さらに踏み込みたい場合は、以下を押さえておくと理解が深まります。

まずは定義式から見ていきましょう。

交差エントロピー誤差の定義

$K$ 個のクラスがある分類問題を考えます。モデルの予測確率を $\bm{y} = (y_1, \dots, y_K)$(各クラスの確率、$\sum_k y_k = 1$)、正解ラベルを one-hot 表現した $\bm{t} = (t_1, \dots, t_K)$(正解クラスだけ $1$、他は $0$)とします。このとき、1つのデータに対する交差エントロピー誤差は次で定義されます。

$$ \begin{equation} \mathrm{CrossEntropyLoss} = – \sum_{k=1}^{K} t_k \log y_k \end{equation} $$

式だけ見ると仰々しいですが、$\bm{t}$ が one-hot である点に注目すると一気に簡単になります。

交差エントロピーの仕組み

図のように、$t_k$ は正解クラスだけ $1$ で、それ以外は $0$ です。したがって $t_k \log y_k$ は正解クラス以外ではすべてゼロになり、和の中で生き残るのは正解クラスの項だけです。結局、交差エントロピーは

$$ \mathrm{Loss} = – \log y_c \qquad (c = \text{正解クラス}) $$

という、たった1項の式に帰着します。「正解クラスにモデルが与えた確率 $y_c$ の対数にマイナスを付けただけ」——これが交差エントロピーの正体です。

−log(x) の形が意味すること

損失が $-\log y_c$ なので、その形は $-\log(x)$ の曲線そのものです。

予測確率と損失の関係

図のように、正解クラスへの予測確率が高い(自信あり、$p=0.9$)ほど損失は小さく、低い(自信なし、$p=0.2$)ほど損失は大きくなります。$p \to 0$ では損失が無限大に発散します。これは「正解なのにほぼ確率ゼロを付けた」モデルへの強烈なペナルティで、学習を正しい方向へ強く引き戻す働きをします。逆に $p \to 1$ で損失ゼロに近づくので、「正解に確信を持てた」状態が報われます。

正答率(当たり外れの0/1)と違い、交差エントロピーは「どれだけ自信を持てたか」を連続的に測れるため、勾配法による学習に向いているのです。

二値分類の場合(Binary Cross-Entropy)

クラスが2つ(正例 $y=1$/負例 $y=0$)の場合は、予測確率 $p$(クラス1である確率)を使って次のように書けます。

$$ \begin{equation} \mathrm{BCE} = -\big[\, y \log p + (1-y)\log(1-p) \,\big] \end{equation} $$

正解が $y=1$ なら $-\log p$、$y=0$ なら $-\log(1-p)$ となり、多クラスの式の特殊ケースになっています。

二値交差エントロピー

図は2つの損失曲線です。正解が $y=1$(緑)のときは $p$ を $1$ に近づけるほど損失が下がり、正解が $y=0$(赤)のときは $p$ を $0$ に近づけるほど損失が下がります。どちらの場合も「正解側に確率を寄せると報われる」構造になっているのがわかります。

情報理論から見た交差エントロピー

「交差エントロピー」という名前は、情報理論に由来します。ここを押さえると、なぜこの損失が自然なのかが腑に落ちます。

出発点は自己情報量 $-\log q(x)$ です。これは「確率 $q(x)$ の事象が起きたときの驚きの大きさ」を表します。めったに起きない事象($q$ が小さい)ほど、起きたときの驚き(情報量)は大きい、という直感です。

この自己情報量を、真の分布 $p$ で平均したものがエントロピー $H(p) = -\sum_k p_k \log p_k$ です。そして、真の分布 $p$ のもとで、予測分布 $q$ の自己情報量を平均したものが交差エントロピー $H(p,q) = -\sum_k p_k \log q_k$ になります。

情報理論で見る交差エントロピー

図のように、これらは一本の線でつながっています。交差エントロピー $H(p,q)$ とエントロピー $H(p)$ の差が、KLダイバージェンス $D_{\mathrm{KL}}(p\|q) = H(p,q) – H(p) \geq 0$ です。KLダイバージェンスは「予測分布 $q$ が真の分布 $p$ からどれだけ離れているか」を測る量で、常に非負です。

ここから重要な事実が導けます。分類問題では真の分布 $p$(=one-hotの正解ラベル)は固定なので、$H(p)$ は定数です。したがって、

$$ \underbrace{H(p,q)}_{\text{交差エントロピー}} = \underbrace{H(p)}_{\text{定数}} + \underbrace{D_{\mathrm{KL}}(p\|q)}_{\text{最小化したい}} $$

となり、交差エントロピーを最小化することは、KLダイバージェンスを最小化すること(=予測分布を真の分布に近づけること)と等価なのです。

交差エントロピーはq=pで最小

図は、真の分布を $p=0.7$ に固定して予測 $q$ を動かしたときの交差エントロピー $H(p,q)$ です。$q=p=0.7$ のときに最小値をとり、その最小値はエントロピー $H(p)$ に一致します(差がKLダイバージェンス)。「予測を真の分布に合わせると交差エントロピーが最小になる」ことが視覚的に確認できます。

最尤推定との関係

交差エントロピーは、統計学の最尤推定とも一致します。$N$ 個のデータに対するモデルの尤度(正解クラスに与えた確率の積)は $\prod_{n=1}^{N} y_{c_n}$ で、その対数をとって符号を反転した負の対数尤度は

$$ -\log \prod_{n=1}^{N} y_{c_n} = -\sum_{n=1}^{N} \log y_{c_n} = \sum_{n=1}^{N} \mathrm{Loss}_n $$

となり、各データの交差エントロピーの和そのものです。つまり、交差エントロピーを最小化する=尤度を最大化する(最尤推定)ことになります。情報理論・確率論・最尤推定という別々の入り口が、すべて同じ損失にたどり着くのは美しいところです。

ソフトマックスとの組み合わせ

実際の分類ネットワークでは、出力層の生の値(ロジット $\bm{z}$、正負を取る実数)を、まずソフトマックス関数で確率分布に変換してから交差エントロピーに渡します。

$$ \begin{equation} y_i = \mathrm{softmax}(\bm{z})_i = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}} \end{equation} $$

ソフトマックス

図のように、ソフトマックスはロジット(左:正負の実数)を、合計が $1$ になる確率分布(右)に変換します。大きいロジットほど大きな確率になり、指数関数を使うため差が強調されます。こうして得た確率 $\bm{y}$ を交差エントロピーに入れることで、分類の損失が完成します。

勾配が「予測 − 正解」になる美しさ

ソフトマックスと交差エントロピーを組み合わせる最大の利点は、ロジットに関する勾配が驚くほど単純になることです。結論を先に書くと、

$$ \begin{equation} \frac{\partial L}{\partial z_i} = y_i – t_i \qquad (\text{予測確率} – \text{正解}) \end{equation} $$

です。導出してみましょう。$L = -\sum_k t_k \log y_k$ で、$y_k = \mathrm{softmax}(\bm{z})_k$ です。ソフトマックスの微分 $\dfrac{\partial y_k}{\partial z_i} = y_k(\delta_{ik} – y_i)$($\delta_{ik}$ はクロネッカーのデルタ)を使うと、

$$ \frac{\partial L}{\partial z_i} = -\sum_k \frac{t_k}{y_k}\frac{\partial y_k}{\partial z_i} = -\sum_k t_k (\delta_{ik} – y_i) $$

ここで和を2つに分けます。第1項は $-\sum_k t_k \delta_{ik} = -t_i$、第2項は $y_i \sum_k t_k = y_i$($\bm{t}$ はone-hotなので $\sum_k t_k = 1$)です。よって

$$ \frac{\partial L}{\partial z_i} = -t_i + y_i = y_i – t_i $$

が得られます。

Softmax+CEの勾配=予測−正解

図のように、ソフトマックスと交差エントロピーという複雑な合成関数なのに、勾配は「予測確率と正解の差」というシンプルな形になります。これは実装が容易なだけでなく、誤差逆伝播が数値的に安定するという実用上の大きな利点をもたらします。

なぜ分類では二乗誤差ではなく交差エントロピーか

「損失なら二乗誤差でもいいのでは?」と思うかもしれません。しかし分類では、二乗誤差を使うと学習が遅くなるという致命的な問題があります。

二乗誤差と交差エントロピーの勾配比較

図は、正解 $y=1$ に対して、ロジット $z$ を横軸にとったときの勾配の大きさです。二値分類で出力をシグモイド $\sigma(z)$ とすると、二乗誤差の勾配は $\propto (\sigma(z)-1)\sigma(z)(1-\sigma(z))$ で、大きく外している($z$ が小さく $\sigma \to 0$)ときに勾配がほぼゼロになってしまいます。これは「一番直したい大外れの状態」で学習が止まる、という最悪の挙動です(勾配消失)。

一方、交差エントロピーの勾配は $\sigma(z) – 1$ で、大外れのときも勾配が $-1$ に近く消えません。つまり、間違っているほど大きく修正がかかります。この「外れているほど強く学習する」性質こそ、分類で交差エントロピーが選ばれる決定的な理由です。

Pythonで実装する

ソフトマックスと交差エントロピー、そしてその勾配をNumPyでスクラッチ実装し、勾配の公式が正しいことを数値微分で確認します。

import numpy as np

def softmax(z):
    z = z - z.max()              # オーバーフロー対策
    e = np.exp(z)
    return e / e.sum()

def cross_entropy(y, t):
    eps = 1e-12                  # log(0)対策
    return -np.sum(t * np.log(y + eps))

# 3クラスの例:正解は「猫」(クラス0)
z = np.array([2.0, 0.5, -1.0])   # ロジット
t = np.array([1.0, 0.0, 0.0])    # 正解 (one-hot)

y = softmax(z)
loss = cross_entropy(y, t)
print("予測確率:", y.round(3))
print("損失:", round(loss, 4))

# --- 勾配が y - t になることを数値微分で確認 ---
grad_analytic = y - t            # 解析的な勾配
grad_numeric = np.zeros_like(z)
h = 1e-5
for i in range(len(z)):
    zp, zm = z.copy(), z.copy()
    zp[i] += h; zm[i] -= h
    grad_numeric[i] = (cross_entropy(softmax(zp), t)
                       - cross_entropy(softmax(zm), t)) / (2 * h)

print("解析的な勾配 (y - t):", grad_analytic.round(4))
print("数値微分による勾配:    ", grad_numeric.round(4))
print("最大誤差:", np.max(np.abs(grad_analytic - grad_numeric)))

実行すると、解析的な勾配 $\bm{y}-\bm{t}$ と数値微分の結果が小数点以下5桁レベルで一致し(最大誤差は約 $10^{-12}$)、先ほど導出した勾配の公式が正しいことが確認できます。予測確率は約 $[0.79, 0.18, 0.04]$、損失は約 $0.24$ となります。

PyTorchを使えば、ソフトマックスと交差エントロピーがひとまとめになった nn.CrossEntropyLoss を呼ぶだけです(入力はロジット、内部でソフトマックスが適用されます)。

import torch
import torch.nn as nn

z = torch.tensor([[2.0, 0.5, -1.0]])   # ロジット (バッチ1, 3クラス)
t = torch.tensor([0])                   # 正解クラスのインデックス

loss_fn = nn.CrossEntropyLoss()
loss = loss_fn(z, t)
print("PyTorchの損失:", round(loss.item(), 4))   # NumPy実装と一致する

nn.CrossEntropyLoss がロジットを直接受け取るのは、ソフトマックスと交差エントロピーを別々に計算するより、まとめて計算したほうが数値的に安定する(log-sum-expトリック)ためです。

多クラスの数値例

最後に、3クラス分類の具体例で損失計算を確認しましょう。

多クラスの数値例

図のように、正解が「猫」(one-hot $[1,0,0]$)で、モデルの予測確率が $[0.7, 0.2, 0.1]$ だったとします。交差エントロピーは正解クラスの項だけ残るので、

$$ \mathrm{Loss} = -\log(0.7) \approx 0.357 $$

となります。もし予測が $[0.99, 0.005, 0.005]$ と正解に強い自信を持てば損失は $-\log(0.99) \approx 0.01$ とほぼゼロに、逆に $[0.1, 0.5, 0.4]$ と正解を軽視すれば $-\log(0.1) \approx 2.30$ と大きくなります。「正解クラスにどれだけ確率を割り当てたか」だけで損失が決まる、というシンプルさが改めて確認できます。

BCE と多クラス CE:式と違いを整理する

これまで多クラス交差エントロピーと二値交差エントロピーが混在して登場しました。ここで2つの関係を横並びにして整理しましょう。

多クラス交差エントロピー(Categorical CE)

クラス数が $K \geq 2$ の場合。ネットワーク出力をソフトマックスで確率に変換したあと使います。

$$ \begin{equation} L_{\text{cat}} = -\sum_{k=1}^{K} t_k \log y_k \qquad \Bigl( y_k = \mathrm{softmax}(\bm{z})_k,\; \sum_k t_k = 1 \Bigr) \end{equation} $$

正解ラベルは one-hot なので、和の中で生き残るのは正解クラスの1項だけです。PyTorchでは nn.CrossEntropyLoss がロジット $\bm{z}$ をそのまま受け取り、内部でソフトマックスと対数計算を一括処理します。

二値交差エントロピー(Binary CE / BCE)

クラス数が $K=2$(正例・負例のみ)の場合。シグモイド $\sigma$ で確率 $p$ を得てから使います。

$$ \begin{equation} L_{\text{bce}} = -\bigl[\, y \log p + (1-y)\log(1-p) \,\bigr] \qquad \bigl( p = \sigma(z) \bigr) \end{equation} $$

$y=1$ なら $-\log p$、$y=0$ なら $-\log(1-p)$ だけが残り、正解方向に確率を寄せるほど損失が小さくなります。PyTorchでは nn.BCEWithLogitsLoss がロジットを直接受け取ります(内部でシグモイドを計算)。

2つの使い分け

多クラス CE BCE
クラス数 $K \geq 2$(通常 $K > 2$) 2(正例/負例)
出力変換 ソフトマックス シグモイド
1サンプルあたりの出力次元 $K$ 次元 スカラー
PyTorch nn.CrossEntropyLoss(ロジット入力) nn.BCEWithLogitsLoss(ロジット入力)
典型用途 画像分類・言語モデルのトークン予測 スパム判定・医療診断(陽性/陰性)

多クラス CE は「$K$ 個のクラスのどれか1つを選ぶ」問題、BCE は「各サンプルが条件を満たすか否か」を問う問題に向いています。マルチラベル分類(1つのサンプルが複数ラベルを持つ)では、ラベルごとに独立に BCE を計算するのが定石です。

次のセクションでは、2つの損失に共通する「なぜ分類で MSE を使わないのか」を掘り下げます。

分類問題でなぜ MSE ではなく交差エントロピーなのか

「損失関数ならどれでも同じでは?」——これは合理的な疑問です。回帰では二乗誤差(MSE)が当然のように使われます。しかし分類タスクでシグモイドや softmax と MSE を組み合わせると、「大外れの状態で学習が止まる」 という致命的な問題が起きます。

シグモイド + MSE の勾配消失

二値分類で出力に $p = \sigma(z)$(シグモイド)を使い、MSE 損失 $L_{\text{MSE}} = \frac{1}{2}(p – y)^2$ を採用した場合を考えます。チェーンルールを適用すると

$$ \frac{\partial L_{\text{MSE}}}{\partial z} = (p – y) \cdot \sigma'(z) = (p – y) \cdot p(1-p) $$

シグモイド $p = \sigma(z)$ は $z \to \pm\infty$ で $0$ か $1$ に飽和し、$\sigma'(z) = p(1-p) \to 0$ になります。つまり正解が $y=1$ なのにモデルが $p \approx 0$(大外れ)を出している状況——最も修正すべき状態——で勾配がほぼゼロになってしまいます。

$$ \underbrace{(p – y)}_{\approx -1} \cdot \underbrace{p(1-p)}_{\approx 0} \approx 0 $$

BCE の勾配は消えない

一方、BCE 損失 $L_{\text{bce}} = -[y\log p + (1-y)\log(1-p)]$ の勾配は

$$ \frac{\partial L_{\text{bce}}}{\partial z} = p – y $$

これだけです。$\log$ とシグモイドの掛け合わせが綺麗にキャンセルし、$\sigma'(z)$ の飽和項が現れません。正解 $y=1$ でモデルが $p \approx 0$ を出している場合、勾配は $0 – 1 = -1$ と最大値を取ります。大きく外しているほど大きな勾配で修正がかかる、という理想的な性質です。

数値で確認する

import numpy as np

def sigmoid(z):
    return 1 / (1 + np.exp(-np.clip(z, -500, 500)))

# 正解 y=1 のときの勾配(絶対値)を3点で比較
for z in [-4, 0, 4]:
    p = sigmoid(z)
    grad_mse = abs((p - 1) * p * (1 - p))   # MSE + sigmoid の勾配
    grad_ce  = abs(p - 1)                     # BCE + sigmoid の勾配
    print(f"z={z:+d} (p={p:.4f}): MSE grad={grad_mse:.5f},  CE grad={grad_ce:.5f}")

実行すると以下のような結果が得られます。

z=-4 (p=0.0180): MSE grad=0.01735,  CE grad=0.98201
z=+0 (p=0.5000): MSE grad=0.12500,  CE grad=0.50000
z=+4 (p=0.9820): MSE grad=0.00032,  CE grad=0.01799

$z=-4$(大外れ)では MSE の勾配が $0.017$ しかないのに対し、CE の勾配は $0.98$ と約56倍大きい。$z=+4$(ほぼ正解)では両方とも小さな勾配となり、収束を妨げない。この非対称性こそ、分類で交差エントロピーが選ばれる決定的な理由です。大きく外したときに強く修正し、正解に近づくにつれて修正を弱める——この「比例した修正力」がモデルを効率的に学習へ導きます。

ソフトマックス + 交差エントロピーの勾配を1行ずつ導出する

既存の「勾配が予測 − 正解になる美しさ」セクションでは結論を示しました。ここでは証明の各ステップを丁寧に追います。

設定

  • ロジット: $\bm{z} = (z_1, \dots, z_K)$
  • ソフトマックス出力: $y_k = \dfrac{e^{z_k}}{\sum_j e^{z_j}}$
  • 損失: $L = -\sum_k t_k \log y_k$($\bm{t}$ は one-hot、$\sum_k t_k = 1$)
  • 求めたいもの: $\dfrac{\partial L}{\partial z_i}$

ステップ1: チェーンルールを展開する

$$ \frac{\partial L}{\partial z_i} = -\sum_{k=1}^{K} \frac{t_k}{y_k} \cdot \frac{\partial y_k}{\partial z_i} $$

$y_k$ は $z_i$ を通じて変化するので、まず $\dfrac{\partial y_k}{\partial z_i}$ を求めます。

ステップ2: ソフトマックスの偏微分

$k = i$ と $k \neq i$ で場合分けします。

$k = i$ のとき(クオーシェントルールを適用):

$$ \frac{\partial y_i}{\partial z_i} = \frac{e^{z_i} \cdot S – e^{z_i} \cdot e^{z_i}}{S^2} = y_i – y_i^2 = y_i(1 – y_i) $$

ここで $S = \sum_j e^{z_j}$ と置きました。

$k \neq i$ のとき:

$$ \frac{\partial y_k}{\partial z_i} = \frac{0 \cdot S – e^{z_k} \cdot e^{z_i}}{S^2} = -y_k y_i $$

これをクロネッカーのデルタ $\delta_{ik}$($k=i$ なら $1$、それ以外は $0$)を使ってまとめると

$$ \frac{\partial y_k}{\partial z_i} = y_k(\delta_{ik} – y_i) $$

ステップ3: 代入して整理する

ステップ2の結果をステップ1に代入します。

$$ \frac{\partial L}{\partial z_i} = -\sum_{k=1}^{K} \frac{t_k}{y_k} \cdot y_k(\delta_{ik} – y_i) $$

$y_k$ をキャンセルすると

$$ = -\sum_{k=1}^{K} t_k (\delta_{ik} – y_i) $$

$\delta_{ik}$ を含む項と $y_i$ を含む項に分けます。

$$ = -\sum_{k=1}^{K} t_k \delta_{ik} + y_i \sum_{k=1}^{K} t_k $$

ステップ4: 最終結果

  • 第1項: $\sum_k t_k \delta_{ik} = t_i$($\delta_{ik}$ は $k=i$ のときだけ $1$)
  • 第2項: $\sum_k t_k = 1$(one-hot の和は $1$)

したがって

$$ \begin{equation} \frac{\partial L}{\partial z_i} = -t_i + y_i \cdot 1 = y_i – t_i \end{equation} $$

ソフトマックスの微分で生まれる複雑な項が互いに打ち消し合い、「予測確率 $-$ 正解ラベル」という透明な形に収束します。これがバックプロパゲーションを実装する際の計算効率と数値安定性にも貢献しています。

数値安定化:log-sum-exp と PyTorch がロジットを受け取る理由

log(0) の問題

ソフトマックスと交差エントロピーを素朴に実装すると $\log(y_k)$ の計算で問題が起きます。予測確率が非常に小さいとき、$y_k \approx 0$ となり $\log y_k \to -\infty$ で数値が壊れます。また、ロジット $z_k$ が大きいと $e^{z_k}$ がオーバーフローします。

log-sum-exp トリック

定数 $c$ を引いてもソフトマックスの値は変わりません。

$$ \mathrm{softmax}(z_k) = \frac{e^{z_k – c}}{\sum_j e^{z_j – c}} $$

$c = \max_j z_j$ を選ぶことで、指数の最大値が $e^0 = 1$ に抑えられ、オーバーフローを防げます。

ソフトマックス + CE を融合すると

ソフトマックスと対数を融合させると

$$ \log y_k = z_k – \log \sum_j e^{z_j} $$

この $\log \sum_j e^{z_j}$ の安定計算が log-sum-exp です。

$$ \log \sum_j e^{z_j} = c + \log \sum_j e^{z_j – c} \qquad (c = \max_j z_j) $$

one-hot の正解クラスを $c_{\text{ans}}$ とすると $\sum_k t_k z_k = z_{c_{\text{ans}}}$(正解クラスのロジット)なので

$$ L = -z_{c_{\text{ans}}} + c + \log \sum_j e^{z_j – c} $$

全ての計算がロジットのみで完結します。

数値確認

import numpy as np

# 大きなロジットで素朴な計算を試みる
z_large = np.array([1000.0, 1001.0, 1002.0])
naive_lse = np.log(np.sum(np.exp(z_large)))   # オーバーフローで inf
print(f"naive log-sum-exp: {naive_lse}")       # inf

# log-sum-exp トリック(c = max)
c = z_large.max()  # 1002.0
stable_lse = c + np.log(np.sum(np.exp(z_large - c)))
print(f"stable log-sum-exp: {stable_lse:.6f}")  # 1002.407606

# 小さい値でも一致することを確認
z_normal = np.array([1.0, 2.0, 3.0])
c2     = z_normal.max()
naive  = np.log(np.sum(np.exp(z_normal)))
stable = c2 + np.log(np.sum(np.exp(z_normal - c2)))
print(f"z=[1,2,3]: naive={naive:.6f}, stable={stable:.6f}")  # 同じ値

naive log-sum-exp: inf となる場合も、log-sum-exp トリックなら 1002.407606 と正確な値を返します。z=[1,2,3] でも両方 3.407606 と一致し、安定性が確認できます。PyTorch の nn.CrossEntropyLoss はロジットを直接受け取り、この融合計算を内部で行います。自前でソフトマックスを計算してから nn.NLLLoss に渡すのは、精度の悪化と数値不安定のリスクがあるため推奨されません。

ラベルスムージング:過信への罰則

過信のリスク

one-hot ラベルで交差エントロピーを最小化すると、モデルは正解クラスの確率を $1.0$ に近づけることを目指します。これは合理的ですが、訓練データが少ない場合や分布外データでは、過信(overconfidence) が問題になります。正解クラスに $99\%$ を付けるモデルが、テストデータに対しても根拠なく高確信を示し続けてしまいます。

ラベルスムージングの仕組み

ラベルスムージングは、one-hot ターゲットの代わりに わずかに均一化したターゲット を使う正則化手法です。パラメータ $\varepsilon$(典型値 $0.1$)を使って

$$ \tilde{t}_k = (1 – \varepsilon)\, t_k + \frac{\varepsilon}{K} $$

正解クラスの確率は $1$ から $1 – \varepsilon + \varepsilon/K$ に下がり、不正解クラスには $\varepsilon/K$ の微小確率が割り当てられます。

数値で確認する

import numpy as np

K   = 3      # クラス数
eps = 0.1    # スムージング係数
t_onehot = np.array([1.0, 0.0, 0.0])
t_smooth  = (1 - eps) * t_onehot + eps / K

print(f"one-hot:  {t_onehot}")
print(f"smoothed: {t_smooth.round(4)}")
# → [0.9333, 0.0333, 0.0333]

# 高確信度の予測(正解クラスに 0.9)
y_conf  = np.array([0.9, 0.07, 0.03])
lh = -np.sum(t_onehot * np.log(y_conf + 1e-12))
ls = -np.sum(t_smooth  * np.log(y_conf + 1e-12))
print(f"\n高確信度予測の損失: Hard CE={lh:.4f},  Smooth CE={ls:.4f}")
# Hard CE=0.1054,  Smooth CE=0.3039  ← 過信にペナルティ

# 低確信度の予測(正解クラスに 0.4)
y_unc   = np.array([0.4, 0.35, 0.25])
lh2 = -np.sum(t_onehot * np.log(y_unc + 1e-12))
ls2 = -np.sum(t_smooth  * np.log(y_unc + 1e-12))
print(f"低確信度予測の損失: Hard CE={lh2:.4f},  Smooth CE={ls2:.4f}")
# Hard CE=0.9163,  Smooth CE=0.9364  ← 差は小さい

高確信度の予測に対して Hard CE は $0.105$ と低いのに、Smooth CE は $0.304$ と約3倍の損失をかけます。「$100\%$ 確信に近づくほどペナルティ増大」という正則化効果です。低確信度の予測ではその差が小さく、まだ学習が進む余地があることを示しています。ラベルスムージングは画像認識(ImageNet 訓練)や翻訳(Attention is All You Need 原著でも $\varepsilon=0.1$ を使用)で標準的に使われており、PyTorch では nn.CrossEntropyLoss(label_smoothing=0.1) で有効化できます。

PyTorch の nn.CrossEntropyLoss を正しく使う

ロジットを渡す

最も重要な注意点は ロジット(softmax 前の生の出力)を渡すことです。

import torch
import torch.nn as nn
import torch.nn.functional as F

# バッチサイズ2、クラス数3の例
z = torch.tensor([[2.0, 0.5, -1.0],   # サンプル1のロジット
                   [0.1, 3.0,  1.2]])  # サンプル2のロジット
t = torch.tensor([0, 1])              # 正解クラスのインデックス(0-indexed)

loss_fn = nn.CrossEntropyLoss()
loss = loss_fn(z, t)
print(f"CrossEntropyLoss: {loss.item():.4f}")
# → 内部で log-sum-exp を使い、数値安定な損失を計算

# log_softmax + NLLLoss(CrossEntropyLoss と等価)
loss_ok = nn.NLLLoss()(F.log_softmax(z, dim=1), t)
print(f"log_softmax + NLL: {loss_ok.item():.4f}")  # 同じ値

# ラベルスムージングの有効化
loss_fn_ls = nn.CrossEntropyLoss(label_smoothing=0.1)
loss_ls = loss_fn_ls(z, t)
print(f"ラベルスムージング有り: {loss_ls.item():.4f}")  # 通常より大きい値

# クラス不均衡への重み付き損失
class_weights = torch.tensor([0.2, 2.0, 0.8])   # 少数クラス1に大きい重み
loss_fn_w = nn.CrossEntropyLoss(weight=class_weights)
loss_w = loss_fn_w(z, t)
print(f"重み付き損失: {loss_w.item():.4f}")

CrossEntropyLoss と log_softmax + NLLLoss は完全に一致します。ラベルスムージング有りの損失は通常より大きく(過信ペナルティ)、重み付き損失は少数クラスの誤りをより重視します。ソフトマックスを手動で計算してから BCELoss に渡すのは数値精度が落ちるアンチパターンです。ロジット入力の設計は「数値精度・実装簡潔さ・拡張性」の三点で優れています。

まとめ

交差エントロピー誤差を、定義から情報理論・勾配・実装まで通して解説しました。

  • 定義: $-\sum_k t_k \log y_k$。one-hotの正解ラベルにより、実質は正解クラスの $-\log y_c$ だけ。正解に自信を持つほど損失が小さく、外すほど大きい。
  • BCE と多クラス CE: BCEは2クラス×シグモイド、多クラスCEはKクラス×ソフトマックス。マルチラベル分類にはBCEを変量ごとに適用する。
  • 分類で MSE を使わない理由: シグモイド+MSEの勾配は飽和領域(大外れ)でほぼゼロになる。CEの勾配は $p – y$ で飽和しない。
  • 勾配の導出: ソフトマックスの偏微分 $y_k(\delta_{ik}-y_i)$ を代入してチェーンルールを展開すると $\partial L/\partial z_i = y_i – t_i$ に帰着する。
  • 情報理論: 交差エントロピー $H(p,q)$ はエントロピー $H(p)$ とKLダイバージェンスの和。正解分布が固定なら、交差エントロピー最小化=KL最小化=予測を真の分布に近づけること。
  • 最尤推定: 交差エントロピーの最小化は、負の対数尤度の最小化(最尤推定)と等価。
  • 数値安定化: log-sum-exp トリックでオーバーフロー・log(0) を回避。PyTorchの nn.CrossEntropyLoss はロジット入力でこれを内部実装している。
  • ラベルスムージング: one-hot の代わりに $\tilde{t}_k = (1-\varepsilon)t_k + \varepsilon/K$ を使い、過信を正則化。label_smoothing=0.1 で有効化。

分類タスクで交差エントロピーが「ほぼ一択」で使われるのは、これだけの良い性質が一つの損失にまとまっているからです。

画像なし
ソフトマックス関数の理論と実装
ソフトマックスの定義・数値安定化・勾配まで丁寧に解説
KLダイバージェンス
確率分布間の距離・交差エントロピーとの関係を情報理論から解説