一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

 常有理 2021-07-12
機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

1.第六天

今天是該系列的第六篇文章,我們通過(guò)上一次的學(xué)習(xí),基本上完成了模型模塊,也學(xué)會(huì)了如何搭建網(wǎng)絡(luò)模型,下面進(jìn)入損失函數(shù)的模塊,但是在這之前,先來(lái)看看常用的權(quán)值初始化方法,這是網(wǎng)絡(luò)模型搭建好之后的一個(gè)非常重要的步驟,正確的權(quán)值初始化可以加速模型的收斂,不恰當(dāng)?shù)臋?quán)值初始化導(dǎo)致輸出層的輸出過(guò)大或者過(guò)小,最終導(dǎo)致梯度爆炸或者消失,使得模型無(wú)法訓(xùn)練,這里會(huì)深層剖析權(quán)重初始化的重要性,會(huì)學(xué)習(xí)適用于飽和激活函數(shù) tanh 等的 Xavier 初始化方法和非飽和激活函數(shù) relu 等的 Kaiming 初始化方法(這些在實(shí)踐中非常常用,但是有時(shí)候并不知道用這個(gè)背后的原因),學(xué)習(xí)完了這個(gè),然后再正式整理關(guān)于各種損失函數(shù)的一些知識(shí),這里會(huì)學(xué)習(xí) 18 種損失函數(shù)的原理及使用,最后會(huì)對(duì)這 18 種損失函數(shù)梳理一下,得知道什么樣的任務(wù)有哪些損失函數(shù)可用。通過(guò)這篇文章,可以打通權(quán)值初始化和損失函數(shù)的任督二脈。

「大綱如下:」

  • 權(quán)值初始化(梯度消失與爆炸,Xavier 方法與 Kaiming 方法,十種初識(shí)化方法)
  • 損失函數(shù)(損失函數(shù),代價(jià)函數(shù),目標(biāo)函數(shù)這哥仨不是一回事,交叉熵?fù)p失,NLL/BCE/BCEWithLogits Loss)
  • 總結(jié)梳理

下面依然是一個(gè)思維導(dǎo)圖把知識(shí)拎起來(lái),方便后面的速查:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

2.權(quán)值初始化

在網(wǎng)絡(luò)模型搭建完成之后,對(duì)網(wǎng)絡(luò)中的權(quán)重進(jìn)行合適的初始化是非常重要的一個(gè)步驟, 初始化好了,比如正好初始化到模型的最優(yōu)解附近,那么模型訓(xùn)練起來(lái)速度也會(huì)非常的快, 但如果初始化不好,離最優(yōu)解很遠(yuǎn),那么模型就需要更多次迭代,有時(shí)候還會(huì)引發(fā)梯度消失和爆炸現(xiàn)象, 所以正確的權(quán)值初始化還是非常重要的,下面我們就來(lái)看看常用的權(quán)值初始化的方法,但是在這之前,先了解一下什么是梯度消失和梯度爆炸現(xiàn)象。

2.1 梯度的消失和爆炸

我們以上一篇的一個(gè)圖來(lái)看一下梯度消失和爆炸現(xiàn)象

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

看上面這個(gè)圖, 假設(shè)我們要算的梯度,我們根據(jù)鏈?zhǔn)椒▌t應(yīng)該是下面這樣:

這樣我們就會(huì)發(fā)現(xiàn) 梯度的求解過(guò)程中會(huì)用到上一層神經(jīng)元的輸出值 ,那么這時(shí)候,如果 的輸出值非常小,那么 的梯度也會(huì)非常小,這時(shí)候就有可能造成梯度消失的現(xiàn)象,尤其是當(dāng)網(wǎng)絡(luò)層很多的時(shí)候,這種連乘一個(gè)數(shù)非常小,就會(huì)導(dǎo)致越乘越小,后面的層里面就容易發(fā)現(xiàn)梯度消失。而當(dāng) 非常大的時(shí)候,當(dāng)然也就會(huì)發(fā)生梯度爆炸。

一旦發(fā)生梯度消失或者爆炸,就會(huì)導(dǎo)致模型無(wú)法訓(xùn)練,而如果想避免這個(gè)現(xiàn)象,我們就得「控制網(wǎng)絡(luò)輸出層的一個(gè)尺度范圍,也就是不能讓它太大或者太小」。那么我們?cè)趺纯刂七@個(gè)網(wǎng)絡(luò)輸出層的尺度呢?那就是通過(guò)合理的初始化權(quán)重了。我們下面從代碼切入,進(jìn)行理解吧:

我們建立一個(gè) 100 層的多層感知機(jī),每一層 256 個(gè)神經(jīng)元,我們使用上面學(xué)習(xí)的 ModuleList 進(jìn)行建立:

class MLP(nn.Module): def __init__(self, neural_num, layers):  super(MLP, self).__init__()  self.linears = nn.ModuleList([nn.Linear(neural_num, neural_num, bias=False) for i in range(layers)])  self.neural_num = neural_num # 正向傳播 def forward(self, x):  for (i, linear) in enumerate(self.linears):   x = linear(x)   print('layer:{}, std:{}'.format(i, x.std()))   if torch.isnan(x.std()):    print('output is nan in {} layers'.format(i))    break    return x # 權(quán)值初始化,我們這里使用標(biāo)準(zhǔn)正態(tài) def initialize(self):  for m in self.modules():   if isinstance(m, nn.Linear):    nn.init.normal_(m.weight.data)      # normal: mean=0, std=1# 用一下網(wǎng)絡(luò)layer_nums = 100neural_nums = 256batch_size = 16net = MLP(neural_nums, layer_nums)net.initialize()inputs = torch.randn((batch_size, neural_nums))  # normal: mean=0, std=1output = net(inputs)print(output)

這個(gè)結(jié)果可以發(fā)現(xiàn),在 35 層的時(shí)候,神經(jīng)網(wǎng)絡(luò)的輸出就成了 nan,這說(shuō)明網(wǎng)絡(luò)出現(xiàn)了問(wèn)題,導(dǎo)致后面輸出的值太大了,當(dāng)然我們還沒(méi)有反向傳播,根據(jù)上面的權(quán)重推導(dǎo)的公式,后面的這些如果為 nan 了之后,反向傳播的時(shí)候,這些權(quán)重根本就沒(méi)法進(jìn)行更新,會(huì)發(fā)生梯度爆炸現(xiàn)象。

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這就是有時(shí)候我們?cè)谟?xùn)練網(wǎng)絡(luò)的時(shí)候,最后結(jié)果全是 nan 的原因,這往往可能是權(quán)重初始化的不當(dāng)導(dǎo)致的。

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

