PyTorch torch.nn.CrossEntropyLoss 関数

PyTorch torch.nn 参考手册PyTorch torch.nn リファレンスマニュアル


torch.nn.CrossEntropyLossPyTorch で多クラス分類に使用される損失関数です。

nn.LogSoftmax と nn.NLLLoss を組み合わせたもので、画像分類やテキスト分類などのタスクでよく使用されます。

関数定義

torch.nn.CrossEntropyLoss(weight=None, ignore_index=-100, reduction='mean', label_smoothing=0.0)

パラメータの説明:

  • weight(Tensor): 各クラスに異なる重みを割り当て、クラスの不均衡な場合に使用します。
  • ignore_index(int): 指定したインデックスの損失計算を無視します。デフォルトは -100 です。
  • reduction(str): 損失の集約方法。選択可能'mean'、'sum'、'none'。デフォルトは'mean'。
  • label_smoothing(float): ラベル平滑化パラメータで、0 から 1 の間の値を取ります。デフォルトは 0 です。

数学的原理

交差エントロピー損失の式:

Loss = -log(exp(y_true) / sum(exp(y_i)))

つまり、正しいクラスの予測確率が大きいほど、損失は小さくなります。


使用例

例1: 基本的な使い方

交差エントロピー損失を作成して使用する:

実例

import torch
import torch.nn as nn

# 損失関数を作成
criterion = nn.CrossEntropyLoss()

# モデルが出力する logits(正規化前)
# 形状: (batch_size, num_classes)
outputs = torch.randn(4, 10)

# 実際のラベル
labels = torch.tensor([2, 5, 1, 7])

# 損失を計算
loss = criterion(outputs, labels)

print("モデル出力 (logits):", outputs[0].tolist())
print("実際のラベル:", labels[0].item())
print("交差エントロピー損失:", loss.item())

例2: クラスの重み

クラスの不均衡を処理する:

実例

import torch
import torch.nn as nn

# クラスの重み:少数クラスに高い重みを与える
# 10 個のクラスを想定し、3 番目と 7 番目のクラスがより重要
weight = torch.ones(10)
weight[3] = 2.0
weight[7] = 2.0

criterion_weighted = nn.CrossEntropyLoss(weight=weight)

outputs = torch.randn(4, 10)
labels = torch.tensor([2, 3, 7, 5])

loss = criterion_weighted(outputs, labels)
print("重み付き交差エントロピー損失:", loss.item())

例3: ラベル平滑化

ラベル平滑化を使用して過学習を防ぐ:

実例

import torch
import torch.nn as nn

# ラベル平滑化:0.1 は 10% の確率を他のクラスに均等に分配することを意味します
criterion_smooth = nn.CrossEntropyLoss(label_smoothing=0.1)

outputs = torch.randn(4, 10)
labels = torch.tensor([2, 5, 1, 7])

loss = criterion_smooth(outputs, labels)
print("ラベル平滑化ありの損失:", loss.item())

# 比較:ラベル平滑化なし
criterion = nn.CrossEntropyLoss()
loss_no_smooth = criterion(outputs, labels)
print("ラベル平滑化なしの損失:", loss_no_smooth.item())

例4: 完全な分類トレーニングフロー

完全なモデルトレーニングの例:

実例

import torch
import torch.nn as nn
import torch.optim as optim

# シンプルな分類モデル
class Classifier(nn.Module):
    def __init__(self, input_dim=784, num_classes=10):
        super(Classifier, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(input_dim, 256),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(256, num_classes)
        )

    def forward(self, x):
        return self.fc(x)

# モデルと損失を初期化
model = Classifier()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# トレーニングデータを模擬
batch_size = 32
x = torch.randn(batch_size, 784)  # 入力
y = torch.randint(0, 10, (batch_size,))  # ラベル

# 順伝播
model.train()
outputs = model(x)
loss = criterion(outputs, y)

# 逆伝播
optimizer.zero_grad()
loss.backward()
optimizer.step()

print("バッチ損失:", loss.item())

# 予測
model.eval()
with torch.no_grad():
    outputs = model(x)
    predictions = outputs.argmax(dim=1)
    accuracy = (predictions == y).float().mean()

print("予測精度:", accuracy.item())

例5: ignore_index の使用

特定のラベルを無視する:

実例

import torch
import torch.nn as nn

# label=-100 のサンプルを無視
criterion = nn.CrossEntropyLoss(ignore_index=-100)

outputs = torch.randn(5, 10)
# 一部のサンプルのラベルが -100 の場合、無視を意味します
labels = torch.tensor([2, -100, 5, -100, 7])

loss = criterion(outputs, labels)
print("特殊なラベルを無視した後の損失:", loss.item())

例6: 異なる reduction 方法

損失の集約方法を制御する:

実例

import torch
import torch.nn as nn

outputs = torch.randn(4, 10)
labels = torch.tensor([2, 5, 1, 7])

# mean: 平均損失を返す
loss_mean = nn.CrossEntropyLoss(reduction='mean')(outputs, labels)
print("mean:", loss_mean.item())

# sum: 合計を返す
loss_sum = nn.CrossEntropyLoss(reduction='sum')(outputs, labels)
print("sum:", loss_sum.item())

# none: 各サンプルの損失を返す
loss_none = nn.CrossEntropyLoss(reduction='none')(outputs, labels)
print("none:", loss_none.tolist())

よくある質問

Q1: CrossEntropyLoss と NLLLoss の違いは何ですか?

CrossEntropyLoss = LogSoftmax + NLLLoss です。softmax が組み込まれているため、手動で追加する必要はありません。

Q2: モデルの出力に softmax を使わないのはなぜですか?

CrossEntropyLoss は内部で自動的に softmax を計算するため、logits を直接使用することで数値的安定性が向上します。

Q3: ラベル平滑化はどのような場面に適していますか?

ラベル平滑化はクラス数が多い場合に適しており、モデルの汎化能力を向上させることができます。


使用シーン

nn.CrossEntropyLoss主な適用シーンは次のとおりです:

  • 画像分類: CIFAR-10、ImageNet など
  • テキスト分類: 感情分析、トピック分類
  • 多クラス分類タスク: クラス数が 2 より大きい分類タスク

注意:ラベルはクラスインデックス(0 から num_classes-1)である必要があり、one-hot エンコーディングではありません。


PyTorch torch.nn 参考手册PyTorch torch.nn リファレンスマニュアル

その他の拡張