手計算交差エントロピー損失
「当てずっぽう」から「非常に自信がある」までの予測系列を構築し、交差エントロピー値がそれに伴ってどのように下がるかを観察します。
このケースを学び終えると、以下のことを理解できます:なぜ分類タスクではMSEではなく交差エントロピーを使うのか——MSEよりも「厳しく」自信はあるが間違った予測を罰するからです。
生活からの導入
試験の採点——間違って答えることは、答えないことよりも悪い
2人の学生が単一選択問題(答えはA)に答えます。小红はAの確率を0.5と予測(不確実だが方向は正しい)、小明はCの確率を0.95と予測(非常に自信を持って間違った)。小红は不確実だが方向は正しく、小明は間違っている上に非常に自信がある——このような誤りはさらに許しがたいものです。
交差エントロピー損失はこの採点基準のようなものです:予測が正しいときは自信を評価し、予測が間違っているときは自信を罰します。
直感的理解
正解ラベルは「猫」(one-hot = [1, 0, 0])です。モデルの出力を「当てずっぽう」から「訓練がだんだん正確になる」までシミュレーションします:
- 完全に当てずっぽう [0.33, 0.33, 0.34] → 損失 1.10
- 非常に自信があり正しい [0.98, 0.01, 0.01] → 損失 0.02
- 非常に自信があるが間違い [0.02, 0.9, 0.08] → 損失 3.91(当てずっぽうの約4倍!)
最後の数値に注目してください:-log(0.02) ≈ 3.91 であり、-log(0.33) ≈ 1.10 だからです。
数学的定義
\[ H(p, q) = -\sum_{i=1}^{C} p_i \cdot \log(q_i) \]\(p\) は真の分布(one-hot)、\(q\) は予測分布です。「自信はあるが間違い」の予測では、交差エントロピー = -log(0.02) ≈ 3.91、MSE = (1-0.02)^2 ≈ 0.96。交差エントロピーのペナルティはMSEの12倍です。
Python 実践
実例
import numpy as np
def cross_entropy(p_true, q_pred, eps=1e-12):
q_pred = np.clip(q_pred, eps, 1 - eps)
return -np.sum(p_true * np.log(q_pred))
# 正解ラベル:猫 (第0クラス)
p_true = np.array([1, 0, 0]) # [猫, 犬, 鳥]
predictions = {
"完全に当てずっぽう (一様)": np.array([0.33, 0.33, 0.34]),
"少し感覚がある": np.array([0.5, 0.3, 0.2]),
"だんだん正確になる": np.array([0.7, 0.2, 0.1]),
"訓練が良好": np.array([0.9, 0.07, 0.03]),
"非常に自信があり正しい": np.array([0.98, 0.01, 0.01]),
"非常に自信があるが間違い!": np.array([0.02, 0.9, 0.08]),
}
print("サンプル 交差エントロピー損失の比較 (正解: 猫=[1,0,0])\n")
print(f"{'予測説明':<20} {'損失':<10} {'分析'}")
print("-" * 52)
for name, q in predictions.items():
loss = cross_entropy(p_true, q)
if loss > 2: analysis = "重大な誤り!"
elif loss > 0.5: analysis = "方向は正しいが不確実"
else: analysis = "良い"
print(f"{name:<20} {loss:<10.4f} {analysis}")
# MSE vs 交差エントロピーの比較
q_bad = predictions["非常に自信があるが間違い!"]
mse_bad = np.mean((p_true - q_bad) ** 2)
ce_bad = cross_entropy(p_true, q_bad)
print(f"\nサンプル 自信はあるが間違いのとき: MSE={mse_bad:.4f}, 交差エントロピー={ce_bad:.4f} (厳しさ {ce_bad/mse_bad:.0f}倍)")
def cross_entropy(p_true, q_pred, eps=1e-12):
q_pred = np.clip(q_pred, eps, 1 - eps)
return -np.sum(p_true * np.log(q_pred))
# 正解ラベル:猫 (第0クラス)
p_true = np.array([1, 0, 0]) # [猫, 犬, 鳥]
predictions = {
"完全に当てずっぽう (一様)": np.array([0.33, 0.33, 0.34]),
"少し感覚がある": np.array([0.5, 0.3, 0.2]),
"だんだん正確になる": np.array([0.7, 0.2, 0.1]),
"訓練が良好": np.array([0.9, 0.07, 0.03]),
"非常に自信があり正しい": np.array([0.98, 0.01, 0.01]),
"非常に自信があるが間違い!": np.array([0.02, 0.9, 0.08]),
}
print("サンプル 交差エントロピー損失の比較 (正解: 猫=[1,0,0])\n")
print(f"{'予測説明':<20} {'損失':<10} {'分析'}")
print("-" * 52)
for name, q in predictions.items():
loss = cross_entropy(p_true, q)
if loss > 2: analysis = "重大な誤り!"
elif loss > 0.5: analysis = "方向は正しいが不確実"
else: analysis = "良い"
print(f"{name:<20} {loss:<10.4f} {analysis}")
# MSE vs 交差エントロピーの比較
q_bad = predictions["非常に自信があるが間違い!"]
mse_bad = np.mean((p_true - q_bad) ** 2)
ce_bad = cross_entropy(p_true, q_bad)
print(f"\nサンプル 自信はあるが間違いのとき: MSE={mse_bad:.4f}, 交差エントロピー={ce_bad:.4f} (厳しさ {ce_bad/mse_bad:.0f}倍)")
サンプル 交叉熵损失对比 (真实: 猫=[1,0,0]) 预测描述 损失 分析 ---------------------------------------------------- 完全瞎猜 (均匀) 1.0986 方向对但不确定 有点感觉 0.6931 方向对但不确定 逐渐靠谱 0.3567 很好 训练较好 0.1054 很好 非常自信且正确 0.0202 很好 非常自信但错误! 3.9120 严重错误! サンプル 自信但错误时: MSE=0.3260, 交叉熵=3.9120 (严厉 12x)
AIにおける応用シーン
| シーン | 使用する損失関数 |
|---|---|
| 画像分類 | 多クラス交差エントロピー(CategoricalCrossEntropy) |
| 言語モデル | 各トークン位置の交差エントロピーの合計——GPT訓練の目的関数 |
| 知識蒸留 | 教師モデルのソフトラベルで交差エントロピーを計算する |