可是,這是為啥呢?為啥我初始化權(quán)重不當(dāng)了會(huì)影響到網(wǎng)絡(luò)的輸出呢?剛才不是還說(shuō)是網(wǎng)絡(luò)的輸出影響的權(quán)重梯度嗎?那是反向傳播的時(shí)候,而正向傳播的時(shí)候,權(quán)重肯定要影響到每一層的輸出啊。我們推導(dǎo)一下上面這個(gè)過(guò)程中每一層輸出的方差是如何變化的就明白了。

下面先進(jìn)行一個(gè)方差的公式推導(dǎo):

借助三個(gè)基本公式:

那么

若 ,則

好了, 那么我們看看神經(jīng)網(wǎng)絡(luò)里面每一層輸出的方差計(jì)算:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

還是這個(gè)網(wǎng)絡(luò),我們看第一層第一個(gè)神經(jīng)元的方差應(yīng)該怎么算:

這里我們的輸入數(shù)據(jù)和權(quán)重都初始化的均值為 0,方差為 1 的標(biāo)準(zhǔn)正態(tài)。這樣經(jīng)過(guò)一個(gè)網(wǎng)絡(luò)層就發(fā)現(xiàn)方差擴(kuò)大了 n 倍。而我們上面用了 100 個(gè)網(wǎng)絡(luò)層,那么這個(gè)方差會(huì)指數(shù)增長(zhǎng),所以我們后面才會(huì)出現(xiàn)輸出層方差 nan 的情況。

那么我們?cè)趺唇鉀Q這種情況呢?那很簡(jiǎn)單,讓網(wǎng)絡(luò)層的輸出方差保持尺度不變就可以了,可是怎么做呢?分析一下網(wǎng)絡(luò)層的輸出方差:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

我們發(fā)現(xiàn),每一層的輸出方差會(huì)和每一層神經(jīng)元個(gè)數(shù),前一層輸出方差和本層權(quán)重的方差有關(guān),如果想讓方差的尺度不變,因?yàn)檫@里都是連乘,有個(gè)方法就是讓每一層輸出方差都是 1,也就是 ,這樣后面多層相乘,那么也不會(huì)變這個(gè)尺度。怎么做呢?首先,每一層神經(jīng)元個(gè)數(shù)沒(méi)法變,而前一層輸出方差是 1 又涉及到了方差, 所以這里能變得就是權(quán)重的方差:

這樣,我們權(quán)重在初識(shí)的時(shí)候,方差如果是 的話,每一層的輸入方差都是 1,這樣方差就不會(huì)導(dǎo)致 nan 的情況發(fā)生了。在上面代碼中改一句話:

def initialize(self):  for m in self.modules():    if isinstance(m, nn.Linear):      nn.init.normal_(m.weight.data, std=np.sqrt(1/self.neural_num))         # 把權(quán)重方差改了

這樣就會(huì)發(fā)現(xiàn),不會(huì)出現(xiàn)nan的情況了:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

「所以我們只要采用恰當(dāng)?shù)臋?quán)值初始化方法,就可以實(shí)現(xiàn)多層神經(jīng)網(wǎng)絡(luò)的輸出值的尺度維持在一定范圍內(nèi), 這樣在反向傳播的時(shí)候,就有利于緩解梯度消失或者爆炸現(xiàn)象的發(fā)生」

當(dāng)然,上面的網(wǎng)絡(luò)只是一個(gè)線性網(wǎng)絡(luò),在實(shí)際中我們還得考慮激活函數(shù)的存在,我們從上面的前向傳播中加一個(gè)激活函數(shù)再看一下結(jié)果:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

那么,具有激活函數(shù)的時(shí)候,怎么對(duì)權(quán)重進(jìn)行初始化呢?

2.2 Xavier初始化

「方差一致性」:保持?jǐn)?shù)據(jù)尺度范圍維持在恰當(dāng)范圍,通常方差為 1。如果有了激活函數(shù)之后,我們應(yīng)該怎么對(duì)權(quán)重初始化呢?

2010 年 Xavier 發(fā)表了一篇文章,詳細(xì)探討了如果有激活函數(shù)的時(shí)候,如何進(jìn)行權(quán)重初始化,當(dāng)然它也是運(yùn)用的方差一致性原則,但是它這里「考慮的是飽和激活函數(shù)」,如 sigmoid,tanh。文章中有個(gè)這樣的公式推導(dǎo),從而得到我們權(quán)重的方差:

這里的 、 分別指的輸入層和輸出層神經(jīng)元個(gè)數(shù)。通常 Xavier 采用均勻分布對(duì)權(quán)重進(jìn)行初始化,那么我們可以推導(dǎo)一下均勻分布的上限和下限:

我們讓上面的兩個(gè) 相等就會(huì)得到

這就是 Xavier 初始化方法,那么在代碼中怎么用呢?還是上面的那個(gè)代碼例子,我們?cè)趨?shù)初始化里面用 Xavier 初始化權(quán)重:

def initialize(self):  for m in self.modules():    if isinstance(m, nn.Linear):      # Xavier初始化權(quán)重      tanh_gain = nn.init.calculate_gain('tanh')      nn.init.xavier_uniform_(m.weight.data, gain=tanh_gain)

這里面用到了一個(gè)函數(shù)nn.init.calculate_gain(nonlinearity, param=None)這個(gè)函數(shù)的作用是計(jì)算激活函數(shù)的「方差變化尺度」,怎么理解這個(gè)方差變化尺度呢?其實(shí)就是輸入數(shù)據(jù)的方差除以經(jīng)過(guò)激活函數(shù)之后的輸出數(shù)據(jù)的方差。nonlinearity 表示激活函數(shù)的名稱(chēng),如tanh。param 表示激活函數(shù)的參數(shù),如 Leaky ReLU 的negative_slop。(這里不用也行,但得知道這個(gè)方法)。這時(shí)候再來(lái)看一下最后的結(jié)果:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

「所以Xavier權(quán)重初始化,有利于緩解帶有sigmoid,tanh的這樣的飽和激活函數(shù)的神經(jīng)網(wǎng)絡(luò)的梯度消失和爆炸現(xiàn)象?!?/span>

