1. 程式人生 > 實用技巧 >pytorch(14)損失函式

pytorch(14)損失函式

損失函式

1. 損失函式概念

損失函式:衡量模型輸出與真實標籤的差異

\[損失函式(Loss Function): Loss = f(\hat y,y) \]

\[代價函式(Cost Function): Cost =\frac{1}{N} \sum^{N}_{i}f(\hat y_i ,y_i) \]

\[目標函式(Objective Function): Obj = Cost+Regularization \]

損失函式:計算一個樣本的一個差異
代價函式:計算整個樣本的loss的平均值
目標函式:表示最終的一個目標,目標函式來說在有約束條件下的最小化就是損失函式(loss function)
代價函式未必是越小越好,因為很可能出現過擬合。因此為了不讓代價函式達到最小,出現過擬合。於是我們就添加了Regularization的正則項L1,L2。

  1. 損失函式
class _Loss(Module):
	def __init__(self,reduction='mean'):
		super(_Loss, self).__init__()
		if size_average is not None or reduce is not None:
			self.reduction = _Reduction.legacy_get_string(size_average, reduce)
		else:
			self.reduction = reduction

分析流程:
crossentropyLoss的流程:

loss_functoin = nn.CrossEntropyLoss()   #①處   

先通過nn.CrossEntropyLoss構建損失函式賦給loss_function,緊接著在訓練過程中通過

loss = loss_functoin(outputs, labels)   #②處

進行計算其損失函式,輸入神經網路模型的輸出outputs的值和標籤進行loss。
在①②處設定斷點,step into①處時,進入loss.py,呼叫class CrossEntropyLoss類,繼承_WeightedLoss類,也就是會繼承一個帶權值的Loss類。進入init的初始化類,能夠看到它呼叫了一個父類的super(CrossEntropyLoss)的初始化類,再step into,能夠看到它是一個_WeightedLoss類的init初始化,這個類繼承_Loss這個基本類。再通過step into能夠看到是繼承的Module類,其主要是設定reduction。在這裡reduction="mean"。
接下來我們在step into②處進行step into。剛剛在lossfunction處我們已經知道lossfunction是一個Module型別,所以這裡輸入一個outputs和labels之後就是執行了一個forward.在這裡step into後的hook就比較熟悉,我們直接進入到

result = self.forward(*input, **kwargs)

再進入到step into後,進入到forward模組

    def forward(self, input: Tensor, target: Tensor) -> Tensor:
        return F.cross_entropy(input,target,weight=self.weight,ignore_index=self.ignore_index,reduction=self.reduction)

step into [F.cross_entropy],進入到functional.py中

    if size_average is not None or reduce is not None:
        reduction = _Reduction.legacy_get_string(size_average, reduce)
    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)

接下來就能夠計算出loss,在這裡為[loss:tensor(0.7012, grad_fn=<NllLossBackward>)]

損失函式

  1. nn.CrossEntropyLoss
    功能:nn.LogSoftmax()[採用softmax進行歸一化處理]與nn.NLLLoss()結合,進行交叉熵計算[和公式意義上的交叉熵不同之處:採用softmax進行歸一化,把資料值歸一到一個概率輸出的模式,交叉熵損失函式常常用在分類任務當中,分類任務中通常需要計算兩個輸出的概率值,因為在分類任務當中我們的輸出常常是以概率值為主的,所以交叉熵在這裡主要是衡量兩個概率分佈之間的差異,所以交叉熵的值越低,表示兩個概率分佈越近越相似]
    交叉熵=資訊熵+相對熵

\[{交叉熵: } H(P,Q) = -\sum^{N}_{i=1}P(x_i)log Q(x_i)\\ {自資訊: }I(x)=-log[p(x)]\\ {熵(資訊熵):}H(P)=E_{x\sim p}[I(x)]=-\sum^{N}_{i}P(x_i)logP(x_i)\\ {相對熵:}D_KL(P,Q)=E_{x\sim p}\Big[log \frac{P(x)}{Q(x)}\Big]\\ =E_{x\sim p}[logP(x)-logQ(x)]\\ =\sum_{i=1}^{N}P(x_i)[log P(x_i)-logQ(x_i)]\\ =\sum_{i=1}^{N}P(x_i)logP(x_i)-\sum_{i=1}^{N}P(x_i)logQ(x_i)\\ =H(P,Q)-H(P)\\ {交叉熵:}H(P,Q) = D_{KL}(P,Q)+H(P) \]

