1 L1Loss
創建一個標準來測量標準中每個元素之間的平均絕對誤差(MAE)輸入:math:x
和目標:math:y
where :math:N
is the batch size. If :attr:reduction
is not 'none'
(default 'mean'
)
import torch.nn as nn
import torch
lossfun=nn.L1Loss()
input=torch.randn(3,5,requires_grad=True)
print(input)
target=torch.randn(3,5)
print(target)
output=lossfun(input,target)
print(output)
輸出:
tensor([[ 0.7341, 0.8461, 0.4790, -0.9401, -0.4948],
[-0.2035, -0.9376, 1.4283, -0.6767, -0.8932],
[-0.7168, 0.5816, -0.7438, 0.7729, -1.3174]], requires_grad=True)
tensor([[ 0.5610, -0.6015, -1.0363, -0.8383, -0.7778],
[-0.3118, -0.0527, 1.6309, -0.1973, -0.9312],
[-0.2851, 1.9037, 0.1077, -0.2446, 0.4352]])
tensor(0.7073, grad_fn=<L1LossBackward>)
由此我們可以看出L1損失函數的輸入和輸出的維度是相同的,是直接使用兩個向量的對應的元素想減得到最後的誤差,例如 |x1-y1|。
2、NLLLoss
負對數似然損失。用C類訓練分類問題很有用。這裏的C是分類數目。
m=nn.LogSoftmax(dim=1)
loss=nn.NLLLoss()
input=torch.randn(3,5,requires_grad=True)
print(input)
target=torch.tensor([1,0,4])
print(m(input))
output=loss(m(input),target)
print(output)
輸出:
tensor([[-0.0511, 0.8704, -0.8625, -0.1377, 1.0202],
[ 0.7554, -0.1908, 0.2453, -0.0432, 1.4448],
[-0.3516, -0.2297, 0.1724, 0.3413, -1.3402]], requires_grad=True)
tensor([[-2.0533, -1.1318, -2.8647, -2.1399, -0.9820],
[-1.4887, -2.4349, -1.9988, -2.2872, -0.7992],
[-1.8230, -1.7010, -1.2990, -1.1300, -2.8115]],
grad_fn=<LogSoftmaxBackward>)
tensor(1.8107, grad_fn=<NllLossBackward>)
LogSoftmax就是輸入數據在softmax之後取一個對數,輸出的數值都在0~1之間,求的是一個概率。
NLLLoss的結果就是把上面的輸出與Label對應的那個值拿出來,再將取出的值去掉負號,再求均值。
注意以上的“與Label對應的那個值”指的是位置的對應,而不是數值上的接近。
如上的的標籤爲(1,0,4),就分別取出第一行的第二個數,第二行的第一個數,第三行的第五個數。即(1.1318+1.4887+2.8115)/3=1.8107。
3、PoissonNLLLoss
目標的泊松分佈具有負對數似然損失。
loss=nn.PoissonNLLLoss()
log_input=torch.randn(5,2,requires_grad=True)
print(log_input)
target=torch.randn(5,2)
print(target)
output=loss(log_input,target)
print(output)
輸出:
tensor([[ 1.1679, -0.0214],
[-0.8557, -0.0265],
[ 0.9068, 0.7410],
[ 2.1148, -0.3213],
[-0.1708, -1.1462]], requires_grad=True)
tensor([[-0.2232, 0.8796],
[-0.1447, -1.0068],
[ 0.7258, -1.8143],
[-1.0545, 1.1487],
[-0.9435, -1.4581]])
tensor(2.1924, grad_fn=<MeanBackward1>)
查看實現源碼之後,還是沒能知道具體的實現步驟,發現如上申明的PoissonNLLLoss 中的計算代碼時:
loss = torch.exp(input) - target * input
ret = torch.mean(loss)
如有知曉具體解答過程的,望解答。
4、KLDivLoss
KL散度,也叫相對熵,是用於連續分佈的有用距離度量,並且在對(離散採樣)連續輸出分佈的空間進行直接回歸時通常很有用。
主要參數reduction中,除了經典的三個以外,還多出了batchmean這一選項,如果給reduction賦值爲’batchmean’,那麼就代表着在batchsize維度求平均值(就是計算得到的每一個元素的損失全部加起來之後除以batchsize,而不是mean計算方法下的元素個數)。
inputs=torch.tensor([[0.5,0.3,0.2],[0.2,0.3,0.5]])
target=torch.tensor([[0.9,0.05,0.05],[0.1,0.7,0.2]],dtype=torch.float)
loss_f_none=nn.KLDivLoss(reduction='none')
loss_f_mean=nn.KLDivLoss(reduction='mean')
loss_f_bs_mean=nn.KLDivLoss(reduction='batchmean')
loss_none=loss_f_none(inputs,target)
loss_mean=loss_f_mean(inputs,target)
loss_bs_mean=loss_f_bs_mean(inputs,target)
print("loss_none:\n{}\nloss_mean:\n{}\nloss_bs_mean:\n{}".format(loss_none, loss_mean, loss_bs_mean))
輸出:
loss_none:
tensor([[-0.5448, -0.1648, -0.1598],
[-0.2503, -0.4597, -0.4219]])
loss_mean:
-0.3335360586643219
loss_bs_mean:
-1.000608205795288
5、MSELoss
創建一個標準來測量輸入:math:x
和目標:math:`y中每個元素之間的均方誤差(L2範數平方)
lossfun=nn.MSELoss()
lossfun1=nn.MSELoss(reduction='none')
input=torch.randn(3,5,requires_grad=True)
print(input)
target=torch.randn(3,5)
print(target)
output=lossfun(input,target)
print(output)
output=lossfun1(input,target)
print(output)
輸出:
tensor([[-1.0748, -0.7300, -0.7085, 1.4914, 1.5150],
[ 0.7312, -1.6615, 0.8111, 1.7772, 1.0513],
[ 0.9700, -0.7969, -1.0133, -0.5023, 0.3190]], requires_grad=True)
tensor([[-1.6405, 1.9781, -0.7997, -1.3708, -1.4618],
[ 0.0414, 0.5810, -0.1028, 0.4886, -0.3905],
[-0.2697, 1.0235, -1.3026, 3.2425, -0.2109]])
tensor(3.6022, grad_fn=<MseLossBackward>)
tensor([[3.2006e-01, 7.3339e+00, 8.3100e-03, 8.1922e+00, 8.8612e+00],
[4.7579e-01, 5.0289e+00, 8.3517e-01, 1.6605e+00, 2.0787e+00],
[1.5369e+00, 3.3140e+00, 8.3715e-02, 1.4023e+01, 2.8076e-01]],
grad_fn=<MseLossBackward>)
第三個輸出的reduction爲默認的“mean”,給第四個輸出取了平均值。我們來根據公式計算這個對應的損失值。(x1-y1)2=(-1.0748+1.6405)2=0.320001649.
6、BCELoss
創建一個標準,用於測量目標和輸出之間的二進制交叉熵:
m=nn.Sigmoid()
loss=nn.BCELoss()
loss1=nn.BCELoss(reduction='none')
input=torch.randn(3,requires_grad=True)
print(input)
target=torch.empty(3).random_(2)
print(target)
print(m(input))
output=loss(m(input),target)
print(output)
output=loss1(m(input),target)
print(output)
輸出:
tensor([-0.1348, -0.2154, 0.1736], requires_grad=True)
tensor([1., 1., 1.])
tensor([0.4663, 0.4464, 0.5433], grad_fn=<SigmoidBackward>)
tensor(0.7265, grad_fn=<BinaryCrossEntropyBackward>)
tensor([0.7628, 0.8066, 0.6101], grad_fn=<BinaryCrossEntropyBackward>)
將x1和y1帶入上面的公式去計算,發現l1=-W1[-0.33133]。至於W1是多少,我就不得而知了。
7、CrossEntropyLoss
該標準將nn.LogSoftmax和nn.NLLLoss合併到一個類中。
loss=nn.CrossEntropyLoss()
input=torch.randn(3,5,requires_grad=True)
print(input)
target=torch.empty(3,dtype=torch.long).random_(5)
print(target)
output=loss(input,target)
print(output)
輸出:
tensor([[ 1.1205, -0.7146, 0.2124, -0.3854, -0.5209],
[-1.4408, -1.5053, -1.4333, -1.7397, -0.3800],
[-0.6021, 0.6240, -0.1252, -0.3854, -1.0135]], requires_grad=True)
tensor([1, 1, 4])
tensor(2.3155, grad_fn=<NllLossBackward>)
這個函數和NLLLoss()的區別在於就是不用自己申明一個nn.Logsoftmax().
8、SoftMarginLoss
創建一個標準,優化輸入張量:math:x
和目標張量:math:`y(包含1或-1)之間的兩類分類邏輯損失。
inputs = torch.tensor([[0.3, 0.7], [0.5, 0.5]])
target = torch.tensor([[-1, 1], [1, -1]], dtype=torch.float)
loss_f = nn.SoftMarginLoss(reduction='none')
loss = loss_f(inputs, target)
print("SoftMargin: ", loss)
SoftMargin: tensor([[0.8544, 0.4032],
[0.4741, 0.9741]])
參考文獻:
Pytorch詳解NLLLoss和CrossEntropyLoss
Pytorch的各種損失函數
18種損失函數全詳解及其PyTorch實現與機制