但是,2012年 AlexNet 出現(xiàn)之后,非飽和函數(shù) relu 也用到了神經(jīng)網(wǎng)絡(luò)中,而 Xavier 初始化對(duì)于 relu 就不好使了,不信我們看看:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

2.3 Kaiming 初始化

這個(gè)依然是考慮的方差一致性原則,「針對(duì)的激活函數(shù)是 ReLU 及其變種」。經(jīng)過(guò)公示推導(dǎo),最后的權(quán)值標(biāo)準(zhǔn)差是這樣的:

那么 Kaiming 初始化權(quán)重方法怎么用呢?

def initialize(self):  for m in self.modules():    if isinstance(m, nn.Linear):      nn.init.kaiming_normal_(m.weight.data)      # nn.init.normal_(m.weight.data, std=np.sqrt(2 / self.neural_num))     # 這兩句話其實(shí)作用一樣,不過(guò)自己寫(xiě)還得計(jì)算出標(biāo)準(zhǔn)差

我們可以看一下結(jié)果:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

所以從上面的學(xué)習(xí)中,我們對(duì)權(quán)值的初始化有了清晰的認(rèn)識(shí),發(fā)現(xiàn)了權(quán)重初始化對(duì)于模型的重要性,不好的權(quán)重初始化方法會(huì)引起輸出層的輸出值過(guò)大過(guò)小,從而引發(fā)梯度的消失或者爆炸,最終導(dǎo)致我們的模型無(wú)法訓(xùn)練。所以我們?nèi)绻刖徑膺@種現(xiàn)象,就得控制輸出層的值的范圍尺度,就得采取合理的權(quán)重初始化方法。

2.4 十種權(quán)重初始化方法

Pytorch 里面提供了很多權(quán)重初始化的方法,可以分為下面的四大類(lèi):

  • 針對(duì)飽和激活函數(shù)(sigmoid, tanh):Xavier 均勻分布,Xavier 正態(tài)分布
  • 針對(duì)非飽和激活函數(shù)(relu 及變種):Kaiming 均勻分布,Kaiming 正態(tài)分布
  • 三個(gè)常用的分布初始化方法:均勻分布,正態(tài)分布,常數(shù)分布
  • 三個(gè)特殊的矩陣初始化方法:正交矩陣初始化,單位矩陣初始化,稀疏矩陣初始化:

好了,到了這里,模型模塊才算得上結(jié)束,下面我們就進(jìn)行下一個(gè)模塊的學(xué)習(xí),損失函數(shù)模塊,在這里面學(xué)習(xí)各種損失函數(shù)的原理及應(yīng)用場(chǎng)景。

3.損失函數(shù)

這一部分分為三大塊, 首先看一下?lián)p失函數(shù)到底是干嘛的?然后學(xué)習(xí)非常常用的損失函數(shù)交叉熵,最后再看看其他的幾個(gè)重要損失函數(shù)。

3.1 損失函數(shù)初步介紹

損失函數(shù):衡量模型輸出與真實(shí)標(biāo)簽的差異。而我們談?chuàng)p失函數(shù)的時(shí)候,往往會(huì)有三個(gè)概念:損失函數(shù),代價(jià)函數(shù),目標(biāo)函數(shù)。你知道這仨到底啥區(qū)別嗎?還是以為這仨就是一個(gè)概念?

  • Loss Function:計(jì)算一個(gè)樣本的一個(gè)差異。
  • Cost Function:計(jì)算整個(gè)訓(xùn)練集Loss的一個(gè)平均值。
  • Objective Function:這是一個(gè)更廣泛的概念,在機(jī)器學(xué)習(xí)模型訓(xùn)練中,這是最終的一個(gè)目標(biāo),過(guò)擬合和欠擬合之間進(jìn)行一個(gè)權(quán)衡。

而我們一般都是在衡量模型輸出和真實(shí)標(biāo)簽的差異的時(shí)候,往往都直接成損失函數(shù)。但是我們得知道這哥仨不是一回事。我們下面看一下Pytorch中的損失函數(shù)的真實(shí)面目:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

我們發(fā)現(xiàn)了啥? 原來(lái)_Loss也是繼承于Module,這個(gè)在模型創(chuàng)建的時(shí)候就已經(jīng)很熟悉了,也具體介紹過(guò), 既然_Loss也是繼承于這個(gè)類(lèi),那么就得先想起來(lái)肯定_Loss也有那 8 個(gè)參數(shù)字典了,然后這里面是設(shè)置一個(gè)reduction這個(gè)參數(shù)。下面我們?cè)僖匀嗣駧哦诸?lèi)的實(shí)驗(yàn)中的交叉熵?fù)p失為例子,看看損失函數(shù)是如何創(chuàng)建和使用的,背后的運(yùn)行機(jī)制又是什么?哈哈哈,下面就得來(lái)一波調(diào)試了。這次是損失函數(shù)的學(xué)習(xí),所以我們?cè)诙x損失函數(shù)和使用損失函數(shù)的地方打上斷點(diǎn),并且開(kāi)始 debug:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

程序運(yùn)行到第一個(gè)斷點(diǎn)處,我們步入,就到了 loss.py 文件中的一個(gè) class CrossEntropyLoss(_WeightedLoss):交叉熵?fù)p失類(lèi)的__init__方法, 這里發(fā)現(xiàn)交叉熵?fù)p失函數(shù)繼承_WeightedLoss這個(gè)類(lèi):

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

我們繼續(xù)步入,就到了class _WeightedLoss(_Loss):這個(gè)類(lèi)里面,就會(huì)發(fā)現(xiàn)這個(gè)類(lèi)繼承_Loss, 那么我們繼續(xù)步入,就到了_Loss這個(gè)類(lèi)里面去,會(huì)發(fā)現(xiàn)這個(gè)繼承Module,那么現(xiàn)在就明白了,損失函數(shù)的初始化方法和模型其實(shí)類(lèi)似,也是調(diào)用Module的初始化方法,最終會(huì)有 8 個(gè)屬性字典, 然后就是設(shè)置了一個(gè)reduction這個(gè)參數(shù)。初始化就是這樣子了,學(xué)過(guò)了 nn.Module 之后,這里都比較好理解。

