日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lesson 8.38.4 二分类神经网络torch.nn.functional实现单层二分类网络的正向传播

發布時間:2025/4/5 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lesson 8.38.4 二分类神经网络torch.nn.functional实现单层二分类网络的正向传播 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

二、二分類神經網絡:邏輯回歸

1 二分類神經網絡的理論基礎

線性回歸是統計學經典算法,它能夠擬合出一條直線來描述變量之間的線性關系。但在實際中,變量之間的關系通常都不是一條直線,而是呈現出某種曲線關系。在統計學的歷史中,為了讓統計學模型能夠更好地擬合曲線,統計學家們在線性回歸的方程兩邊引入了聯系函數(link function),對線性回歸的方程做出了各種樣的變化,并將這些變化后的方程稱為“廣義線性回歸”。其中比較著名的有等式兩邊同時取對數的對數函數回歸、同時取指數的S形函數回歸等。
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+blny=ln(ax+b)y=ax+bey=eax+b?
在探索的過程中,一種奇特的變化吸引了統計學家們的注意,這個變化就是sigmoid函數帶來的變化。Sigmoid函數的公式如下:
σ=Sigmoid?(z)=11+e?z\sigma=\operatorname{Sigmoid}(z)=\frac{1}{1+e^{-z}} σ=Sigmoid(z)=1+e?z1?
其中eee為自然常數(約為2.71828),其中zzz是它的自變量,σ\sigmaσ是因變量,zzz的值常常是線性模型的取值(比如,線性回歸的結果zzz)。 Sigmoid函數是一個S型的函數,它的圖像如下:

從圖像上就可以看出,這個函數的性質相當特別。當自變量zzz趨近正無窮時,因變量σ\sigmaσ趨近于1,而當zzz趨近負無窮時,σ\sigmaσ趨近于0,這使得sigmoid函數能夠將任何實數映射到(0,1)區間。同時,Sigmoid的導數在zzz=0點時最大(這一點的斜率最大),所以它可以快速將數據從zzz=0的附近排開,讓數據點到遠離自變量取0的地方去。這樣的性質,讓sigmoid函數擁有將連續性變量zzz=0轉化為離散型變量σ\sigmaσ的力量,這也就是化回歸算法為分類算法的力量。

具體怎么操作呢?只要將線性回歸方程的結果作為自變量帶入sigmoid函數,得出的數據就一定是(0,1) 之間的值。此時,只要我們設定一個閾值(比如0.5),規定σ\sigmaσ大于0.5時,預測結果為1類,σ\sigmaσ小于0.5時,預測結果為0類,則可以順利將回歸算法轉化為分類算法。此時,我們的標簽就是類別0和1了。這個閾值可以自己調整,在沒有調整之前,一般默認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?
更神奇的是,當我們對線性回歸的結果取sigmoid函數之后,只要再進行以下操作:
1)將結果以幾率(σ1?σ)\left(\frac{\sigma}{1-\sigma}\right)(1?σσ?)的形式展現
2)在幾率上求以e為底的對數
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?

不難發現,讓取對數幾率后所得到的值就是我們線性回歸的!因為這個性質,在等號兩邊加sigmoid的算法被稱為“對數幾率回歸”,在英文中就是Logistic Regression,就是邏輯回歸。邏輯回歸可能是廣義線性回歸中最廣為人知的算法,它是一個叫做“回歸“實際上卻總是被用來做分類的算法,對機器學習和深度學習都有重大的意義。在面試中,如果我們希望了解一個人對機器學習的理解程度,第一個問題可能就會從sigmoid函數以及邏輯回歸是如何來的開始。

2 tensor實現二分類神經網絡的正向傳播

我們可以在PyTorch中非常簡單地實現邏輯回歸的預測過程,讓我們來看下面這一組數據。很容易注意到,這組數據和上面的回歸數據的特征( x1x_{1}x1?,x2x_{2}x2?,是完全一致的,只不過標簽y由連續型結果轉變為了分類型的0和1。這一組分類的規律是這樣的:當兩個特征都為1的時候標簽就為1,否則標簽就為0。這一組特殊的數據被我們稱之為“與門” (AND GATE),這里的“與”正是表示“特征一與特征二都是1”的含義。

要擬合這組數據,只需要在剛才我們寫好的代碼后面加上sigmoid函數以及閾值處理后的變化。

import torch X = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32) andgate = torch.tensor([[0],[0],[0],[1]], dtype = torch.float32) '''保險起見,生成二維的、 float32類型的標簽''' w = torch.tensor([-0.2,0.15,0.15], dtype = torch.float32)def LogisticR(X,w):zhat = torch.mv(X,w)sigma = torch.sigmoid(zhat)#sigma = 1/(1+torch.exp(-zhat))andhat = torch.tensor([int(x) for x in sigma >= 0.5], dtype = torch.float32)'''int(true)為1 int(False)為0'''return sigma, andhatsigma, andhat = LogisticR(X,w) sigma #tensor([0.4502, 0.4875, 0.4875, 0.5250]) andhat #tensor([0., 0., 0., 1.])

