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。
- 損失函式
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>)]
損失函式
- nn.CrossEntropyLoss
功能:nn.LogSoftmax()[採用softmax進行歸一化處理]與nn.NLLLoss()結合,進行交叉熵計算[和公式意義上的交叉熵不同之處:採用softmax進行歸一化,把資料值歸一到一個概率輸出的模式,交叉熵損失函式常常用在分類任務當中,分類任務中通常需要計算兩個輸出的概率值,因為在分類任務當中我們的輸出常常是以概率值為主的,所以交叉熵在這裡主要是衡量兩個概率分佈之間的差異,所以交叉熵的值越低,表示兩個概率分佈越近越相似]
交叉熵=資訊熵+相對熵
[熵是夏農從熱力學方面引申的一個概念,用來描述該事情的不確定性,一個事件越不確定,它的熵就越大,例如明天下雨這件事的熵就比明天太陽升起這件事的熵要大。自資訊是用來衡量單個事件的不確定性,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])}\\ 將這一個神經元的輸出值歸一化到一個概率取值區間。 \]- 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函式
主要引數:
- pos_weight:正樣本的權值
- weight:各類別的Loss設定權值
- ignore_index:忽略某個類別
- 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)})]
\]