[熵是夏農從熱力學方面引申的一個概念,用來描述該事情的不確定性,一個事件越不確定,它的熵就越大,例如明天下雨這件事的熵就比明天太陽升起這件事的熵要大。自資訊是用來衡量單個事件的不確定性,px是事件x的概率,對概率取一個-log。熵是整個概率分佈的不確定性,用來描述整個概率分佈,它是自資訊的一個期望。相對熵又叫KL散度,用來衡量兩個分佈之間的差異距離,雖然是可以計算的,但是它不是一個距離函式,距離函式是有對稱性的,這裡的相對熵沒有對稱性。從公式上來看,P是真實的分佈,Q是模型輸出的一個分佈,我們需要用Q去擬合P的分佈,所以是不具備對稱性的。它是對log P(x)/Q(x)]求取期望。因此在深度學習的模型中,我們去優化交叉熵,實際上就是去優化相對熵的,訓練集的P是固定的常數,所以在優化中是優化DKL(P,Q)]
在伯努利模型中,很容易發現概率為0.5的Loss值是0.69,通常意義表明模型訓練壞了,當前模型不具備任何判別能力。因為它對任何的輸出都是0.5,可能或者不可能。
主要引數:

  • weight:各類別的loss設定權值,在公式中如下,如果我們想讓第0類的loss更大點,讓模型更關注第0類,我們可以把它的weight設定為1.2
  • ignore_index:忽略某個類別,不計算Loss
  • reduction:計算模式,可為none/sum/mean
    none:逐個元素計算
    sum:所有元素求和,返回標量
    mean:加權平均,返回標量
    nn.CrossEntropyLoss(weight=None,size_average=None,ignore_index=-100,reduce=None,reduction='mean')

交叉熵的計算公式如下:

\[x是概率值,class是類別值 \\H(P,Q)=\sum^{N}_{i=1}P(x_i)logQ(x_i)\\ loss(x,class)=-log\Big(\frac{exp(x[class])}{\sum_j exp(x[j])} \Big)=-x[class]+log\Big(\sum_j exp(x[j]) \Big)\\ softmax歸一化=\frac{exp(x[class])}{\sum_j exp(x[j])}\\ 將這一個神經元的輸出值歸一化到一個概率取值區間。 \]

  1. NLL/BCE/BCEWithLogits Loss

nn.NLLLoss
功能:實現負對數似然函式中的負號功能
主要引數:

  • weight:各類別的Loss設定權值
  • ignore_index:忽略某個類別
  • reduction:計算模式,可為none/sum/mean
nn.NLLLoss(weight=None,size_average=None,ignore_index=-100,reduce=None,reduction='mean')

\[l(x,y)=L=\{l_1,...,l_N\}^T,l_n=-{w_{y_n}}x_{n,y_n} \]

nn.BCELoss
功能:二分類交叉熵
注意事項:輸入值取值在[0,1]
主要引數:

  • weight:各類別的Loss設定權值
  • ignore_index:忽略某個類別
  • reduction:計算模式,可為none/sum/mean
    none-逐個元素計算
    sum-所有元素求和,返回標量
    mean-加權平均,返回標量
nn.BCELoss(weight=None,size_average=None,reduce=None,reduction='mean')

\[l_n = -w_n[y_n*log{x_n} +(1-y_n)*log(1-x_n) ] \]

nn.BCEWithLogitsLoss
功能:結合Sigmoid與二分類交叉熵
注意事項:網路最後不加sigmoid函式
主要引數:

  1. pos_weight:正樣本的權值
  2. weight:各類別的Loss設定權值
  3. ignore_index:忽略某個類別
  4. reduction:計算模式:none,sum,mean
    程式碼:
nn.BCEWithLogitsLoss(weight=None,size_average=None,reduce=None,reduction='mean',pos_weight=None)

\[l_n = -w_n[y_n * log(1- \sigma{(x_n)})] \]