PyTorchのクロスエントロピー損失に少し混乱しています。
この例を考えてみましょう:
import torch
import torch.nn as nn
from torch.autograd import Variable
output = Variable(torch.FloatTensor([0,0,0,1])).view(1, -1)
target = Variable(torch.LongTensor([3]))
criterion = nn.CrossEntropyLoss()
loss = criterion(output, target)
print(loss)
損失は0になると予想しますが、次のようになります。
Variable containing:
0.7437
[torch.FloatTensor of size 1]
私の知る限り、クロスエントロピーは次のように計算できます。
しかし、結果は1 * log(1)= 0ではありませんか?
ワンホットエンコーディングなどのさまざまな入力を試しましたが、これはまったく機能しないため、損失関数の入力形状は問題ないようです。
誰かが私を助けて、私の間違いがどこにあるかを教えてくれたら本当に感謝しています。
前もって感謝します!
あなたの例では、出力[0,0,0,1]をクロスエントロピーの数学的定義で要求される確率として扱っています。しかし、PyTorchはそれらを出力として扱います。合計は1である必要はなく、softmax関数を使用する確率に最初に変換する必要があります。
H(p、q)は次のようになります。
H(p、softmax(output))
出力の変換[0,0,0,1]確率:
softmax([0,0,0,1] [0.1749,0.1749,0.1749,0.4754]) ==
そこから:
-log(0.4754 0.7437)==
あなたの理解は正しいですが、pytorchは cross entropy をそのように計算しません。 Pytorchは次の式を使用します。
loss(x, class) = -log(exp(x[class]) / (\sum_j exp(x[j])))
= -x[class] + log(\sum_j exp(x[j]))
あなたのシナリオでは、x = [0, 0, 0, 1]
およびclass = 3
、上記の式を評価すると、次の結果が得られます。
loss(x, class) = -1 + log(exp(0) + exp(0) + exp(0) + exp(1))
= 0.7437
Pytorchは自然対数を考慮します。
混乱を招くことが多いので、重要なメモを追加したいと思います。
Softmaxは損失関数ではありませんではなく、実際にアクティベーション関数でもありません。これには非常に具体的なタスクがあります。特定のクラスのスコアを正規化するマルチクラス分類に使用されます。そうすることで、合計が1となる各クラスの確率を取得します。
Softmaxはクロスエントロピー損失と組み合わされますモデルの損失を計算します。
残念ながら、この組み合わせは非常に一般的であるため、しばしば省略されます。 PyTorchがCross-Entropy-Lossのみと呼んでいるのに対し、一部はSoftmax-Lossという用語を使用しています。