那么下面看看使用過(guò)程中的運(yùn)行機(jī)制:我們到第二個(gè)斷點(diǎn),然后步入,我們知道既然這個(gè)損失函數(shù)也是一個(gè) Module,那么在調(diào)用的時(shí)候肯定也是調(diào)用的 forward 方法了,還真的是這樣,它也有一個(gè) forward 的函數(shù)的:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

看這里也是調(diào)用的 forward 函數(shù),我們把程序運(yùn)行到 547 行,再次步入,看看損失函數(shù)的 forward 長(zhǎng)啥樣:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

我們模型構(gòu)建里面 forward 里面寫(xiě)的是各個(gè)模塊的拼接方式,而損失函數(shù)的 forward 里面調(diào)用了 F 里面的各種函數(shù),我們 Ctrl 然后點(diǎn)擊這個(gè)函數(shù),看看這個(gè)交叉熵?fù)p失函數(shù)到底長(zhǎng)啥樣:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這個(gè)是底層計(jì)算了,不再往下了,我們退回去。

這就是損失函數(shù)的初始化和使用方法的內(nèi)部運(yùn)行機(jī)制了。從上面我們發(fā)現(xiàn)了損失函數(shù)其實(shí)也是一個(gè) Module, 那么既然是 Module,初始化依然是有 8 個(gè)屬性字典,使用的方法依然是定義在了 forward 函數(shù)中。下面我們就詳細(xì)的學(xué)習(xí)一個(gè)非常重要的函數(shù),也是上面例子里面的函數(shù)nn.CrossEntropyLoss, 這個(gè)在分類(lèi)任務(wù)中很常用, 所以下面得詳細(xì)的說(shuō)說(shuō)。

3.2 交叉熵?fù)p失 CrossEntropyLoss

nn.CrossEntropyLoss: nn.LogSortmax() 與 nn.NLLLoss() 結(jié)合,進(jìn)行交叉熵計(jì)算。

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析
  • weight:各類(lèi)別的 loss 設(shè)置權(quán)值
  • ignore_index:忽略某個(gè)類(lèi)別
  • reduction:計(jì)算模式,可為 none/sum/mean,none 表示逐個(gè)元素計(jì)算,這樣有多少個(gè)樣本就會(huì)返回多少個(gè) loss。sum 表示所有元素的 loss 求和,返回標(biāo)量,mean 所有元素的 loss 求加權(quán)平均(加權(quán)平均的含義下面會(huì)提到),返回標(biāo)量。看了下面的原理就懂了。

在詳細(xì)介紹這些參數(shù)用法之前,得先說(shuō)說(shuō)這里的交叉熵?fù)p失函數(shù),這個(gè)并不是公式意義上的交叉熵?fù)p失函數(shù),而是有一些不同之處。還記得普通的交叉熵?fù)p失函數(shù)嗎?

表示數(shù)據(jù)的原始分布, 表示模型輸出的分布,交叉熵?fù)p失衡量?jī)蓚€(gè)分布之間的差異程度,交叉熵越低,說(shuō)明兩個(gè)分布越近。這里的一個(gè)不同就是先用nn.LogSoftmax()把模型的輸出值歸一化成了概率分布的形式,然后是單個(gè)樣本的輸出,并且沒(méi)有求和符號(hào)。

具體的下面會(huì)解釋?zhuān)墙忉屩埃孟让靼滓粋€(gè)問(wèn)題,就是為什么交叉熵可以衡量?jī)蓚€(gè)分布的差異,這個(gè)到底是個(gè)什么東西?這就不得不提到相對(duì)熵, 而想了解相對(duì)熵,就得先明白熵的概念,而如果想明白熵,就得先知道自信息,好吧,成功懵逼。下面我們先看看這些都是啥吧:

首先從熵開(kāi)始,這是信息論之父香農(nóng)從熱力學(xué)借鑒來(lái)的名詞,用來(lái)描述事件的不確定性,一個(gè)事物不確定性越大,熵就越大。比如明天會(huì)下雨這個(gè)熵就比明天太陽(yáng)從東邊升起這個(gè)熵要大。那么熵的公式長(zhǎng)這樣:

原來(lái)這個(gè)熵是自信息的一個(gè)期望, 那么就得先看看自信息是什么東西?下面是自信息的公式:

這個(gè)比較好理解了,就是一個(gè)事件發(fā)生的概率,然后取對(duì)數(shù)再取反。也就是一個(gè)事件如果發(fā)生的概率越大,那么自信息就會(huì)少。所有事件發(fā)生的概率都很大,那么熵就會(huì)小,則事件的不確定性就小??磦€(gè)圖就好理解了:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這是一個(gè)兩點(diǎn)分布的一個(gè)信息熵,可以看到,當(dāng)概率是 0.5 的時(shí)候熵最大,也就是事件的不確定性最大,熵大約是 0.69。這個(gè)數(shù)是不是很熟悉?因?yàn)檫@個(gè)在二分類(lèi)模型中經(jīng)常會(huì)碰到,模型訓(xùn)練壞了的時(shí)候,或者剛訓(xùn)練的時(shí)候,我們就會(huì)發(fā)現(xiàn) Loss 值也可能是 0.69,這時(shí)候就說(shuō)模型目前沒(méi)有任何的判斷能力。這就是信息熵的概念。

相對(duì)熵又稱(chēng)為 KL 散度,用來(lái)衡量?jī)蓚€(gè)分布之間的差異,也就是兩個(gè)分布之間的距離,但是不是一個(gè)距離函數(shù),因?yàn)榫嚯x函數(shù)有對(duì)稱(chēng)性,也就是 p 到 q 的距離等于 q 到 p 的距離。而這里的相對(duì)熵不具備這樣的對(duì)稱(chēng)性, 如果看過(guò)我寫(xiě)的生成對(duì)抗原理推導(dǎo)那篇博客的話,那里面也有 KL 散度這個(gè)概念,并且可以通過(guò)組合這個(gè)得到一個(gè)既能夠衡量分布差異也有對(duì)稱(chēng)性的一個(gè)概念叫做 JS 散度。這里先不說(shuō)了,看看這個(gè)公式:

這里的P是數(shù)據(jù)的真實(shí)分布,Q 是模型輸出的分布,這里就是用 Q 的分布去逼近 P 的分布。所以這不具備對(duì)稱(chēng)性。

