pytorch | Softmax->Log->NLLLoss->CrossEntropyLoss
1.torch.nn.Softmax
做什么的:將Softmax函數應用于n維輸入張量,重新縮放它們,以便n維輸出張量的元素位于[0,1]范圍內,并且總和為1。
注意事項:需要指定按照行和為1還是列和為1,參數設置dim=1表示行和為1,dim=0表示列和為1。
計算公式:
難點:看到公式,手動該如何計算?假設需要進行softmax操作的張量是:[[1,2,3],[1,2,4]]是一個2*3規模的張量,經過softmax后,希望行和為1,手動計算過程(把公式列舉出來,計算可以使用百度幫忙計算):
根據計算公式,把算式列出來,通過百度計算出結果。
????
手動計算結果出來了,接著寫段代碼來驗證一下,看看是否和計算結果一致。
代碼:
import torch import torch.nn as nn m = nn.Softmax(dim=1) input = torch.Tensor([[1,2,3],[1,2,4]]) print(input) output = m(input) print(output)代碼運行結果:
觀察結果:結果都是小數點后保留4位小數,對比第一行手動計算結果,是一致的。接著按照同樣的公式,把第二行的結果計算出來
? ?? ??
對比結果中的第二行,確實是一致的。觀察結果:每行的和為1,這是因為dim=1這個參數所控制的。
總結:該公式的意義有點像計算每個值占總和中的比例,總和為1,每個值的范圍是[0,1]之間。可以理解為概率。
2.torch.nn.LogSoftmax
做什么的:通過softmax計算出來的占比,也可以理解為概率大小,因為都是0-1之間的數,概率很小的時候,還要進行連乘操作,會導致結果更小,為了避免下溢,將積運算轉換為和運算,使用的公式是:
注意事項:公式中只寫了一個log,底數沒有給出,需要首先確定底數是多少,一般底數比較特殊的就是2和e以及10,e可以排除,如果是e,一般是寫為ln,10為底一般可以寫為lg,所以優先猜測是以2位底的,其次,計算機機器碼就是0和1組成,所以是2的可能性很大。
計算公式:
觀察公式,好像就是比Softmax的結果上加了一個log,也就是取對數。那我把上面計算結果去對數看看:
python中有數學公式,直接調用,這次就不要傻傻的去百度計算結果,因為輸入的時候不好計算,對數m為底n的對數,輸入不方便,所以調用現成的。
代碼:
x00 = math.log(0.0900) x01 = math.log(0.2447) x02 = math.log(0.6652) x10 = math.log(0.0420) x11 = math.log(0.1142) x12 = math.log(0.8438) print(x00, x01, x02) print(x10, x11, x12)運行結果:
這個計算結果就理解為手動計算出來的結果,也就是將softmax計算出來的結果,取了對數,可能存在一些誤差,softmax計算出來的結果是保留了4位小數的。
為了驗證手動計算結果是否準確,上代碼,看看運行結果
代碼:
??import torch import torch.nn as nn m = nn.LogSoftmax(dim=1) input = torch.Tensor([[1,2,3],[1,2,4]]) print(input) output = m(input) print(output)代碼運行結果:
結果顯示:和手動結算結果是一致的。說明我們對公式的理解沒有問題。注意:舉例都是在dim=1參數下做的,不要把條件搞忘了。
總結:在softmax上加了對數,可以理解為對數概率。
3.torch.nn.NLLLoss
做什么的:負對數似然損失,訓練分類。
手動計算過程:首先需要明確的點是:NLLLoss函數輸入input之前,需要對input進行log_softmax處理。
假設數據是:[[1,2,3],[1,2,4]],標簽為:[1,2] dim設置為1,按行求和
首先計算softmax,計算結果是[[0.0900,0.2447,0.6652],[0.0420,0.1142,0.8438]]
再取對數,計算結果是:[[-2.4076,-1.4076,-0.4076],[-3.1698,-2.1698,-0.1698]]
計算負對數似然,首先取負數,再計算,默認是取均值。
根據標簽,1表示第一行的索引為1的的數,即:-1.4076
2表示第二行的索引為2的數,即:-0.1698
取負數后,1.4076和0.1698
求均值:(1.4076+0.1698)/2 = 1.5774/2=0.7887
注意事項:標簽中的索引號范圍是:[0,C-1],比如分為3類,則最多出現:0,1,2,不可能出現比0小或者比2大的數成為標簽中的元素。
寫段代碼驗證一下手動計算結果。
代碼:
m = nn.LogSoftmax(dim=1) # 模型 loss = nn.NLLLoss() # 計算損失的標準 input = torch.Tensor([[1,2,3],[1,2,4]]) print('input:',input) target = torch.tensor([1, 2])#每一項的范圍是[0,C-1] print('target:', target) output = loss(m(input), target) print('output:', output)代碼運行結果:
4.torch.nn.CrossEntropyLoss
前面所說的一切,都是為了給交叉熵作鋪墊,^_^,先看下官網怎么說的:
這句描述說的是:交叉熵是LogSoftmax()和NLLLoss()組合而成,而LogSoftmax()實際上是softmax+log,所以通俗的講:交叉熵是softmax+log+NLLLoss組合而成。并沒有什么新的內容。
變相的說,調用交叉熵的結果,和上面一步一步實現的結果是一樣的。
代碼:
input = torch.Tensor([[1,2,3],[1,2,4]]) target = torch.Tensor([1,2]).long() criterion = nn.CrossEntropyLoss() loss = criterion(input, target) print(loss)代碼運行結果:
再單獨一步一步執行測試一下:
代碼:
import torch import torch.nn as nn input = torch.Tensor([[1, 2, 3], [1, 2, 4]]) target = torch.Tensor([1, 2]).long() m1 = nn.Softmax(dim=1) r1 = m1(input) print('softmax結果:\n', r1) r2 = torch.log(r1) print('log結果:\n', r2) m2 = nn.NLLLoss() loss = m2(r2, target) print('NLLLoss結果:\n',loss) print(loss)代碼運行結果:
總結:我感覺最難的點是公式看不懂,不知道如何展開,其次,就是測試的時候最好是自己寫數字,因為隨機產生的,不好計算,自己寫的,手動計算的時候稍微好計算一些。總之,無論多艱難,一步一步走,大不了多花點時間,總會弄明白。
總結
以上是生活随笔為你收集整理的pytorch | Softmax->Log->NLLLoss->CrossEntropyLoss的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 问题 | list(set(list))
- 下一篇: pytorch:一维线性回归(二)
