Lesson 8.38.4 二分类神经网络torch.nn.functional实现单层二分类网络的正向传播
二、二分類神經(jīng)網(wǎng)絡(luò):邏輯回歸
1 二分類神經(jīng)網(wǎng)絡(luò)的理論基礎(chǔ)
線性回歸是統(tǒng)計學(xué)經(jīng)典算法,它能夠擬合出一條直線來描述變量之間的線性關(guān)系。但在實(shí)際中,變量之間的關(guān)系通常都不是一條直線,而是呈現(xiàn)出某種曲線關(guān)系。在統(tǒng)計學(xué)的歷史中,為了讓統(tǒng)計學(xué)模型能夠更好地擬合曲線,統(tǒng)計學(xué)家們在線性回歸的方程兩邊引入了聯(lián)系函數(shù)(link function),對線性回歸的方程做出了各種樣的變化,并將這些變化后的方程稱為“廣義線性回歸”。其中比較著名的有等式兩邊同時取對數(shù)的對數(shù)函數(shù)回歸、同時取指數(shù)的S形函數(shù)回歸等。
y=ax+b→ln?y=ln?(ax+b)y=ax+b→ey=eax+b\begin{array}{l} y=a x+b \rightarrow \ln y=\ln (a x+b) \\ y=a x+b \rightarrow e^{y}=e^{a x+b} \end{array} y=ax+b→lny=ln(ax+b)y=ax+b→ey=eax+b?
在探索的過程中,一種奇特的變化吸引了統(tǒng)計學(xué)家們的注意,這個變化就是sigmoid函數(shù)帶來的變化。Sigmoid函數(shù)的公式如下:
σ=Sigmoid?(z)=11+e?z\sigma=\operatorname{Sigmoid}(z)=\frac{1}{1+e^{-z}} σ=Sigmoid(z)=1+e?z1?
其中eee為自然常數(shù)(約為2.71828),其中zzz是它的自變量,σ\sigmaσ是因變量,zzz的值常常是線性模型的取值(比如,線性回歸的結(jié)果zzz)。 Sigmoid函數(shù)是一個S型的函數(shù),它的圖像如下:
從圖像上就可以看出,這個函數(shù)的性質(zhì)相當(dāng)特別。當(dāng)自變量zzz趨近正無窮時,因變量σ\sigmaσ趨近于1,而當(dāng)zzz趨近負(fù)無窮時,σ\sigmaσ趨近于0,這使得sigmoid函數(shù)能夠?qū)⑷魏螌?shí)數(shù)映射到(0,1)區(qū)間。同時,Sigmoid的導(dǎo)數(shù)在zzz=0點(diǎn)時最大(這一點(diǎn)的斜率最大),所以它可以快速將數(shù)據(jù)從zzz=0的附近排開,讓數(shù)據(jù)點(diǎn)到遠(yuǎn)離自變量取0的地方去。這樣的性質(zhì),讓sigmoid函數(shù)擁有將連續(xù)性變量zzz=0轉(zhuǎn)化為離散型變量σ\sigmaσ的力量,這也就是化回歸算法為分類算法的力量。
具體怎么操作呢?只要將線性回歸方程的結(jié)果作為自變量帶入sigmoid函數(shù),得出的數(shù)據(jù)就一定是(0,1) 之間的值。此時,只要我們設(shè)定一個閾值(比如0.5),規(guī)定σ\sigmaσ大于0.5時,預(yù)測結(jié)果為1類,σ\sigmaσ小于0.5時,預(yù)測結(jié)果為0類,則可以順利將回歸算法轉(zhuǎn)化為分類算法。此時,我們的標(biāo)簽就是類別0和1了。這個閾值可以自己調(diào)整,在沒有調(diào)整之前,一般默認(rèn)0.5。
σ=11+e?z=11+e?Xw\sigma=\frac{1}{1+e^{-z}}=\frac{1}{1+e^{-\boldsymbol{X} \boldsymbol{w}}} σ=1+e?z1?=1+e?Xw1?
更神奇的是,當(dāng)我們對線性回歸的結(jié)果取sigmoid函數(shù)之后,只要再進(jìn)行以下操作:
1)將結(jié)果以幾率(σ1?σ)\left(\frac{\sigma}{1-\sigma}\right)(1?σσ?)的形式展現(xiàn)
2)在幾率上求以e為底的對數(shù)
ln?σ1?σ=ln?(11+e?Xw1?11+e?Xw)=ln?(11+e?Xwe?Xw1+e?Xw)=ln?(1e?Xw)=ln?(eXw)=Xw\begin{aligned} \ln \frac{\sigma}{1-\sigma} &=\ln \left(\frac{\frac{1}{1+e^{-X w}}}{1-\frac{1}{1+e^{-X w}}}\right) \\ &=\ln \left(\frac{\frac{1}{1+e^{-X w}}}{\frac{e^{-X w}}{1+e^{-X w}}}\right) \\ &=\ln \left(\frac{1}{e^{-X \boldsymbol{w}}}\right) \\ &=\ln \left(e^{\boldsymbol{X} \boldsymbol{w}}\right) \\ &=\boldsymbol{X} \boldsymbol{w} \end{aligned} ln1?σσ??=ln(1?1+e?Xw1?1+e?Xw1??)=ln(1+e?Xwe?Xw?1+e?Xw1??)=ln(e?Xw1?)=ln(eXw)=Xw?
不難發(fā)現(xiàn),讓取對數(shù)幾率后所得到的值就是我們線性回歸的!因?yàn)檫@個性質(zhì),在等號兩邊加sigmoid的算法被稱為“對數(shù)幾率回歸”,在英文中就是Logistic Regression,就是邏輯回歸。邏輯回歸可能是廣義線性回歸中最廣為人知的算法,它是一個叫做“回歸“實(shí)際上卻總是被用來做分類的算法,對機(jī)器學(xué)習(xí)和深度學(xué)習(xí)都有重大的意義。在面試中,如果我們希望了解一個人對機(jī)器學(xué)習(xí)的理解程度,第一個問題可能就會從sigmoid函數(shù)以及邏輯回歸是如何來的開始。
2 tensor實(shí)現(xiàn)二分類神經(jīng)網(wǎng)絡(luò)的正向傳播
我們可以在PyTorch中非常簡單地實(shí)現(xiàn)邏輯回歸的預(yù)測過程,讓我們來看下面這一組數(shù)據(jù)。很容易注意到,這組數(shù)據(jù)和上面的回歸數(shù)據(jù)的特征( x1x_{1}x1?,x2x_{2}x2?,是完全一致的,只不過標(biāo)簽y由連續(xù)型結(jié)果轉(zhuǎn)變?yōu)榱朔诸愋偷?和1。這一組分類的規(guī)律是這樣的:當(dāng)兩個特征都為1的時候標(biāo)簽就為1,否則標(biāo)簽就為0。這一組特殊的數(shù)據(jù)被我們稱之為“與門” (AND GATE),這里的“與”正是表示“特征一與特征二都是1”的含義。
要擬合這組數(shù)據(jù),只需要在剛才我們寫好的代碼后面加上sigmoid函數(shù)以及閾值處理后的變化。
接下來,我們對這段代碼進(jìn)行詳細(xì)的說明:
'''導(dǎo)入torch庫''' import torch'''特征張量,養(yǎng)成良好習(xí)慣,上來就定義數(shù)據(jù)類型''' X = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32) '''標(biāo)簽,分類問題的標(biāo)簽是整型''' andgate = torch.tensor([0,0,0,1], dtype = torch.float32) '''定義w,注意這一組w與之前在回歸中使用的完全一樣''' w = torch.tensor([-0.2,0.15,0.15], dtype = torch.float32)def LogisticR(X,w):zhat = torch.mv(X,w) '''首先執(zhí)行線性回歸的過程,依然是mv函數(shù),讓矩陣與向量相乘得到z'''sigma = torch.sigmoid(zhat) '''執(zhí)行sigmoid函數(shù),你可以調(diào)用torch中的sigmoid函數(shù),也可 以自己用torch.exp來寫'''#sigma = 1/(1+torch.exp(-zhat))andhat = torch.tensor([int(x) for x in sigma >= 0.5], dtype = torch.float32) '''設(shè)置閾值為0.5, 使用列表推導(dǎo)式將值轉(zhuǎn)化為0和1'''return sigma, andhat sigma #tensor([0.4502, 0.4875, 0.4875, 0.5250]) andhat #tensor([0., 0., 0., 1.])andgate == andhat '''最后得到的都是0和1,雖然是andhat的數(shù)據(jù)格式是float32,但本質(zhì)上數(shù)還是整數(shù),不存在精度問題''' #tensor([True, True, True, True])可見,這里得到了與我們期待的結(jié)果一致的結(jié)果,這就將回歸算法轉(zhuǎn)變?yōu)榱硕诸悺_@個過程在神經(jīng)網(wǎng)絡(luò)中的表示圖如下:
可以看出,這個結(jié)構(gòu)與線性回歸的神經(jīng)網(wǎng)絡(luò)唯一不同的就是輸出層中多出了一個Sigmoid(zzz)。當(dāng)有了Sigmoid函數(shù)的結(jié)果之后,只要了解閾值是0.5(或者任意我們自己設(shè)定的數(shù)值),就可以輕松地判斷任意樣本的預(yù)測標(biāo)簽y^\hat{y}y^?。在二分類神經(jīng)網(wǎng)絡(luò)中,Sigmoid實(shí)現(xiàn)了將連續(xù)型數(shù)值轉(zhuǎn)換為分類型數(shù)值的作用, 在現(xiàn)代神經(jīng)網(wǎng)絡(luò)架構(gòu)中,除了Sigmoid函數(shù)之外,還有許多其他的函數(shù)可以被用來將連續(xù)型數(shù)據(jù)分割為離散型數(shù)據(jù),接下來,我們就介紹一下這些函數(shù)。
3 符號函數(shù)sign,ReLU,Tanh
- 符號函數(shù)sign
符號函數(shù)是圖像如下所示的函數(shù)。
我們可以使用以下表達(dá)式來表示它:
y={1if?z>00if?z=0?1if?z<0y=\left\{\begin{aligned} 1 & \text { if } z>0 \\ 0 & \text { if } z=0 \\ -1 & \text { if } z<0 \end{aligned}\right. y=??????10?1??if?z>0?if?z=0?if?z<0?
由于函數(shù)的取值是間斷的,符號函數(shù)也被稱為“階躍函數(shù)”,表示在0的兩端,函數(shù)的結(jié)果y是從-1直接階躍到了1。在這里,我們使用y而不是來表示輸出的結(jié)果,是因?yàn)檩敵鼋Y(jié)果直接是0、1、-1這樣的類別,就相當(dāng)于標(biāo)簽了。對于sigmoid函數(shù)而言,返回的是0~1之間的概率值,如果我們希望獲取最終預(yù)測出的類別,還需要將概率轉(zhuǎn)變成0或1這樣的數(shù)字才可以。但符號函數(shù)可以直接返回類別,因此我們可以認(rèn)為符號函數(shù)輸出的結(jié)果就是最終的預(yù)測結(jié)果y。在二分類中,符號函數(shù)也可以忽略中間的時候,直接分為0和1兩類,用如下式子表示:
y={1if?z>00if?z≤0y=\left\{\begin{array}{ll} 1 & \text { if } z>0 \\ 0 & \text { if } z \leq 0 \end{array}\right. y={10??if?z>0?if?z≤0?
等號被并在上方或下方都可以。這個式子可以很容易被轉(zhuǎn)化為下面的式子:
∵z=w1x1+w2x2+b∴y={1if?w1x1+w2x2+b>00if?w1x1+w2x2+b≤0∴y={1if?w1x1+w2x2>?b0if?w1x1+w2x2≤?b\begin{array}{l} \because z=w_{1} x_{1}+w_{2} x_{2}+b \\ \therefore y=\left\{\begin{array}{ll} 1 & \text { if } w_{1} x_{1}+w_{2} x_{2}+b>0 \\ 0 & \text { if } w_{1} x_{1}+w_{2} x_{2}+b \leq 0 \end{array}\right. \\ \therefore y=\left\{\begin{array}{ll} 1 & \text { if } w_{1} x_{1}+w_{2} x_{2}>-b \\ 0 & \text { if } w_{1} x_{1}+w_{2} x_{2} \leq-b \end{array}\right. \end{array} ∵z=w1?x1?+w2?x2?+b∴y={10??if?w1?x1?+w2?x2?+b>0?if?w1?x1?+w2?x2?+b≤0?∴y={10??if?w1?x1?+w2?x2?>?b?if?w1?x1?+w2?x2?≤?b??
此時,?b-b?b就是一個閾值,我們可以使用任意字母來替代它,比較常見的是字母θ\thetaθ。當(dāng)然,不把它當(dāng)做閾值,依然保留w1x1+w2x2+bw_{1} x_{1}+w_{2} x_{2}+bw1?x1?+w2?x2?+b與0進(jìn)行比較的關(guān)系也沒有任何問題。和sigmoid一樣,我們也可以使用階躍函數(shù)來處理”與門“的數(shù)據(jù):
階躍函數(shù)和sigmoid都可以完成二分類的任務(wù)。在神經(jīng)網(wǎng)絡(luò)的二分類中,σ\sigmaσ的默認(rèn)取值一般都是sigmoid函數(shù),少用階躍函數(shù),這是由神經(jīng)網(wǎng)絡(luò)的解法決定的,我們將在第三部分來詳細(xì)講解。
- ReLU
ReLU(Rectified Linear Unit)函數(shù)又名整流線型單元函數(shù),英文發(fā)音為/rel-you/,是現(xiàn)在神經(jīng)網(wǎng)絡(luò)領(lǐng)域中的寵兒,應(yīng)用甚至比sigmoid更廣泛。ReLU提供了一個很簡單的非線性變換:當(dāng)輸入的自變量大于0時,直接輸出該值,當(dāng)輸入的自變量小于等于0時,輸出0。這個過程可以用以下公式表示出來:
Re?LU:σ={z(z>0)0(z≤0)\operatorname{Re} L U: \sigma=\left\{\begin{array}{ll} z & (z>0) \\ 0 & (z \leq 0) \end{array}\right. ReLU:σ={z0?(z>0)(z≤0)?
ReLU函數(shù)是一個非常簡單的函數(shù),本質(zhì)就是max(0,z)。max函數(shù)會從輸入的數(shù)值中選擇較大的那個值進(jìn)行輸出,以達(dá)到保留正數(shù)元素,將負(fù)元素清零的作用。ReLU的圖像如下所示:
相對的,ReLU函數(shù)導(dǎo)數(shù)的圖像如下:
當(dāng)輸入zzz為正數(shù)時,ReLU函數(shù)的導(dǎo)數(shù)為1,當(dāng)zzz為負(fù)數(shù)時,ReLU函數(shù)的導(dǎo)數(shù)為0,當(dāng)輸入為0時,ReLU函數(shù)不可導(dǎo)。因此,ReLU函數(shù)的導(dǎo)數(shù)圖像看起來就是階躍函數(shù),這是一個美好的巧合。
- tanh
tanh(hyperbolic tangent)是雙曲正切函數(shù),英文發(fā)音/t?nt?/或者/θ?n/ (兩者均來源于柯林斯簡明詞典,p1520)。雙曲正切函數(shù)的性質(zhì)與sigmoid相似,它能夠?qū)?shù)值壓縮到(-1,1)區(qū)間內(nèi)。
tanh?:σ=e2z?1e2z+1\tanh : \sigma=\frac{e^{2 z}-1}{e^{2 z}+1} tanh:σ=e2z+1e2z?1?
而雙曲正切函數(shù)的圖像如下:
可以看出,tanh的圖像和sigmoid函數(shù)很像,不過sigmoid函數(shù)的范圍是在(0,1)之間,tanh卻是在坐標(biāo)系的原點(diǎn)(0,0)點(diǎn)上中心對稱。
對tanh求導(dǎo)后可以得到如下公式和導(dǎo)數(shù)圖像:
tanh?′(z)=1?tanh?2(z)\tanh ^{\prime}(z)=1-\tanh ^{2}(z) tanh′(z)=1?tanh2(z)
可以看出,當(dāng)輸入的zzz約接近于0,tanh函數(shù)導(dǎo)數(shù)也越接近最大值1,當(dāng)輸入越偏離0時,tanh函數(shù)的導(dǎo)數(shù)越接近于0。這些函數(shù)是最常見的二分類轉(zhuǎn)化函數(shù),他們在神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)中有著不可替代的作用。在單層神經(jīng)網(wǎng)絡(luò)中,這種作用是無法被體現(xiàn)的,因此關(guān)于這一點(diǎn),我們可以之后再進(jìn)行說明。到這里,我們\只需要知道這些函數(shù)都可以將連續(xù)型數(shù)據(jù)轉(zhuǎn)化為二分類就足夠了。
4 torch.functional實(shí)現(xiàn)單層二分類神經(jīng)網(wǎng)絡(luò)的正向傳播
之前我們使用torch.nn.Linear類實(shí)現(xiàn)了單層回歸神經(jīng)網(wǎng)絡(luò),現(xiàn)在我們試著來實(shí)現(xiàn)單層二分類神經(jīng)網(wǎng)絡(luò),也就是邏輯回歸。邏輯回歸與線性回歸的唯一區(qū)別,就是在線性回歸的結(jié)果之后套上了sigmoid函數(shù)。不難想象,只要讓nn.Linear的輸出結(jié)果再經(jīng)過sigmoid函數(shù),就可以實(shí)現(xiàn)邏輯回歸的正向傳播了。
在PyTorch中,我們幾乎總是從nn.functional中調(diào)用相關(guān)函數(shù)。
回顧一下我們的數(shù)據(jù)和網(wǎng)絡(luò)架構(gòu):
接下來,我們在之前線性回歸代碼的基礎(chǔ)上,加上nn.functional來實(shí)現(xiàn)單層二分類神經(jīng)網(wǎng)絡(luò):
在這里,nn.Linear雖然依然是輸出層,但卻沒有擔(dān)任最終輸出值的角色,因此這里我們使用dense作為變量名。 dense表示緊密鏈接的層,即上一層的大部分神經(jīng)元都與這一層的大部分神經(jīng)元相連,在許多神經(jīng)網(wǎng)絡(luò)中我們都會用到密集鏈接的層,因此dense是我們經(jīng)常會用到的一個變量名。我們將數(shù)據(jù)從nn.Linear傳入,得到zhat,然后再將zhat的結(jié)果傳入sigmoid函數(shù),得到sigma,之后在設(shè)置閾值為0.5,得到最后的y。
在PyTorch中,我們可以從functional模塊里找出大部分之前我們提到的函數(shù),來看看ReLU、 Tanh以及Sign函數(shù)都是如何使用PyTorch實(shí)現(xiàn)的吧:
在PyTorch的安排中,符號函數(shù)sign與雙曲正切函數(shù)tanh更多時候只是被用作數(shù)學(xué)計算工具,而ReLU和Sigmoid卻作為神經(jīng)網(wǎng)絡(luò)的組成部分被放在庫functional中,這其實(shí)反映出實(shí)際使用時大部分人的選擇。ReLU與Sigmoid還是主流的、位于nn.Linear后的函數(shù)。
總結(jié)
以上是生活随笔為你收集整理的Lesson 8.38.4 二分类神经网络torch.nn.functional实现单层二分类网络的正向传播的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Lesson 8.18.2 单层回归神经
- 下一篇: Lesson 8.5 SOFTMAX回归