好了信息熵和相對(duì)熵都說(shuō)了,就可以引出交叉熵了。其實(shí)「交叉熵=信息熵+相對(duì)熵」, 公式如下:

什么?沒(méi)看出交叉熵等于上面兩個(gè)熵之和嗎?那么我們把相對(duì)熵化簡(jiǎn)一下子:

這樣看出來(lái)了吧。

所以,根據(jù)上面的推導(dǎo)我們得到:

在機(jī)器學(xué)習(xí)模型中,我們最小化交叉熵,其實(shí)就是最小化相對(duì)熵,因?yàn)槲覀冇?xùn)練集取出來(lái)之后就是固定的了,熵就是一個(gè)常數(shù)。

好了,我們已經(jīng)知道了交叉熵是衡量?jī)蓚€(gè)分布之間的距離,一個(gè)差異。所以這里使用 softmax,就可以將一個(gè)輸出值轉(zhuǎn)換到概率取值的一個(gè)范圍。我們看看這里的交叉熵?fù)p失函數(shù)是怎么計(jì)算的:

這里的 x 就是我們輸出的概率值,class 就是某一個(gè)類(lèi)別,在括號(hào)里面執(zhí)行了一個(gè) softmax,把某個(gè)神經(jīng)元的輸出歸一化成了概率取值,然后 -log 一下,就得到了交叉熵?fù)p失函數(shù)。我們可以對(duì)比一下我們的交叉熵公式:

由于是某個(gè)樣本,那么 已經(jīng)是 1 了,畢竟取出來(lái)了已經(jīng)。而是某個(gè)樣本,所以也不用求和符號(hào)。

這就是用 softmax 的原因了,把模型的輸出值轉(zhuǎn)成概率分布的形式,這樣就得到了交叉熵?fù)p失函數(shù)。

好了,這里就可以說(shuō)一說(shuō)那些參數(shù)的作用了, 第一個(gè)參數(shù)weight, 各類(lèi)別的 loss 設(shè)置權(quán)值, 如果類(lèi)別不均衡的時(shí)候這個(gè)參數(shù)很有必要了,加了之后損失函數(shù)變成這樣:

這樣,就是如果我們想讓模型更關(guān)注某一類(lèi)的話,就可以把這一類(lèi)的權(quán)值設(shè)置的大一點(diǎn)。第二個(gè)參數(shù)ignore_index, 這個(gè)是表示某個(gè)類(lèi)別不去計(jì)算 loss。而關(guān)于第三個(gè)參數(shù)reduction, 有三個(gè)計(jì)算模式 none/sum/mean, 上面已經(jīng)說(shuō)了,下面我們從代碼中看看這三個(gè)的區(qū)別:

# fake datainputs = torch.tensor([[1, 2], [1, 3], [1, 3]], dtype=torch.float)  # 這里就是模型預(yù)測(cè)的輸出, 這里是兩個(gè)類(lèi),可以看到模型輸出是數(shù)值,我們得softmax一下轉(zhuǎn)成分布target = torch.tensor([011], dtype=torch.long)  # 這里的類(lèi)型必須是long, 兩個(gè)類(lèi)01# 三種模式的損失函數(shù)loss_f_none = nn.CrossEntropyLoss(weight=None, reduction='none')loss_f_sum = nn.CrossEntropyLoss(weight=None, reduction='sum')loss_f_mean = nn.CrossEntropyLoss(weight=None, reduction='mean')# forwardloss_none = loss_f_none(inputs, target)loss_sum = loss_f_sum(inputs, target)loss_mean = loss_f_mean(inputs, target)# viewprint('Cross Entropy Loss:\n ', loss_none, loss_sum, loss_mean)## 結(jié)果:Cross Entropy Loss:  tensor([1.31330.12690.1269]) tensor(1.5671) tensor(0.5224)

這樣可以看到,none 模式下是輸出三個(gè)損失,sum 下是三個(gè)損失求和,mean 下是三個(gè)損失求平均。這里還要注意一下這里的 target, 「這個(gè)是每個(gè)樣本給出屬于哪一個(gè)類(lèi)即可,類(lèi)型是 torch.long, 為什么要強(qiáng)調(diào)這個(gè),我們下面會(huì)學(xué)習(xí)二分類(lèi)交叉熵?fù)p失,是交叉熵?fù)p失函數(shù)的特例,那里的 target 更要注意,對(duì)比起來(lái)更容易理解」

下面我們?cè)偻ㄟ^(guò)代碼看看加上 weight 的損失:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這里可以發(fā)現(xiàn),給類(lèi)別加上權(quán)值之后,對(duì)應(yīng)樣本的損失就會(huì)相應(yīng)的加倍,這里重點(diǎn)是了解一下這個(gè)加上權(quán)之后, mean 模式下怎么計(jì)算的損失:其實(shí)也很簡(jiǎn)單,我們?nèi)齻€(gè)樣本,第一個(gè)權(quán)值為 1, 后兩個(gè)權(quán)值為 2, 所以分母不再是 3 個(gè)樣本,而是 1+2+2, 畢竟后兩個(gè)樣本權(quán)為 2, 一個(gè)樣本頂?shù)谝粋€(gè)的這樣的 2 個(gè)。所以 「mean 模式下求平均不是除以樣本的個(gè)數(shù),而是樣本所占的權(quán)值的總份數(shù)」

3.2.1 還有幾個(gè)交叉熵?fù)p失函數(shù)的特例

「1 nn.NLLoss」

在上面的交叉熵?fù)p失中,我們發(fā)現(xiàn)這個(gè)是softmax和NLLoss的組合,那么這里的nn.NLLLoss是何物???交叉熵?fù)p失里面還有個(gè)這個(gè)東西,其實(shí)這個(gè)東西不要被這個(gè)名字給迷惑了, 這個(gè)就是實(shí)現(xiàn)了一個(gè)負(fù)號(hào)的功能:nn.NLLoss: 實(shí)現(xiàn)負(fù)對(duì)數(shù)似然函數(shù)里面的負(fù)號(hào)功能

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

下面看看這個(gè)東西到底干啥用, 我這樣測(cè)試了一下:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這個(gè)損失函數(shù),就是根據(jù)真實(shí)類(lèi)別去獲得相應(yīng)的 softmax 之后的概率結(jié)果,然后取反就是最終的損失。還別說(shuō),真能反應(yīng)模型好壞,因?yàn)榈谝粋€(gè)類(lèi)分錯(cuò)了,所以損失就大,看到?jīng)]。

