クラス不均衡問題に対処するために Cross-Entropy Loss を改良した損失関数。簡単なサンプル(高確信度の正解予測)の損失重みを下げ、難しいサンプル(低確信度の予測)に学習を集中させる。物体検出の RetinaNet で提案され、LLM のトークンレベル学習やクラス不均衡なテキスト分類でも効果を発揮する。
Focal Loss は 2017 年に Meta AI(当時 Facebook AI Research)の Tsung-Yi Lin らが RetinaNet 論文で提案した損失関数である。従来の Cross-Entropy Loss に (1 - p_t)^γ という変調係数を掛けることで、正しく分類できているサンプル(p_t が高い)の損失寄与を抑え、誤分類されやすいサンプルに学習を集中させる。
FL(p_t) = -α_t * (1 - p_t)^γ * log(p_t)
γ=2.0 の場合、p_t=0.9(確信度 90%)のサンプルの損失は Cross-Entropy の 1/100 に低下。p_t=0.5(確信度 50%)では約 1/4 にしか低下せず、難しいサンプルに学習リソースが集中する。
| γ 値 | p_t=0.9 の重み | p_t=0.5 の重み | 用途 |
|---|---|---|---|
| 0 | 1.0 | 1.0 | Cross-Entropy と同一 |
| 1 | 0.1 | 0.5 | 軽い補正 |
| 2 | 0.01 | 0.25 | 標準設定 |
| 3 | 0.001 | 0.125 | 強い補正 |
| 5 | 0.00001 | 0.031 | 極端な不均衡向け |
RetinaNet が Focal Loss で達成した成果:
Focal Loss は元々画像認識向けだが、テキスト処理でも有効:
# PyTorch での Focal Loss 実装
class FocalLoss(nn.Module):
def __init__(self, gamma=2.0, alpha=0.25):
super().__init__()
self.gamma = gamma
self.alpha = alpha
def forward(self, logits, targets):
ce_loss = F.cross_entropy(logits, targets, reduction='none')
p_t = torch.exp(-ce_loss)
focal_weight = (1 - p_t) ** self.gamma
loss = self.alpha * focal_weight * ce_loss
return loss.mean()
Q1: γ=2 以外の値を使うべき場面はありますか? A: 不均衡が極端(正例 0.1% 未満)なら γ=3-5 が有効。逆に比較的バランスの取れたデータセット(正例 30%+)では γ=0.5-1.0 で十分。γ が大きすぎると難しすぎるノイズラベルにも過度に注力するため、ラベル品質が低い場合は γ を控えめにする。
Q2: Focal Loss と Class Weight の違いは? A: Class Weight はクラス全体に一律の重みを付与するのに対し、Focal Loss はサンプルごとの予測確信度に応じて動的に重みを調整する。両者の併用(α + γ)が最も効果的で、RetinaNet の標準設定もこの併用。
Q3: LLM の事前学習に Focal Loss は使われていますか? A: 2026 年現在、主要な LLM の事前学習では標準 Cross-Entropy が主流。ただし Focal Loss 的なトークン重み付け(高頻度トークンの重み削減)は研究レベルで効果が確認されており、今後の採用が期待される。SFT フェーズでは不均衡な指示分布への対処として使用例がある。