Lesson 8.5 SOFTMAX回归
三、多分類(lèi)神經(jīng)網(wǎng)絡(luò):Softmax回歸
1 認(rèn)識(shí)softmax函數(shù)
之前介紹分類(lèi)神經(jīng)網(wǎng)絡(luò)時(shí),我們只說(shuō)明了二分類(lèi)問(wèn)題,即標(biāo)簽只有兩種類(lèi)別的問(wèn)題(0和1,貓和狗)。 雖然在實(shí)際應(yīng)用中,許多分類(lèi)問(wèn)題都可以用二分類(lèi)的思維解決,但依然存在很多多分類(lèi)的情況,最典型的就是手寫(xiě)數(shù)字的識(shí)別問(wèn)題。計(jì)算機(jī)在識(shí)別手寫(xiě)數(shù)字時(shí),需要對(duì)每一位數(shù)字進(jìn)行判斷,而個(gè)位數(shù)字總共有10個(gè)(09),所以手寫(xiě)數(shù)字的分類(lèi)是十分類(lèi)問(wèn)題,一般分別用0-9表示。
在之前展示深度學(xué)習(xí)中的數(shù)據(jù)時(shí),我們也展示過(guò)另一個(gè)數(shù)據(jù)集的標(biāo)簽:
這個(gè)數(shù)據(jù)集是對(duì)服裝樣式進(jìn)行分類(lèi),從它標(biāo)簽也可以看出來(lái),這也是一個(gè)多分類(lèi)問(wèn)題。正常來(lái)說(shuō),我們都對(duì)多分類(lèi)的類(lèi)別按整數(shù)[1,+∞]的數(shù)字進(jìn)行編號(hào),比較少有使用0類(lèi)的情況。
在機(jī)器學(xué)習(xí)中,我們會(huì)使用二分類(lèi)算法的Many-vs-Many(多對(duì)多)和One-vs-Rest (一對(duì)多)模式來(lái)進(jìn)行多分類(lèi)。其中,OvR是指將多個(gè)標(biāo)簽類(lèi)別中的一類(lèi)作為類(lèi)別1,其他所有類(lèi)別作為類(lèi)別0,分別建立多個(gè)二分類(lèi)模型,綜合得出多分類(lèi)結(jié)果的方法。MvM是指把好幾個(gè)標(biāo)簽類(lèi)作為1,剩下的幾個(gè)標(biāo)簽類(lèi)別作為0,同樣分別建立多個(gè)二分類(lèi)模型來(lái)得出多分類(lèi)結(jié)果的方法。這兩種方法非常有效,尤其是在邏輯回歸 做多分類(lèi)的問(wèn)題上能夠解決很多問(wèn)題,但是在深度學(xué)習(xí)世界卻完全不奏效。理由非常簡(jiǎn)單:
Softmax函數(shù)是深度學(xué)習(xí)基礎(chǔ)中的基礎(chǔ),它是神經(jīng)網(wǎng)絡(luò)進(jìn)行多分類(lèi)時(shí),默認(rèn)放在輸出層中處理數(shù)據(jù)的函數(shù)。假設(shè)現(xiàn)在神經(jīng)網(wǎng)絡(luò)是用于三分類(lèi)數(shù)據(jù),且三個(gè)分類(lèi)分別是蘋(píng)果,檸檬和百香果,序號(hào)則分別是分類(lèi) 1、分類(lèi)2和分類(lèi)3。則使用softmax函數(shù)的神經(jīng)網(wǎng)絡(luò)的模型會(huì)如下所示:
與二分類(lèi)一樣,我們從網(wǎng)絡(luò)左側(cè)輸入特征,從右側(cè)輸出概率,且概率是通過(guò)線性回歸的結(jié)果zzz外嵌套softmax函數(shù)來(lái)進(jìn)行計(jì)算。在二分類(lèi)時(shí),輸出層只有一個(gè)神經(jīng)元,只輸出樣本對(duì)于正類(lèi)別的概率(通常是標(biāo)簽為1的概率),而softmax的輸出層有三個(gè)神經(jīng)元,分別輸出該樣本的真實(shí)標(biāo)簽是蘋(píng)果、檸檬或百香果的概率 。在多分類(lèi)中,神經(jīng)元的個(gè)數(shù)與標(biāo)簽類(lèi)別的個(gè)數(shù)是一致的,如果是十分類(lèi),在輸出層上就會(huì)存在十個(gè)神經(jīng)元,分別輸出十個(gè)不同的概率。此時(shí),樣本的預(yù)測(cè)標(biāo)簽就是所有輸出的概率中最大的概率對(duì)應(yīng)的標(biāo)簽類(lèi)別。
那每個(gè)概率是如何計(jì)算出來(lái)的呢?來(lái)看Softmax函數(shù)的公式:
σk=Softmax?(zk)=ezk∑Kez\sigma_{k}=\operatorname{Softmax}\left(z_{k}\right)=\frac{e^{z_{k}}}{\sum^{K} e^{z}} σk?=Softmax(zk?)=∑Kezezk??
其中eee為自然常數(shù)(約為2.71828),zzz與sigmoid函數(shù)中的zzz一樣,表示回歸類(lèi)算法(如線性回歸)的結(jié)果。K表示該數(shù)據(jù)的標(biāo)簽中總共有K個(gè)標(biāo)簽類(lèi)別,如三分類(lèi)時(shí)K=3,四分類(lèi)時(shí)K=4。kkk表示標(biāo)簽類(lèi)別kkk類(lèi)。很容易可以看出,Softmax函數(shù)的分子是多分類(lèi)狀況下某一個(gè)標(biāo)簽類(lèi)別的回歸結(jié)果的指數(shù)函數(shù),分母是多分類(lèi)狀況下所有標(biāo)簽類(lèi)別的回歸結(jié)果的指數(shù)函數(shù)之和,因此Softmax函數(shù)的結(jié)果代表了樣本的結(jié)果為類(lèi)別kkk的概率。
舉個(gè)例子,當(dāng)我們有三個(gè)分類(lèi),分別是蘋(píng)果,梨,百香果的時(shí)候,樣本i被分類(lèi)為百香果的概率σ百香果\sigma_{百香果}σ百香果?為:
2 PyTorch中的softmax函數(shù)
我們?cè)?jīng)提到過(guò),神經(jīng)網(wǎng)絡(luò)是模型效果很好,但運(yùn)算速度非常緩慢的算法。 softmax函數(shù)也存在相同的問(wèn)題——它可以將多分類(lèi)的結(jié)果轉(zhuǎn)變?yōu)楦怕?#xff08;這是一個(gè)極大的優(yōu)勢(shì)),但它需要的計(jì)算量非常巨大。由于softmax的分子和分母中都帶有為底的指數(shù)函數(shù),所以在計(jì)算中非常容易出現(xiàn)極大的數(shù)值。
如上圖所示,就已經(jīng)等于20000了,而回歸結(jié)果完全可能是成千上萬(wàn)的數(shù)字。事實(shí)上會(huì)變成一個(gè)后面有40多個(gè)0的超大值,則會(huì)直接返回?zé)o限大inf,這意味著這些數(shù)字已經(jīng)超出了計(jì)算機(jī)處理數(shù)時(shí)要求的有限數(shù)據(jù)寬度,超大數(shù)值無(wú)法被計(jì)算機(jī)運(yùn)算和表示。這種現(xiàn)象叫做“溢出“,當(dāng)計(jì)算機(jī)返回”內(nèi)存不足”或Python服務(wù)器直接斷開(kāi)連接的時(shí)候,可能就是發(fā)生了這個(gè)問(wèn)題。來(lái)看看這個(gè)問(wèn)題實(shí)際發(fā)生時(shí)的狀況:
因此,我們一般不會(huì)親自使用tensor來(lái)手寫(xiě)softmax函數(shù)。在PyTorch中,我們往往使用內(nèi)置好的softmax函數(shù)來(lái)計(jì)算softmax的結(jié)果,我們可以使用torch.softmax來(lái)輕松的調(diào)用它,具體代碼如下:
z = torch.tensor([1010,1000,990], dtype=torch.float32) torch.softmax(z,0) #你也可以使用F.softmax, 它返回的結(jié)果與torch.softmax是完全一致的 #tensor([9.9995e-01, 4.5398e-05, 2.0611e-09])可以看出,同樣的數(shù)據(jù)在PyTorch的softmax計(jì)算下,不會(huì)發(fā)生溢出問(wèn)題,這是因?yàn)镻yTorch使用了一些巧妙地手段來(lái)解決溢出問(wèn)題,感興趣地小伙伴可以自行閱讀本節(jié)最后的加餐內(nèi)容。如果我們將調(diào)整到較小的數(shù)值,可以發(fā)現(xiàn),手寫(xiě)的softmax函數(shù)與torch庫(kù)自帶的softmax返回的結(jié)果是一模一樣的。
#假設(shè)三個(gè)輸出層神經(jīng)元得到的z分別是10,9,5 z = torch.tensor([10,9,5], dtype=torch.float32) torch.exp(z) / torch.sum(torch.exp(z)) # softmax函數(shù)的運(yùn)算 #tensor([0.7275, 0.2676, 0.0049]) z = torch.tensor([10,9,5], dtype=torch.float32) torch.softmax(z,0) #tensor([0.7275, 0.2676, 0.0049])從上面的結(jié)果可以看出,softmax函數(shù)輸出的是從0到1.0之間的實(shí)數(shù),而且多個(gè)輸出值的總和是1。因?yàn)橛辛诉@個(gè)性質(zhì),我們可以把softmax函數(shù)的輸出解釋為“概率”,這和我們使用sigmoid函數(shù)之后認(rèn)為函數(shù)返回的結(jié)果是概率異曲同工。從結(jié)果來(lái)看,我們可以認(rèn)為返回了我們?cè)O(shè)定的([10,9,5])的這個(gè)樣本的結(jié)果應(yīng)該是第一個(gè)類(lèi)別(也就是z=10的類(lèi)別),因?yàn)轭?lèi)別1的概率是最大的(實(shí)際上幾乎達(dá)到了99.9%)。
需要注意的是,使用了softmax函數(shù)之后,各個(gè)之間的大小關(guān)系并不會(huì)隨之改變,這是因?yàn)橹笖?shù)函數(shù)是單調(diào)遞增函數(shù),也就是說(shuō),使用softmax之前的如果比較大,那使用softmax之后返回的概率也依然比較大。這是說(shuō),無(wú)論是否使用softmax,我們都可以判斷出樣本被預(yù)測(cè)為哪一類(lèi),我們只需要看最大的那一類(lèi)就可以了。所以,在神經(jīng)網(wǎng)絡(luò)進(jìn)行分類(lèi)的時(shí)候,如果不需要了解具體分類(lèi)問(wèn)題每一類(lèi)的概率是多少,而只需要知道最終的分類(lèi)結(jié)果,我們可以省略輸出層上的softmax函數(shù)。
但如果,你確實(shí)遇見(jiàn)了需要自己計(jì)算的情況,你就可以使用torch中的softmax函數(shù)。大家可能有注意到,torch中的softmax函數(shù)有兩個(gè)參數(shù),第一個(gè)參數(shù)是我們輸入的用來(lái)進(jìn)行計(jì)算的張量z,另一個(gè)參數(shù)我輸入了0。這其實(shí)代表了你希望運(yùn)行softmax計(jì)算的維度的索引。
softmax函數(shù)只能對(duì)單一維度進(jìn)行計(jì)算,它只能夠識(shí)別單一維度上的不同類(lèi)別,但我們輸入softmax的張量卻可能是一個(gè)很高維的張量。比如:
s = torch.tensor([[[1,2],[3,4],[5,6]],[[5,6],[7,8],[9,10]]], dtype=torch.float32) s.ndim #3 s.shape #torch.Size([2, 3, 2])對(duì)于s而言,我們現(xiàn)在有三個(gè)維度——最外層代表了“2個(gè)二維張量”,3則代表每個(gè)二維張量中有3行,最后的2則代表每個(gè)二維張量中有2列。此時(shí),我們可以從外向內(nèi)索引我們的維度,索引0對(duì)應(yīng)的就是最外層,索引2對(duì)應(yīng)的就是最里層,相似的,我們也可以反向索引,-1對(duì)應(yīng)的就是最里層,-3對(duì)應(yīng)的就是最外層。所以softmax函數(shù)中需要我們輸入的,就是我們希望在哪個(gè)維度上進(jìn)行softmax運(yùn)算。
torch.softmax(s,dim=0) #在整個(gè)張量中,有2個(gè)張量,一個(gè)二維張量就是一類(lèi) #tensor([[[0.0180, 0.0180], # [0.0180, 0.0180], # [0.0180, 0.0180]], # # [[0.9820, 0.9820], # [0.9820, 0.9820], # [0.9820, 0.9820]]]) torch.softmax(s,dim=1) #在一個(gè)二維張量中,有3行數(shù)據(jù),每一行是一種類(lèi)別 #tensor([[[0.0159, 0.0159], # [0.1173, 0.1173], # [0.8668, 0.8668]], # # [[0.0159, 0.0159], # [0.1173, 0.1173], # [0.8668, 0.8668]]]) torch.softmax(s,dim=2) #在每一行中,有4個(gè)數(shù)據(jù),每個(gè)數(shù)據(jù)是一種類(lèi)別 #tensor([[[0.2689, 0.7311], # [0.2689, 0.7311], # [0.2689, 0.7311]], # # [[0.2689, 0.7311], # [0.2689, 0.7311], # [0.2689, 0.7311]]])看到計(jì)算的結(jié)果,你明白這個(gè)維度的含義了嗎?實(shí)際上softmax函數(shù)在實(shí)際中應(yīng)用不多,但是只要用到,新手就一定會(huì)被繞進(jìn)dim參數(shù)的選項(xiàng)中去,因此我們?cè)谶@里特此說(shuō)明。
在實(shí)際中,訓(xùn)練神經(jīng)網(wǎng)絡(luò)時(shí)往往會(huì)使用softmax函數(shù),但在預(yù)測(cè)時(shí)就不再使用softmax函數(shù),而是直接讀取結(jié)果最大的對(duì)應(yīng)的類(lèi)別了。但無(wú)論如何,了解softmax是必要的,也是非常有用的。
3 使用nn.Linear與functional實(shí)現(xiàn)多分類(lèi)神經(jīng)網(wǎng)絡(luò)的正向傳播
學(xué)到這里,我相信你應(yīng)該能夠?qū)懗鰏oftmax回歸的正向傳播代碼。請(qǐng)使用如下的數(shù)據(jù):
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)我強(qiáng)烈建議你先進(jìn)行思考,對(duì)照下面的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu),嘗試自己寫(xiě)一寫(xiě)這段代碼,然后再查看答案。在這里你需要弄明白這些問(wèn)題:
4 【加餐】解決Softmax的溢出問(wèn)題
為了解決softmax函數(shù)的溢出問(wèn)題,我們需要對(duì)softmax的公式進(jìn)行如下更改。首先,在分子和分母上都乘上常數(shù)C。因?yàn)橥瑫r(shí)對(duì)分母和分子乘以相同的常數(shù),所以計(jì)算結(jié)果不變。然后,把這個(gè)C移動(dòng)到指數(shù)函數(shù)中,計(jì)作elog?Ce^{\log C}elogC,在這里log指的是以自然底數(shù)e為底的對(duì)數(shù)函數(shù)。只要C大于0,logC就必然存在,此時(shí)我們可以把logC替換為另一個(gè)符號(hào)C’ ,它同樣代表了一個(gè)常數(shù)。即是說(shuō),其實(shí)我們只需要在softmax函數(shù)的兩個(gè)指數(shù)函數(shù)自變量上都加上一個(gè)常數(shù)就可以了,這樣做不會(huì)改變計(jì)算結(jié)果。
ok=ezk∑i=1Kezi=CezkC∑i=1Kezi=elog?C?ezk∑i=1Kelog?C?ezi=e(zk+log?C)∑i=1Ke(zi+log?C)=e(zk+C′)∑i=1Ke(zi+C′)\begin{aligned} o_{k} &=\frac{e^{z_{k}}}{\sum_{i=1}^{K} e^{z_{i}}} \\ &=\frac{C e^{z_{k}}}{C \sum_{i=1}^{K} e^{z_{i}}} \\ &=\frac{e^{\log C} \cdot e^{z_{k}}}{\sum_{i=1}^{K} e^{\log C} \cdot e^{z_{i}}} \\ &=\frac{e^{\left(z_{k}+\log C\right)}}{\sum_{i=1}^{K} e^{\left(z_{i}+\log C\right)}} \\ &=\frac{e^{\left(z_{k}+C^{\prime}\right)}}{\sum_{i=1}^{K} e^{\left(z_{i}+C^{\prime}\right)}} \end{aligned} ok??=∑i=1K?ezi?ezk??=C∑i=1K?ezi?Cezk??=∑i=1K?elogC?ezi?elogC?ezk??=∑i=1K?e(zi?+logC)e(zk?+logC)?=∑i=1K?e(zi?+C′)e(zk?+C′)??
現(xiàn)在來(lái)思考,加入一個(gè)怎樣的C’才會(huì)對(duì)抑制計(jì)算溢出最有效呢?我們是希望避免十分巨大的zzz,因此我們只要讓C’的符號(hào)為負(fù)號(hào),在讓其大小接近zkz_{k}zk?中的最大值就可以了。來(lái)看看在python中我們?nèi)绾尾僮?#xff1a;
來(lái)看看剛才求出的softmax函數(shù)的結(jié)果加和之后會(huì)顯示怎樣的效果:
sum(softmax(z)) #1.0四、回歸vs二分類(lèi)vs多分類(lèi)
到這里,我們已經(jīng)見(jiàn)過(guò)了三個(gè)不同的神經(jīng)網(wǎng)絡(luò):
注意到有什么相似和不同了嗎?
首先可能會(huì)注意到的是,這三個(gè)神經(jīng)網(wǎng)絡(luò)都是單層神經(jīng)網(wǎng)絡(luò),除了輸入層,他們都有且只有一層網(wǎng)絡(luò)。實(shí)際上,現(xiàn)實(shí)中使用的神經(jīng)網(wǎng)絡(luò)幾乎99%都是多層的,但我們的網(wǎng)絡(luò)也能夠順利進(jìn)行預(yù)測(cè),這說(shuō)明單層神經(jīng)網(wǎng)絡(luò)其實(shí)已經(jīng)能夠?qū)崿F(xiàn)基本的預(yù)測(cè)功能。同時(shí),這也說(shuō)明了一個(gè)問(wèn)題,無(wú)論處理的是回歸還是分類(lèi),神經(jīng)網(wǎng)絡(luò)的處理原理是一致的。實(shí)際上,就連算法的限制、優(yōu)化方法和求解方法也都是一致的。回歸和分類(lèi)神經(jīng)網(wǎng)絡(luò)唯一的不同只有輸出層上的σ\sigmaσ 。
雖然線性回歸看起來(lái)并沒(méi)有的存在,但實(shí)際上我們可以認(rèn)為線性回歸中的是一個(gè)恒等函數(shù)(identity function),即是說(shuō)σ(z)=z\sigma(z)=zσ(z)=z(相當(dāng)于y=xy = xy=x,或f(x)=xf(x) = xf(x)=x )。而多分類(lèi)的時(shí)候也可以不采用任何函數(shù),只觀察zzz的大小,所以多分類(lèi)也可以被認(rèn)為是利用了恒等函數(shù)作為σ\sigmaσ。總結(jié)來(lái)說(shuō),回歸和分類(lèi)對(duì)應(yīng)的分別如下:
第二個(gè)很容易發(fā)現(xiàn)的現(xiàn)象是,只有多分類(lèi)的情況在輸出層出現(xiàn)了超過(guò)一個(gè)神經(jīng)元。實(shí)際上,當(dāng)處理單標(biāo)簽問(wèn)題時(shí)(即只有一個(gè)y的問(wèn)題),回歸神經(jīng)網(wǎng)絡(luò)和二分類(lèi)神經(jīng)網(wǎng)絡(luò)的輸出層永遠(yuǎn)只有一個(gè)神經(jīng)元,而只有多分類(lèi)的情況才會(huì)讓輸出層上超過(guò)一個(gè)神經(jīng)元。為了方便計(jì)算和演示,在之后的課程中我們都會(huì)使用二分類(lèi)神經(jīng)網(wǎng)絡(luò)作為例子。
總結(jié)
以上是生活随笔為你收集整理的Lesson 8.5 SOFTMAX回归的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Lesson 8.38.4 二分类神经网
- 下一篇: Lesson 9.5 从0实现多层神经网