「2 nn.BCELoss」

這個(gè)是交叉熵?fù)p失函數(shù)的特例,二分類(lèi)交叉熵。注意:輸入值取值在 [0,1]

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這里的參數(shù)和上面的一樣,也不說(shuō)了, 看看這個(gè)計(jì)算公式吧:

邏輯回歸的時(shí)候,是不是就是這個(gè)公式啊?我們看看代碼中這個(gè)怎么用:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這里首先注意的點(diǎn)就是 target,這里可以發(fā)現(xiàn)和交叉熵那里的標(biāo)簽就不一樣了,首先是類(lèi)型是 float,每個(gè)樣本屬于哪一類(lèi)的時(shí)候要寫(xiě)成獨(dú)熱的那種形式,這是因?yàn)榭磽p失函數(shù)的計(jì)算公式也能看到,每個(gè)神經(jīng)元一一對(duì)應(yīng)的去計(jì)算 loss,而不是一個(gè)整的神經(jīng)元向量去計(jì)算 loss,看結(jié)果也會(huì)發(fā)現(xiàn)有 8 個(gè) loss,因?yàn)槊總€(gè)神經(jīng)元都一一去計(jì)算 loss,根據(jù) inputs,這里是兩個(gè)神經(jīng)元的。

「3 nn.BCEWithLogitsLoss」

這個(gè)函數(shù)結(jié)合了 Sigmoid 與二分類(lèi)交叉熵,注意事項(xiàng):網(wǎng)絡(luò)最后不加sigmoid函數(shù)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這里的參數(shù)多了一個(gè)pow_weight, 這個(gè)是平衡正負(fù)樣本的權(quán)值用的, 對(duì)正樣本進(jìn)行一個(gè)權(quán)值設(shè)定。比如我們正樣本有 100 個(gè),負(fù)樣本有 300 個(gè),那么這個(gè)數(shù)可以設(shè)置為 3,在類(lèi)別不平衡的時(shí)候可以用。

計(jì)算公式如下:

這里了就是加了個(gè) sigmoid。

3.3 剩余的 14 種損失函數(shù)介紹

「1 nn.L1Loss」

這個(gè)用于回歸問(wèn)題,用來(lái)計(jì)算inputs與target之差的絕對(duì)值

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

上面的 size_average 和 reduce 不用再關(guān)注,即將淘汰。而 reduction 這個(gè)三種模式,其實(shí)和上面的一樣。

「2 nn.MSE」

這個(gè)也是用于回歸問(wèn)題,計(jì)算inputs與target之差的平方

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

「3 nn.SmoothL1Loss」

這是平滑的L1Loss(回歸問(wèn)題)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

那么這個(gè)平滑到底是怎么體現(xiàn)的呢?

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

采用這種平滑的損失函數(shù)可以減輕離群點(diǎn)帶來(lái)的影響。

「4 nn.PoissonNLLLoss」

功能:泊松分布的負(fù)對(duì)數(shù)似然損失函數(shù),分類(lèi)里面如果發(fā)現(xiàn)數(shù)據(jù)的類(lèi)別服從泊松分布,可以使用這個(gè)損失函數(shù)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析
  • log_intput: 輸入是否為對(duì)數(shù)形式,決定我們的計(jì)算公式。若為T(mén)rue, . 若為False,
  • full: 計(jì)算所有l(wèi)oss,默認(rèn)為False,這個(gè)一般不用管
  • eps: 修正項(xiàng),避免log(input) 為nan

「5 nn.KLDivLoss」

功能:計(jì)算 KLD, KL 散度,相對(duì)熵,注意:需要提前將輸入計(jì)算 log-probabilities,如通過(guò) nn.logsoftmax()

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

其實(shí)這個(gè)已經(jīng)在上面交叉熵的時(shí)候說(shuō)完了。上面的 Pytorch 里面的計(jì)算和我們?cè)瓉?lái)公式里面的計(jì)算還有點(diǎn)不太一樣,所以我們得自己先 logsoftmax(),完成轉(zhuǎn)換為分布然后轉(zhuǎn)成對(duì)數(shù)才可以。這里的 reduction 還多了一種計(jì)算模式叫做 batchmean,是按照 batchsize 的大小求平均值。

「6 nn.MarginRankingLoss」

功能:計(jì)算兩個(gè)向量之間的相似度,用于排序任務(wù)。特別說(shuō)明,該方法計(jì)算兩組數(shù)據(jù)之間的差異,也就是每個(gè)元素兩兩之間都會(huì)計(jì)算差異,返回一個(gè) n*n 的 loss 矩陣。類(lèi)似于相關(guān)性矩陣那種。

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

margin 表示邊界值,x1 與 x2 之間的差異值。這里的計(jì)算公式如下:

  • y=1時(shí), 希望x1比x2大, 當(dāng)x1>x2時(shí),不產(chǎn)生loss
  • y=-1時(shí), 希望x2比x1大, 當(dāng)x2>x1時(shí), 不產(chǎn)生loss

這個(gè)地方看一下代碼理解吧還是:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

「7 nn.MultiLabelMarginLoss」

功能:多標(biāo)簽邊界損失函數(shù), 這是一個(gè)多標(biāo)簽分類(lèi),就是一個(gè)樣本可能屬于多個(gè)類(lèi),和多分類(lèi)任務(wù)還不一樣。(多標(biāo)簽問(wèn)題)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這個(gè)的計(jì)算公式如下:

這里的 i 取值從 0 到輸出的維度減 1,j 取值也是 0 到 y 的維度減 1,對(duì)于所有的 i 和 j,i 不等于 y[j],也就是標(biāo)簽所在的神經(jīng)元去減掉那些非標(biāo)簽所在的神經(jīng)元,這說(shuō)的啥?一臉懵逼,還是看代碼理解一下吧:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

我們看上面這個(gè)代碼,假設(shè)我們有一個(gè)訓(xùn)練樣本,輸出層 4 個(gè)神經(jīng)元,也就是 4 分類(lèi)的問(wèn)題,前向傳播后,神經(jīng)網(wǎng)絡(luò)的四個(gè)神經(jīng)元的輸出分別是 [0.1, 0.2, 0.4, 0.8],而這個(gè)樣本的真實(shí)標(biāo)簽是 [0, 3, -1, -1], 首先解釋這是啥意思,就是說(shuō)這個(gè)樣本屬于第 0 類(lèi)和第 3 類(lèi),這個(gè)地方必須是 torch.long 型,并且必須和輸出神經(jīng)元個(gè)數(shù)一樣,屬于哪幾類(lèi)寫(xiě)前面,不夠長(zhǎng)度的用 -1 填補(bǔ)。使用多標(biāo)簽邊界損失函數(shù)的時(shí)候,具體計(jì)算就是下面那樣:

