1. 程式人生 > 實用技巧 >【學習筆記】Pytorch深度學習—損失函式(二)

【學習筆記】Pytorch深度學習—損失函式(二)

5、nn.L1Loss

迴歸任務中常用的損失函式。
功能:計算模型輸出inputs與真實標籤target之差的絕對值

\[L_n=\vert x_n-y_n\vert \]

6、nn.MSELoss

迴歸任務中常用的損失函式。
功能:計算模型輸出inputs與target之差的平方

\[L_n=( x_n-y_n)^2 \]

nn.L1Loss(size_average=None,reduce=None,reduction='mean')
nn.MSELoss(size_average=None,reduce=None,reduction='mean')
reduction:計算模式,可為none(逐個元素計算)/sum(所有元素求和,返回標量)/mean(加權平均,返回標量)

實驗
(1)L1Loss:計算模型輸出與target之差的絕對值
(2)MSELoss:計算模型輸出與target之差的平方
注意事項:reduction採用none模式,以每個神經元一一對應計算L1Loss和MSELoss。

//建立輸入為2*2張量,值全為1。target同樣大小的張量,元素值為3.
    inputs = torch.ones((2, 2))
    target = torch.ones((2, 2)) * 3

    loss_f = nn.L1Loss(reduction='none')
    loss = loss_f(inputs, target)

    print("input:{}\ntarget:{}\nL1 loss:{}".format(inputs, target, loss))

# ------------------------------------------------- 6 MSE loss ----------------------------------------------

    loss_f_mse = nn.MSELoss(reduction='none')
    loss_mse = loss_f_mse(inputs, target)

    print("MSE loss:{}".format(loss_mse))

實驗結果:


圖1 L1Loss、MSELoss輸出結果

7、nn.SmoothL1Loss

功能:平滑的L1Loss

\[Loss(x,y)=\frac{1}{n}\sum_i{Z_i} \]

\(Z_i\)是如何求解的?\(Z_i\)是分段函式;其中,\(x_i\)是模型輸出,\(y_i\)是真實標籤。

\[\ Z_i = \begin{cases} 0.5(x_i-y_i)^2, & if\vert x_i-y_i\vert < 1 \\\vert x_i-y_i\vert-0.5, & otherwise \end{cases} \]


圖2 SmoothL1Loss輸出結果

實驗
結合圖2的實驗結果可以看出,相對於L1Loss損失函式,SmoothL1Loss通過"這一平滑"可以減輕離群點帶來的影響。

//構建inputs模型輸出,對應於公式中的 x,在[-3,3]上平均的取500個數據點
    inputs = torch.linspace(-3, 3, steps=500)
//構建與 inputs模型輸出 同維度的標籤target,元素為0
    target = torch.zeros_like(inputs)
//採用none一一對應求解Loss
    loss_f = nn.SmoothL1Loss(reduction='none')

    loss_smooth = loss_f(inputs, target)

    loss_l1 = np.abs(inputs.numpy())

    plt.plot(inputs.numpy(), loss_smooth.numpy(), label='Smooth L1 Loss')
    plt.plot(inputs.numpy(), loss_l1, label='L1 loss')
    plt.xlabel('x_i - y_i')
    plt.ylabel('loss value')
    plt.legend()
    plt.grid()
    plt.show()

8、nn.PoissonNLLLoss

功能:泊松分佈的負對數似然損失函式
輸出分類時,分類服從泊松分佈時採用的損失函式。

nn.PoissonNLLLoss(log_input=True,
                  full=False,
                  size_average=None,
                  eps=1e-08,
                  reduce=None,
                  reduction='mean')
(1)log_input=True,
loss(input,target)=exp(input)-target*input;
(2)log_input=False,
loss(input,target)=input-target*log(input+eps)
主要引數:
log_input:輸入是否為對數形式,決定計算公式
full:計算所有Loss,預設為False
eps:修正項,避免log(input)為nan

解釋:
(1)log_input:指示輸入資料是否已經為對數形式,直接決定了計算公式形式;
① log_input=True,
loss(input,target)=exp(input)-target * input ;

如果log_input=False:輸入資料還不是對數形式,計算中還需要對input取對數,取對數時有可能遇到input=0,這樣就無法正常進行取對數運算,因此在input後加入修正項eps。其中修正項很小,大概在\(10^{-8}\),它的加入並不會影響到對input對數數值的,即便有影響也可忽略不計。
② log_input=False,
loss(input,target)=input-target * log(input+eps)

(2)eps:修正項,將eps加在input後構成log(input+eps),從而避免nan現象。

實驗—當預設模式log_input=True,泊松分佈負對數似然函式nn.PoissonNLLLoss的使用方法和計算

//輸入和標籤都在正態分佈中以隨機取樣的方式獲取2×2張量
    inputs = torch.randn((2, 2))
    target = torch.randn((2, 2))

    loss_f = nn.PoissonNLLLoss(log_input=True, full=False, reduction='none')
    loss = loss_f(inputs, target)
    print("input:{}\ntarget:{}\nPoisson NLL loss:{}".format(inputs, target, loss))

9、nn.KLDivLoss

功能:相對熵損失函式也稱KLD(divergence)、KL散度
注意事項:
需提前將輸入計算log-probabilities,如通過nn.logsoftmax()實現

nn.PoissonNLLLoss(size_average=None,
                   reduce=None,
                   reduction='mean')
主要引數:
reduction:none/sum/mean/batchmean(以batchsize維度求平均值)