接下來,我們對這段代碼進行詳細的說明:

'''導入torch庫''' import torch'''特征張量,養成良好習慣,上來就定義數據類型''' X = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32) '''標簽,分類問題的標簽是整型''' 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) '''首先執行線性回歸的過程,依然是mv函數,讓矩陣與向量相乘得到z'''sigma = torch.sigmoid(zhat) '''執行sigmoid函數,你可以調用torch中的sigmoid函數,也可 以自己用torch.exp來寫'''#sigma = 1/(1+torch.exp(-zhat))andhat = torch.tensor([int(x) for x in sigma >= 0.5], dtype = torch.float32) '''設置閾值為0.5, 使用列表推導式將值轉化為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的數據格式是float32,但本質上數還是整數,不存在精度問題''' #tensor([True, True, True, True])

可見,這里得到了與我們期待的結果一致的結果,這就將回歸算法轉變為了二分類。這個過程在神經網絡中的表示圖如下:

可以看出,這個結構與線性回歸的神經網絡唯一不同的就是輸出層中多出了一個Sigmoid(zzz)。當有了Sigmoid函數的結果之后,只要了解閾值是0.5(或者任意我們自己設定的數值),就可以輕松地判斷任意樣本的預測標簽y^\hat{y}y^?。在二分類神經網絡中,Sigmoid實現了將連續型數值轉換為分類型數值的作用, 在現代神經網絡架構中,除了Sigmoid函數之外,還有許多其他的函數可以被用來將連續型數據分割為離散型數據,接下來,我們就介紹一下這些函數。

3 符號函數sign,ReLU,Tanh

  • 符號函數sign

符號函數是圖像如下所示的函數。

我們可以使用以下表達式來表示它:
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?
由于函數的取值是間斷的,符號函數也被稱為“階躍函數”,表示在0的兩端,函數的結果y是從-1直接階躍到了1。在這里,我們使用y而不是來表示輸出的結果,是因為輸出結果直接是0、1、-1這樣的類別,就相當于標簽了。對于sigmoid函數而言,返回的是0~1之間的概率值,如果我們希望獲取最終預測出的類別,還需要將概率轉變成0或1這樣的數字才可以。但符號函數可以直接返回類別,因此我們可以認為符號函數輸出的結果就是最終的預測結果y。在二分類中,符號函數也可以忽略中間的時候,直接分為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?z0?
等號被并在上方或下方都可以。這個式子可以很容易被轉化為下面的式子:
∵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?+by={10??if?w1?x1?+w2?x2?+b>0?if?w1?x1?+w2?x2?+b0?y={10??if?w1?x1?+w2?x2?>?b?if?w1?x1?+w2?x2??b??
此時,?b-b?b就是一個閾值,我們可以使用任意字母來替代它,比較常見的是字母θ\thetaθ。當然,不把它當做閾值,依然保留w1x1+w2x2+bw_{1} x_{1}+w_{2} x_{2}+bw1?x1?+w2?x2?+b與0進行比較的關系也沒有任何問題。和sigmoid一樣,我們也可以使用階躍函數來處理”與門“的數據:

import torch X = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32) andgate = torch.tensor([[0],[0],[0],[1]], dtype = torch.float32) w = torch.tensor([-0.2,0.15, 0.15], dtype = torch.float32)def LinearRwithsign(X,w):zhat = torch.mv(X,w)andhat = torch.tensor([int(x) for x in zhat >= 0], dtype = torch.float32)return zhat, andhat zhat, andhat = LinearRwithsign(X,w) zhat #tensor([-0.2000, -0.0500, -0.0500, 0.1000]) andhat #tensor([0., 0., 0., 1.])

階躍函數和sigmoid都可以完成二分類的任務。在神經網絡的二分類中,σ\sigmaσ的默認取值一般都是sigmoid函數,少用階躍函數,這是由神經網絡的解法決定的,我們將在第三部分來詳細講解。

  • ReLU

ReLU(Rectified Linear Unit)函數又名整流線型單元函數,英文發音為/rel-you/,是現在神經網絡領域中的寵兒,應用甚至比sigmoid更廣泛。ReLU提供了一個很簡單的非線性變換:當輸入的自變量大于0時,直接輸出該值,當輸入的自變量小于等于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)(z0)?
ReLU函數是一個非常簡單的函數,本質就是max(0,z)。max函數會從輸入的數值中選擇較大的那個值進行輸出,以達到保留正數元素,將負元素清零的作用。ReLU的圖像如下所示:

相對的,ReLU函數導數的圖像如下:

當輸入zzz為正數時,ReLU函數的導數為1,當zzz為負數時,ReLU函數的導數為0,當輸入為0時,ReLU函數不可導。因此,ReLU函數的導數圖像看起來就是階躍函數,這是一個美好的巧合。

  • tanh

tanh(hyperbolic tangent)是雙曲正切函數,英文發音/t?nt?/或者/θ?n/ (兩者均來源于柯林斯簡明詞典,p1520)。雙曲正切函數的性質與sigmoid相似,它能夠將數值壓縮到(-1,1)區間內。
tanh?:σ=e2z?1e2z+1\tanh : \sigma=\frac{e^{2 z}-1}{e^{2 z}+1} tanh:σ=e2z+1e2z?1?
而雙曲正切函數的圖像如下:

可以看出,tanh的圖像和sigmoid函數很像,不過sigmoid函數的范圍是在(0,1)之間,tanh卻是在坐標系的原點(0,0)點上中心對稱。

對tanh求導后可以得到如下公式和導數圖像:
tanh?′(z)=1?tanh?2(z)\tanh ^{\prime}(z)=1-\tanh ^{2}(z) tanh(z)=1?tanh2(z)

可以看出,當輸入的zzz約接近于0,tanh函數導數也越接近最大值1,當輸入越偏離0時,tanh函數的導數越接近于0。這些函數是最常見的二分類轉化函數,他們在神經網絡的結構中有著不可替代的作用。在單層神經網絡中,這種作用是無法被體現的,因此關于這一點,我們可以之后再進行說明。到這里,我們\只需要知道這些函數都可以將連續型數據轉化為二分類就足夠了。

4 torch.functional實現單層二分類神經網絡的正向傳播

之前我們使用torch.nn.Linear類實現了單層回歸神經網絡,現在我們試著來實現單層二分類神經網絡,也就是邏輯回歸。邏輯回歸與線性回歸的唯一區別,就是在線性回歸的結果之后套上了sigmoid函數。不難想象,只要讓nn.Linear的輸出結果再經過sigmoid函數,就可以實現邏輯回歸的正向傳播了。
在PyTorch中,我們幾乎總是從nn.functional中調用相關函數。

回顧一下我們的數據和網絡架構:

接下來,我們在之前線性回歸代碼的基礎上,加上nn.functional來實現單層二分類神經網絡:

import torch from torch.nn import functional as F X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32) torch.random.manual_seed(420) #人為設置隨機數種子 dense = torch.nn.Linear(2,1) zhat = dense(X) sigma = F.sigmoid(zhat) y = [int(x) for x in sigma > 0.5] y #[1, 1, 1, 1]

在這里,nn.Linear雖然依然是輸出層,但卻沒有擔任最終輸出值的角色,因此這里我們使用dense作為變量名。 dense表示緊密鏈接的層,即上一層的大部分神經元都與這一層的大部分神經元相連,在許多神經網絡中我們都會用到密集鏈接的層,因此dense是我們經常會用到的一個變量名。我們將數據從nn.Linear傳入,得到zhat,然后再將zhat的結果傳入sigmoid函數,得到sigma,之后在設置閾值為0.5,得到最后的y。
在PyTorch中,我們可以從functional模塊里找出大部分之前我們提到的函數,來看看ReLU、 Tanh以及Sign函數都是如何使用PyTorch實現的吧:

torch.random.manual_seed(420) #人為設置隨機數種子 dense = torch.nn.Linear(2,1) zhat = dense(X) #符號函數sign print(zhat) torch.sign(zhat) #tensor([[0.6730], # [1.1048], # [0.2473], # [0.6792]], grad_fn=<AddmmBackward0>) #tensor([[1.], # [1.], # [1.], # [1.]], grad_fn=<SignBackward0>)#ReLU F.relu(zhat) #tensor([[0.6730], # [1.1048], # [0.2473], # [0.6792]], grad_fn=<ReluBackward0>)#tanh torch.tanh(zhat) #tensor([[0.5869], # [0.8022], # [0.2424], # [0.5910]], grad_fn=<TanhBackward0>)

在PyTorch的安排中,符號函數sign與雙曲正切函數tanh更多時候只是被用作數學計算工具,而ReLU和Sigmoid卻作為神經網絡的組成部分被放在庫functional中,這其實反映出實際使用時大部分人的選擇。ReLU與Sigmoid還是主流的、位于nn.Linear后的函數。

總結

以上是生活随笔為你收集整理的Lesson 8.38.4 二分类神经网络torch.nn.functional实现单层二分类网络的正向传播的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。