我們的輸入樣本屬于 0 和 3 這兩類(lèi),不屬于 1 和 2, 那么就根據(jù)上面那個(gè)公式,后面那部分是標(biāo)簽所在的神經(jīng)元減去標(biāo)簽不不在的神經(jīng)元, 比如標(biāo)簽在第0個(gè)神經(jīng)元:

item_1 = (1-(x[0]-x[1])) + (1-(x[0]-x[2]))     # 標(biāo)簽在第0個(gè)神經(jīng)元的時(shí)候item_2 = (1-(x[3]-x[1])) + (1-(x[3]-x[2]))    # 標(biāo)簽在第3個(gè)神經(jīng)元的時(shí)候loss = (item_1+item_3) / x.shape[0]  # 然后就是這兩部分的損失相加除以總的神經(jīng)元個(gè)數(shù)

應(yīng)該差不多明白這個(gè)過(guò)程了,可以為啥要這么做呢? 這個(gè)意思就是說(shuō)我們希望「標(biāo)簽所在的神經(jīng)元要比非標(biāo)簽所在的神經(jīng)元的輸出值要盡量的大」,當(dāng)這個(gè)差大于 1 了, 我們根據(jù)max(0, 1-差值), 才發(fā)現(xiàn)不會(huì)有損失產(chǎn)生, 當(dāng)這個(gè)差值小或者非標(biāo)簽所在的神經(jīng)元比標(biāo)簽所在神經(jīng)元大的時(shí)候,都會(huì)產(chǎn)生損失。所以上面那個(gè)例子,我們想讓第 0 個(gè)神經(jīng)元的值要比第 1 個(gè),第二個(gè)大一些,第 3 個(gè)神經(jīng)元的值要比第 1 個(gè),第 2 個(gè)大一些,這才能說(shuō)明這個(gè)樣本屬于第 0 類(lèi)和第 3 類(lèi),才是我們想要的結(jié)果啊。有沒(méi)有一點(diǎn) hinge loss 的意思?只不過(guò)那里是多分類(lèi),而這里是多標(biāo)簽分類(lèi),感覺(jué)思想差不多。

「8 nn.SoftMarginLoss」

功能:計(jì)算二分類(lèi)的 logistic 損失(二分類(lèi)問(wèn)題)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

計(jì)算公式如下:

「9 nn.MultiLabelSortMarginLoss」

功能:SoftMarginLoss 多標(biāo)簽版本 (多標(biāo)簽問(wèn)題)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

之類(lèi)的 weight,表示各類(lèi)別的 loss 設(shè)置權(quán)值。計(jì)算公式如下:

這個(gè)理解起來(lái)也不是那么好理解,也是看看代碼怎么計(jì)算:我們這里是一個(gè)三分類(lèi)的任務(wù),輸入的這個(gè)樣本屬于第二類(lèi)和第三類(lèi):

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

「10 nn.MultiMarginLoss(hingLoss)」

功能:計(jì)算多分類(lèi)的折頁(yè)損失(多分類(lèi)問(wèn)題)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這里的 p 可選 1 或者 2,margin 表示邊界值。計(jì)算公式如下:

這里的 x, y 是 0 - 神經(jīng)元個(gè)數(shù)減 1,并且對(duì)于所以 i 和 j,i 不等于 y[j]。這里就類(lèi)似于 hing loss 了,這里的 x[y] 表示標(biāo)簽所在的神經(jīng)元,x[i] 表示非標(biāo)簽所在的神經(jīng)元。還是先看個(gè)例子,了解一下這個(gè)計(jì)算過(guò)程,然后借著這個(gè)機(jī)會(huì)也說(shuō)一說(shuō) hing loss 吧:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這個(gè)其實(shí)和多標(biāo)簽邊界損失函數(shù)的原理差不多,只不過(guò)那里是一個(gè)樣本屬于多個(gè)類(lèi),需要每個(gè)類(lèi)都這樣算算,而這里一個(gè)樣本屬于 1 個(gè)類(lèi),只計(jì)算一次即可。這個(gè)其實(shí)就是我們的 hinge loss 損失,我們可以看一下:

這個(gè)地方的原理啥的就先不推了:

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

假如我們現(xiàn)在有三個(gè)類(lèi)別,而得分函數(shù)計(jì)算某張圖片的得分為 ,而實(shí)際結(jié)果是第一類(lèi)( )。假設(shè) ,這個(gè)就是上面的 margin,那么上面的公式就把錯(cuò)誤類(lèi)別 () 都遍歷了一遍,求值加和:

這個(gè)損失和交叉熵?fù)p失是不同的兩種評(píng)判標(biāo)準(zhǔn),這個(gè)損失聚焦于分類(lèi)錯(cuò)誤的與正確類(lèi)別之間的懲罰距離越小越好,而交叉熵?fù)p失聚焦分類(lèi)正確的概率分布越大越好。

「11 nn.TripletMarginLoss」

功能:計(jì)算三元組損失,人臉驗(yàn)證中常用

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這里的 p 表示范數(shù)的階。計(jì)算公式:

三元組在做這么個(gè)事情, 我們?cè)谧鋈四樧R(shí)別訓(xùn)練模型的時(shí)候,往往需要把訓(xùn)練集做成三元組 (A, P, N), A 和 P 是同一個(gè)人,A 和 N 不是同一個(gè),然后訓(xùn)練我們的模型

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

我們想讓模型把 A 和 P 看成一樣的,也就是爭(zhēng)取讓 A 和 P 之間的距離小,而 A 和 N 之間的距離大,那么我們的模型就能夠進(jìn)行人臉識(shí)別任務(wù)了。

「12 nn.HingeEmbeddingLoss」

功能:算兩個(gè)輸入的相似性,常用于非線性 embedding 和半監(jiān)督學(xué)習(xí)。特別注意,輸入的x應(yīng)為兩個(gè)輸入之差的絕對(duì)值, 也就是手動(dòng)計(jì)算兩個(gè)輸入的差值

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