由於相對熵損失函式(KL散度)衡量的是2個概率分佈之間的差異,用來計算2個概率分佈的距離。因此,應當保證參與計算的輸入應當在概率區間,並且Pytorch提供的KLDivLoss計算公式也是直接取輸入(模型輸出值\(x_n\))計算,因而利用該函式計算應當提前計算log-probabilities,如通過nn.softmax()實現。


圖3 KLDivLoss計算原理

實驗

     //該輸入處於概率區間(0,1),符合probabilities
    inputs = torch.tensor([[0.5, 0.3, 0.2], [0.2, 0.3, 0.5]])
    //預先進行log計算
    inputs_log = torch.log(inputs)
    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)

10、nn.MarginRankingLoss

功能:計算兩個向量之間的相似度,用於排序任務
特別說明:該方法計算兩組資料之間的差異,返回1個n*n的Loss矩陣。

nn.MarginRankingLoss(margin=0.0,
                      size_average=None,
                      reduce=None,
                      reduction='mean')
主要引數:
margin:邊界值,x1與x2之間的差異值
reduction:計算模式none/sum/mean

圖4 MarginRankingLoss計算原理

實驗

    x1 = torch.tensor([[1], [2], [3]], dtype=torch.float)
    x2 = torch.tensor([[2], [2], [2]], dtype=torch.float)

    target = torch.tensor([1, 1, -1], dtype=torch.float)

    loss_f_none = nn.MarginRankingLoss(margin=0, reduction='none')

    loss = loss_f_none(x1, x2, target)

    print(loss)

實驗結果


圖5 MarginRankingLoss輸出結果分析

11、nn.MultilabelMarginLoss

功能:多標籤邊界損失函式
容易將多標籤與多分類任務混淆。
多標籤是指一個樣本可能對應多個類別。一些任務會將影象進行分類,即風景、人像、美食進行基本劃分,這時會對影象基本元素進行分類,比如下述圖6風景影象有云、樹、草地等標籤,因此這張圖片可能對應多個類別。


圖6 示例影象
nn.MarginRankingLoss(size_average=None,
                      reduce=None,
                      reduction='mean')
主要引數:
reduction:計算模式none/sum/mean

舉例:四分類任務,樣本x屬於0類和3類,標籤:[0,3,-1,1]而非[1,0,0,1]


圖6 MultiLabelMarginLoss計算原理及輸出結果分析

12、nn.SoftMarginLoss

功能:計算二分類的logistic損失

\[\ Loss(x,y) = \sum_i \frac{log(1+exp(-y[i]*x[i]))}{x.nelement()} \]

nn.SoftMarginLoss(size_average=None,
                   reduce=None,
                   reduction='mean')
主要引數:
weight:各類別的Loss設定權值
reduction:計算模式none/sum/mean

13、nn.MultiLabelSoftMarginLoss

MultiLabelSoftMarginLoss第12個損失函式的多標籤版本
功能:SoftMarginLoss的多標籤版本

nn.SoftMarginLoss(weight=None,size_average=None,
                   reduce=None,
                   reduction='mean')
主要引數:
reduction:計算模式none/sum/mean

圖7 MultiLabelSoftMarginLoss計算原理

14、nn.MultiMarginLoss

功能:計算多分類的摺頁損失

nn.MultiMarginLoss(p=1,margin=1.0,weight=None,
                   size_average=None,
                   reduce=None,
                   reduction='mean')
主要引數:
p:可選1或2
weight:各類別的loss設定權值
margin:邊界值
reduction:計算模式none/sum/mean

圖8 MultiMarginLoss計算原理

15、nn.TripletMarginLoss

功能:計算三元組損失,人臉驗證中常用。
通過學習,希望Anchor與Negative之間的距離要更長,Anchor與Positive之間的距離更短。

nn.TripletMarginLoss(margin=1.0,p=2.0,eps=1e-06,
                      swap=False,
                      size_average=None,
                      reduce=None,
                      reduction='mean')
主要引數:
p:範數的階,預設為2
margin:邊界值
reduction:計算模式none/sum/mean

人臉驗證中經常使用,Anchor是自己人臉影象,Positive自己的人臉影象,Negative是其他人的人臉影象,訓練時希望自己的人臉影象相近,而與其他人的人臉影象不相同。


圖9 TripletMarginLoss計算原理

16、nn.HingeEmbeddingLoss

功能:計算兩個輸入的相似性,常用於非線性embedding(嵌入學習)和半監督學習

nn.HingeEmbeddingLoss(margin=1.0,
                       size_average=None,
                       reduce=None,
                       reduction='mean')
主要引數:
margin:邊界值
reduction:計算模式none/sum/mean

圖10 HingeEmbeddingLoss計算原理

17、nn.CosineEmbeddingLoss

功能:採用餘弦相似度計算兩個輸入的相似性

nn.CosineEmbeddingLoss(margin=0.0,
                       size_average=None,
                       reduce=None,
                       reduction='mean')
主要引數:
margin:邊界值,可取值[-1,1],推薦為[0,0.5]
reduction:計算模式none/sum/mean

圖11 CosineEmbeddingLoss計算原理

18、nn.CTCLoss

功能:計算CTC損失,解決時序類資料的分類。比如OCR中,輸入和輸出長度不確定的情況下,計算其分類可用到CTCLoss,通常在影象任務中使用比較少。

torch.nn.CTCLoss(blank=0.0,
                       reduction='mean',
                       zero_infinity=False)
主要引數:
blank:blank label
zero_infinity:無窮大的值或梯度置0
reduction:計算模式none/sum/mean

以上是Pytorch中18種損失函式,需要仔細整理,在具體任務中選擇衡量輸出與標籤之間差異的相應損失函式。