計(jì)算公式如下:

「13 nn.CosineEmbeddingLoss」

功能:采用余弦相似度計(jì)算兩個(gè)輸入的相似性,常用于半監(jiān)督學(xué)習(xí)和 embedding

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

這里的 margin 可取值 [-1, 1],推薦為 [0,0.5]。計(jì)算公式如下:

之所以用 cos, 希望關(guān)注于這兩個(gè)輸入方向上的一個(gè)差異,而不是距離上的差異,cos 函數(shù)如下:

「14 nn.CTCLoss」

功能:計(jì)算 CTC 損失, 解決時(shí)序類(lèi)數(shù)據(jù)的分類(lèi)

機(jī)器學(xué)習(xí)「Pytorch 」筆記六:初始化與 18 種損失函數(shù)的源碼解析

blank: blank label, zeor_infinity: 無(wú)窮大的值或者梯度置 0,這個(gè)使用起來(lái)比較復(fù)雜,所以具體的可以看看官方文檔。

到這里,18 種損失函數(shù)就介紹完了,哇,太多了,這哪能記得住啊, 所以我們可以對(duì)這些損失函數(shù)從任務(wù)的角度分分類(lèi),到時(shí)候看看是什么任務(wù),然后看看有哪些損失函數(shù)可以用,再去查具體用法就可以啦。我這邊是這樣分的:

  • 「分類(lèi)問(wèn)題」
    • 「二分類(lèi)單標(biāo)簽問(wèn)題」nn.BCELoss, nn.BCEWithLogitsLoss, nn.SoftMarginLoss
    • 「二分類(lèi)多標(biāo)簽問(wèn)題」nn.MultiLabelSoftMarginLoss
    • 「多分類(lèi)單標(biāo)簽問(wèn)題」: nn.CrossEntropyLoss, nn.NLLLoss, nn.MultiMarginLoss
    • 「多分類(lèi)多標(biāo)簽問(wèn)題」: nn.MultiLabelMarginLoss,
    • 「不常用」nn.PoissonNLLLoss, nn.KLDivLoss
  • 「回歸問(wèn)題」: nn.L1Loss, nn.MSELoss, nn.SmoothL1Loss
  • 「時(shí)序問(wèn)題」nn.CTCLoss
  • 「人臉識(shí)別問(wèn)題」nn.TripletMarginLoss
  • 「半監(jiān)督Embedding問(wèn)題(輸入之間的相似性)」: nn.MarginRankingLoss, nn.HingeEmbeddingLoss, nn.CosineEmbeddingLoss

4.總結(jié)

今天的內(nèi)容就到這里了,這次整理的內(nèi)容還是比較多的,主要分為兩大塊:權(quán)重初始化和損失函數(shù)的介紹, 第一塊里面有 10 中權(quán)重初始化方法,而第二塊里面18種損失函數(shù)。哇,這個(gè)知識(shí)量還是很大的,當(dāng)然我們其實(shí)并不需要都記住,只知道有哪些方法,具體什么時(shí)候用就行了,這個(gè)系列的目的也不是要求一下子都會(huì)了, 而是先有個(gè)框架出來(lái)??焖偈崂硪槐榘桑?/span>

  • 首先,我們解決了模型模塊的小尾巴, 權(quán)重的初始化方法,我們學(xué)習(xí)了梯度消失和梯度爆炸的原理,也知道了權(quán)重初始化的重要性,針對(duì)各種情況學(xué)習(xí)了不同的初始化方法,重要的是Xavier初始化和Kaiming初始化方法, 分別針對(duì)非飽和激活函數(shù)和包含激活函數(shù)的網(wǎng)絡(luò)。
  • 然后學(xué)習(xí)了損失函數(shù)的相關(guān)知識(shí),通過(guò)損失函數(shù)的初步介紹,我們知道了損失函數(shù)也是一個(gè)Module,那么初始化和運(yùn)行機(jī)制就基本了解。然后學(xué)習(xí)了交叉熵?fù)p失函數(shù)及四個(gè)特例, 交叉熵?fù)p失函數(shù)比較重要,所以學(xué)習(xí)了一下原理,從自信息,熵,相對(duì)熵到交叉熵都過(guò)了一遍。最后又根據(jù)場(chǎng)景的不同學(xué)習(xí)了其他14種損失函數(shù)。

好了,損失函數(shù)模塊到這里就結(jié)束了,后面進(jìn)入優(yōu)化器部分, 我們還是那個(gè)流程:數(shù)據(jù)模塊 -> 模型模塊 -> 損失函數(shù)模塊 -> 優(yōu)化器 -> 迭代訓(xùn)練。我們已經(jīng)完成了3個(gè)模塊的學(xué)習(xí),馬上就要看到曙光,再堅(jiān)持一下, rush ;)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    青青操视频在线播放免费| 麻豆视频传媒入口在线看| 中文字幕日韩欧美一区| 国产中文字幕一二三区| 91精品国产综合久久精品| 欧美一级内射一色桃子| 国产午夜福利一区二区| 国产色一区二区三区精品视频 | 日韩精品日韩激情日韩综合| 日本熟女中文字幕一区| 东京热男人的天堂久久综合| 99香蕉精品视频国产版| 日韩人妻av中文字幕| 亚洲国产精品一区二区毛片| 一级片黄色一区二区三区| 国产欧美韩日一区二区三区| 大胆裸体写真一区二区| 国产一区二区三区香蕉av| 国产免费操美女逼视频| 欧美激情一区二区亚洲专区| 免费在线成人激情视频| 好吊妞视频这里有精品| 视频在线观看色一区二区| 九九热精彩视频在线播放| 人妻少妇久久中文字幕久久| 99久只有精品免费视频播放| 日韩美成人免费在线视频| 日本不卡一本二本三区| 亚洲第一视频少妇人妻系列| 国产精品激情对白一区二区| 欧美亚洲国产日韩一区二区| 国产精品免费自拍视频| 人妻内射在线二区一区| 最新日韩精品一推荐日韩精品| 久久福利视频视频一区二区| 日韩一级欧美一级久久| 少妇激情在线免费观看| 高清免费在线不卡视频| 男人大臿蕉香蕉大视频| 狠狠干狠狠操亚洲综合| 中文字幕乱码亚洲三区|