做地方門戶網(wǎng)站的資質(zhì)清遠(yuǎn)今日頭條最新消息
文章目錄
- 一、神經(jīng)網(wǎng)絡(luò)
- 1.1神經(jīng)元結(jié)構(gòu)
- 1.2單層神經(jīng)網(wǎng)絡(luò):單層感知機(jī)
- 1.3兩層神經(jīng)網(wǎng)絡(luò):多層感知機(jī)
- 1.4多層神經(jīng)網(wǎng)絡(luò)
- 二、全連接神經(jīng)網(wǎng)絡(luò)
- 2.1基本結(jié)構(gòu)
- 2.2激活函數(shù)、前向傳播、反向傳播、損失函數(shù)
- 2.2.1激活函數(shù)的意義
- 2.2.2前向傳播
- 2.2.3損失函數(shù)、反向傳播
- 2.2.4梯度下降法
- 2.3模型訓(xùn)練流程
- 2.4全連接神經(jīng)網(wǎng)絡(luò)的Pytorch實(shí)現(xiàn)
一、神經(jīng)網(wǎng)絡(luò)
1.1神經(jīng)元結(jié)構(gòu)
??生物神經(jīng)元結(jié)構(gòu)如下:
- 樹突:一個(gè)神經(jīng)元往往有多個(gè)樹突,用于接收傳如的信息。
- 軸突與軸突末梢:一個(gè)神經(jīng)元只有一個(gè)軸突,但卻有多個(gè)軸突末梢用于給其他多個(gè)神經(jīng)元傳遞信息。軸突末梢跟其他神經(jīng)元的樹突產(chǎn)生連接,從而傳遞信號(hào)。
生物神經(jīng)元彼此之間相互連接,不斷傳遞信息而構(gòu)成生物神經(jīng)網(wǎng)絡(luò)。
??神經(jīng)元結(jié)構(gòu)則是模仿生物神經(jīng)元提出的一種數(shù)學(xué)模型,其包含輸入、輸出與計(jì)算功能。其中,輸入可類比神經(jīng)元樹突,樹突可類比神經(jīng)元的軸突末梢,計(jì)算則可類比為細(xì)胞核。經(jīng)典的神經(jīng)元模型如下:
其中包含三個(gè)輸入 a 1 、 a 2 、 a 3 a_1、a_2、a_3 a1?、a2?、a3?,每個(gè)輸入分別對(duì)應(yīng)一個(gè)權(quán)值,分別為 w 1 、 w 2 、 w 3 w_1、w_2、w_3 w1?、w2?、w3?。將輸入與權(quán)值相乘并求和(加權(quán)求和)后,再經(jīng)過Sgn函數(shù)計(jì)算即可得到輸出Z。而神經(jīng)網(wǎng)絡(luò)訓(xùn)練算法的目的在于,讓權(quán)重的值調(diào)整到最佳,使得輸出結(jié)果Z的值最接近真實(shí)值。
??一般地,將sum與Sgn函數(shù)合并到一個(gè)圓圈里,代表神經(jīng)元的內(nèi)部計(jì)算,便于畫出更加復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)。并且,一個(gè)神經(jīng)元可引出多個(gè)代表輸出的有向箭頭(具有相同的值),作為下一神經(jīng)元的輸入值并參與運(yùn)算:
??神經(jīng)元模型的意義可以理解為:我們有一個(gè)數(shù)據(jù),稱之為樣本。樣本有四個(gè)屬性,其中三個(gè)屬性已知,一個(gè)屬性未知,神經(jīng)網(wǎng)絡(luò)需要做的就是通過三個(gè)已知屬性預(yù)測(cè)未知屬性。具體辦法就是使用神經(jīng)元的公式進(jìn)行計(jì)算。三個(gè)已知屬性的值是 a 1 、 a 2 、 a 3 a_1、a_2、a_3 a1?、a2?、a3?,未知屬性的值是z。并且,已知的屬性往往稱之為特征,未知的屬性往往稱之為目標(biāo)。假設(shè)特征與目標(biāo)之間確實(shí)是線性關(guān)系,并且我們已經(jīng)得到表示這個(gè)關(guān)系的權(quán)值 w 1 、 w 2 、 w 3 w_1、w_2、w_3 w1?、w2?、w3?。那么,就可以通過神經(jīng)元模型預(yù)測(cè)新樣本的目標(biāo)。
1.2單層神經(jīng)網(wǎng)絡(luò):單層感知機(jī)
??單層神經(jīng)網(wǎng)絡(luò)是由兩層神經(jīng)元(輸入層、輸出層)組成的神經(jīng)網(wǎng)絡(luò),也被稱之為感知機(jī)模型。其結(jié)構(gòu)如下:
在感知機(jī)中有輸入層、輸出層兩個(gè)層次:
- 輸入層:只負(fù)責(zé)傳輸數(shù)據(jù),不做計(jì)算。
- 輸出層:需要對(duì)前面一層的輸入進(jìn)行計(jì)算,并將結(jié)果輸出。
其中, w i , j w_{i,j} wi,j?表示前一層第 j j j個(gè)神經(jīng)元輸入到后一層第 i i i神經(jīng)元時(shí),前一層神經(jīng)元的輸出對(duì)應(yīng)的權(quán)值。觀察 z 1 、 z 2 z_1、z_2 z1?、z2?公式,實(shí)際可看作是一對(duì)線性代數(shù)方程組,因此可以用矩陣乘法來表示。系數(shù)矩陣 w w w是兩行三列矩陣:
[ w 1 , 1 w 1 , 2 w 1 , 3 w 2 , 1 w 2 , 2 w 2 , 3 ] (3) \left[ \begin{matrix} w_{1,1} & w_{1,2} & w_{1,3} \\ w_{2,1} & w_{2,2} & w_{2,3} \\ \end{matrix} \right] \tag{3} [w1,1?w2,1??w1,2?w2,2??w1,3?w2,3??](3)
同理,輸入的是由 a 1 、 a 2 、 a 3 a_1、a_2、a_3 a1?、a2?、a3?組成的列向量:
[ a 1 a 2 a 3 ] (3) \left[ \begin{matrix} a_1 \\ a_2 \\ a_3 \end{matrix} \right] \tag{3} ?a1?a2?a3?? ?(3)
用g()表示輸入加權(quán)和后經(jīng)過的激活函數(shù),則有:
z = g ( w ? a ) z=g(w*a) z=g(w?a)
1.3兩層神經(jīng)網(wǎng)絡(luò):多層感知機(jī)
??兩層神經(jīng)網(wǎng)絡(luò)在單層神經(jīng)網(wǎng)絡(luò)的基礎(chǔ)上增加了一個(gè)中間層(隱藏層),此時(shí),隱藏層和輸出層都是計(jì)算層。中間層結(jié)構(gòu)如下:
輸出層的結(jié)果由隱藏層兩個(gè)神經(jīng)元的輸入經(jīng)過加權(quán)求和、激活函數(shù)計(jì)算后才可得到,此時(shí)即引入了第二個(gè)參數(shù)矩陣 w ( 2 ) w^{(2)} w(2):
同樣也可使用矩陣運(yùn)算來概括整個(gè)網(wǎng)絡(luò)的運(yùn)算流程:
z = g ( 2 ) ( a ( 2 ) ? w ( 2 ) ) a 1 ( 2 ) = g 1 ( 1 ) ( a ( 1 ) ? w 1 ( 1 ) ) a 2 ( 2 ) = g 2 ( 1 ) ( a ( 1 ) ? w 2 ( 1 ) ) z=g^{(2)}(a^{(2)}*w^{(2)})\\ a_1^{(2)}=g^{(1)}_1(a^{(1)}*w^{(1)}_1)\\ a_2^{(2)}=g^{(1)}_2(a^{(1)}*w^{(1)}_2) z=g(2)(a(2)?w(2))a1(2)?=g1(1)?(a(1)?w1(1)?)a2(2)?=g2(1)?(a(1)?w2(1)?)
??需要說明的是,上文對(duì)神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)圖的討論中都沒有提到偏置節(jié)點(diǎn)(bias unit)。事實(shí)上,這些節(jié)點(diǎn)是默認(rèn)存在的,其本質(zhì)是存儲(chǔ)值永遠(yuǎn)為一個(gè)常量的單元。在神經(jīng)網(wǎng)絡(luò)的每個(gè)層次中,除了輸出層以外,都會(huì)含有這樣一個(gè)偏置單元,在引入偏置值后,神經(jīng)元基本模型變?yōu)?#xff1a;
數(shù)學(xué)表達(dá)式:
??同樣的,將偏置值加入到兩層神經(jīng)網(wǎng)絡(luò)當(dāng)中得到:
1.4多層神經(jīng)網(wǎng)絡(luò)
??在兩層神經(jīng)網(wǎng)絡(luò)的輸出層后面,繼續(xù)添加層次,使得原來的輸出層變成隱藏層,新加的層次成為新的輸出層,從而構(gòu)建多層神經(jīng)網(wǎng)絡(luò)。簡(jiǎn)單的多層神經(jīng)網(wǎng)絡(luò)如下:
輸出z的推導(dǎo)公式為:
z = g ( 3 ) ( a ( 3 ) ? w ( 3 ) ) a ( 3 ) = g ( 2 ) ( a ( 2 ) ? w ( 2 ) ) a ( 2 ) = g ( 1 ) ( a ( 1 ) ? w ( 1 ) ) z=g^{(3)}(a^{(3)}*w^{(3)})\\ a^{(3)}=g^{(2)}(a^{(2)}*w^{(2)})\\ a^{(2)}=g^{(1)}(a^{(1)}*w^{(1)}) z=g(3)(a(3)?w(3))a(3)=g(2)(a(2)?w(2))a(2)=g(1)(a(1)?w(1))
??從圖中可以看出,參數(shù)矩陣 w ( 1 ) 、 w ( 2 ) 、 w ( 3 ) w^{(1)}、w^{(2)}、w^{(3)} w(1)、w(2)、w(3)分別有6、4、6個(gè)參數(shù),即整個(gè)神經(jīng)網(wǎng)絡(luò)共有16個(gè)參數(shù):
假設(shè)我們將中間層的節(jié)點(diǎn)數(shù)做一下調(diào)整。第一個(gè)中間層改為3個(gè)單元,第二個(gè)中間層改為4個(gè)單元。經(jīng)過調(diào)整以后,整個(gè)網(wǎng)絡(luò)的參數(shù)變成了33個(gè):
二、全連接神經(jīng)網(wǎng)絡(luò)
2.1基本結(jié)構(gòu)
??全連接神經(jīng)網(wǎng)絡(luò)是指第 N 層的每個(gè)神經(jīng)元和第 N-1 層的所有神經(jīng)元相連,即第 N-1 層神經(jīng)元的輸出就是第 N 層神經(jīng)元的輸入。整體結(jié)構(gòu)由三部分組成:
- 輸入層:輸入的數(shù)據(jù),即向量(矩陣)組 x 1 、 x 2 、 x 3 x_1、x_2、x_3 x1?、x2?、x3?,可以是圖片、矩陣等。
- 隱藏層:對(duì)輸入數(shù)據(jù)進(jìn)行特征提取,對(duì)于不同的輸入神經(jīng)單元設(shè)置不同的權(quán)重與偏置,從而影響神經(jīng)單元對(duì)輸入信息敏感程度,可以形成輸出結(jié)果的偏向)。
- 輸出層:輸出的結(jié)果,即 y 1 、 y 2 、 y 3 y_1、y_2、y_3 y1?、y2?、y3?,可以是分類結(jié)果等。
??通過輸入層激活信號(hào),再通過隱藏層提取特征,不同隱藏層神經(jīng)單元對(duì)應(yīng)不同輸入層的神經(jīng)單元,其權(quán)重和自身偏置均可能不同。由隱藏層將信號(hào)
經(jīng)計(jì)算再傳遞到輸出層,最后由輸出層輸出信號(hào)。例如,識(shí)別一個(gè)4x3的圖像,下例中采用了12 神經(jīng)元來對(duì)應(yīng) 4x3 個(gè)像素點(diǎn)進(jìn)行輸入,在隱藏層中使用另外三個(gè)神經(jīng)單元進(jìn)行特征提取,最后輸出層再使用兩個(gè)神經(jīng)節(jié)點(diǎn)標(biāo)記識(shí)別結(jié)果是 0 或 1(分別表示黑與白):
- 對(duì)于輸入層,十二個(gè)神經(jīng)單元對(duì)應(yīng) 4 * 3 像素值(0或1),如果該像素是白的,則對(duì)應(yīng)神經(jīng)元興奮(對(duì)應(yīng)1),否則靜息(對(duì)應(yīng)0)。
- 對(duì)于輸出層的兩個(gè)節(jié)點(diǎn),如果識(shí)別結(jié)果偏向0,那么第一個(gè)節(jié)點(diǎn)興奮度會(huì)高于第二個(gè)節(jié)點(diǎn),反之識(shí)別結(jié)果偏向1。
- 對(duì)于隱藏層,每一個(gè)節(jié)點(diǎn)會(huì)對(duì)輸入層的興奮有不同的接收權(quán)重,從而更加偏向于某種識(shí)別模式。例如,隱藏層第一個(gè)神經(jīng)單元對(duì)應(yīng)下圖模式A,也就是對(duì)應(yīng)輸入層 4、7號(hào)神經(jīng)單元接收權(quán)重比較高,對(duì)其他神經(jīng)單元接受權(quán)重比較低,如果超過了神經(jīng)單元自身的偏置(閾值)則會(huì)引發(fā)隱藏層的興奮,向輸出層傳遞興奮信息,隱藏層其他神經(jīng)單元同理。
??事實(shí)上,神經(jīng)網(wǎng)絡(luò)模型的意義就在于找到最為合適的參數(shù)w、b,使得預(yù)測(cè)結(jié)果與真實(shí)情況最為接近。
2.2激活函數(shù)、前向傳播、反向傳播、損失函數(shù)
2.2.1激活函數(shù)的意義
??由上文可知,每一層的參數(shù)運(yùn)算均可表示為矩陣運(yùn)算:
a [ 1 ] = w [ 1 ] ? x + b [ 1 ] a^{[1]}=w^{[1]}*x+b^{[1]} a[1]=w[1]?x+b[1]
- a [ 1 ] a^{[1]} a[1]:上一層神經(jīng)元輸出值的與系數(shù)矩陣、偏置的加權(quán)和,是本層神經(jīng)元的輸出值。
- b [ 1 ] b^{[1]} b[1]`:系數(shù)矩陣。
- x x x:上一層神經(jīng)元的輸出值。
- b [ 1 ] b^{[1]} b[1]:偏置。
若直接將 a [ 1 ] a^{[1]} a[1]作為下一隱藏層的輸入,并繼續(xù)只進(jìn)行線性運(yùn)算(僅含有加法、數(shù)量乘法運(yùn)算),即 a [ 2 ] = w [ 2 ] ? a [ 1 ] + b [ 2 ] a^{[2]}=w^{[2]}*a^{[1]}+b^{[2]} a[2]=w[2]?a[1]+b[2],則會(huì)出現(xiàn)“無效的隱藏層”。數(shù)學(xué)推導(dǎo)如下:
可見,此時(shí) a [ 2 ] a^{[2]} a[2] 相當(dāng)于是一組新參數(shù) w ′ 、 b ′ w^{'}、b^{'} w′、b′與輸入向量 x x x運(yùn)算得到,則原先的 a [ 1 ] a^{[1]} a[1]隱藏層退化,神經(jīng)網(wǎng)絡(luò)仍只含有一層隱藏層(多層線性操作等價(jià)于一層線性操作,多層神經(jīng)網(wǎng)絡(luò)退化為最簡(jiǎn)單的單層神經(jīng)網(wǎng)絡(luò)模型)。
??事實(shí)上,真實(shí)世界有些原始數(shù)據(jù)本身就是線性不可分的,必須要對(duì)原始空間進(jìn)行一定的非線性操作,此時(shí)就必須使用非線性的激活函數(shù)參與運(yùn)算來為神經(jīng)網(wǎng)絡(luò)引入非線性性,否則多層神經(jīng)網(wǎng)絡(luò)就沒有意義。
??除此之外,激活函數(shù)有助于將神經(jīng)元輸出的值限制在我們要求的某個(gè)限制內(nèi)。 因?yàn)榧せ詈瘮?shù)的輸入是 W ? x + b W * x + b W?x+b,如果不限制在某個(gè)值上,則此值的變動(dòng)范圍會(huì)非常大,此時(shí)可使用激活函數(shù)將輸出值限定在一個(gè)范圍(常用0~1),來表示神經(jīng)元的興奮程度(0表靜默,1表活躍)。
2.2.2前向傳播
??前向傳播,是指將數(shù)據(jù)特征作為輸入,輸入到隱藏層,將數(shù)據(jù)特征和對(duì)應(yīng)的權(quán)重相乘同時(shí)再和偏置進(jìn)行求和,將計(jì)算的結(jié)果通過激活函數(shù)進(jìn)行激活,激活函數(shù)輸出值作為下一層神經(jīng)網(wǎng)絡(luò)層的輸入再和對(duì)應(yīng)的權(quán)重相乘同時(shí)和對(duì)應(yīng)的偏置求和,再將計(jì)算的結(jié)果通過激活函數(shù)進(jìn)行激活,不斷重復(fù)上述的過程直到神經(jīng)網(wǎng)絡(luò)的輸出層,最終得到神經(jīng)網(wǎng)絡(luò)的輸出值。
??簡(jiǎn)單來說,輸入數(shù)據(jù)輸入到神經(jīng)網(wǎng)絡(luò)并通過隱藏層進(jìn)行運(yùn)算,最后輸出結(jié)果的過程,就是神經(jīng)網(wǎng)絡(luò)的前向傳播。一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò):
隱藏層兩個(gè)神經(jīng)元的計(jì)算:
輸出層神經(jīng)元的計(jì)算:
其中, w 11 、 w 13 、 b 1 、 w 12 、 w 14 、 b 2 、 w 21 、 w 22 、 b 3 w_{11}、w_{13}、b_1、w_{12}、w_{14}、b_2、w_{21}、w_{22}、b_3 w11?、w13?、b1?、w12?、w14?、b2?、w21?、w22?、b3?是模型中所包含的權(quán)重和偏置,而訓(xùn)練模型的目的在于,找到一種方法可以求出準(zhǔn)確的 w w w和 b b b,使得前向傳播計(jì)算出來的預(yù)測(cè)值 y y y無限接近于真實(shí)值。
2.2.3損失函數(shù)、反向傳播
【損失函數(shù)】
??在模型確定后(本質(zhì)是確定了一組參數(shù)),就希望訓(xùn)練結(jié)果接近于真實(shí)值,此時(shí)可設(shè)置損失函數(shù)來計(jì)算前向傳播的輸出值和真實(shí)的label值之間的損失誤差,來對(duì)模型性能進(jìn)行評(píng)估。目前常見的損失函數(shù)有均方誤差、交叉熵誤差。對(duì)于不同類型的問題,如:
- 回歸問題:輸出的是物體的值,如預(yù)測(cè)當(dāng)前溫度等,是對(duì)真實(shí)值的一種逼近預(yù)測(cè),輸出值是連續(xù)的。
- 分類問題:輸出的是物體所屬的類別,輸出值是離散的。
對(duì)于不同類型的問題就有著不同的常用損失函數(shù)。
【反向傳播】
??事實(shí)上,模型訓(xùn)練的流程為,將數(shù)據(jù)輸入模型并通過前向傳播得到輸出數(shù)據(jù),利用損失函數(shù)計(jì)算輸出數(shù)據(jù)與真實(shí)數(shù)據(jù)之間的誤差,并利用反向傳播更新參數(shù)(這一過程需使用梯度)使損失函數(shù)變低(神經(jīng)網(wǎng)絡(luò)的輸出和真實(shí)值更加逼近),最后不斷重復(fù)這一過程,直到損失函數(shù)接近于0。
??但是實(shí)際項(xiàng)目中,由于數(shù)據(jù)中存在噪聲,因此損失值在參數(shù)不斷的更新下會(huì)不斷接近0,但是不可能等于0,所以我們往常將模型的訓(xùn)練輪次和損失值變化畫圖顯示出來,如果損失值在一定的輪次后趨于平緩不再下降,那么就認(rèn)為模型的訓(xùn)練已經(jīng)收斂了。例如:
2.2.4梯度下降法
??梯度下降法是最為常見的反向傳播更新參數(shù)的算法,具體步驟為:
- 1.計(jì)算損失:使用損失函數(shù)計(jì)算預(yù)測(cè)值與真實(shí)值之間的誤差。例如,使用均方誤差(MSE)或交叉熵?fù)p失。
- 2.誤差反向傳播:從輸出層開始,計(jì)算損失相對(duì)于每個(gè)參數(shù)的梯度。通過鏈?zhǔn)椒▌t,將梯度逐層傳遞回輸入層。
- 3.參數(shù)更新:使用優(yōu)化算法(如梯度下降)更新每個(gè)參數(shù),使損失最小化。參數(shù)更新公式如下:
其中, W o l d W_{old} Wold?是更新前的權(quán)重, W n e w W_{new} Wnew?是更新后的權(quán)重, η η η是學(xué)習(xí)率, ? l ? w \frac{\partial l}{\partial w} ?w?l?是損失函數(shù)相對(duì)于權(quán)重的梯度。
【梯度下降法原理】
梯度下降法正是基于此思想,只是從追求不同方向上最陡的山體梯度,變?yōu)樽非笕绾涡薷膮?shù)可使損失函數(shù)值下降最快。反之,就是梯度上升法。需要注意的是,梯度下降法只是一種局部搜索優(yōu)化算法,即它無法保證得到全局最優(yōu)解。因此,有時(shí)需要運(yùn)用其他優(yōu)化算法來搜索全局最優(yōu)解。
1.一元函數(shù):模型僅有一個(gè)參數(shù)
??函數(shù) J ( w ) J(w) J(w)即為損失函數(shù),橫坐標(biāo) w w w表示模型參數(shù),問題轉(zhuǎn)化為如何求出函數(shù)極小值處參數(shù) w w w的值。
思路:在當(dāng)前位置求偏導(dǎo),即梯度,負(fù)梯度不斷增大接近零的方向( w w w的變化方向),就是不斷逼近函數(shù)極小值的方向。有時(shí)得到的是函數(shù)最小值的局部最優(yōu)解,如果損失函數(shù)是凸函數(shù),梯度下降法得到的解就是全局最優(yōu)解。
??一元函數(shù)的梯度(導(dǎo)數(shù))公式:
??假設(shè)損失函數(shù)為 J ( θ ) J(θ) J(θ),其中 θ θ θ是模型參數(shù),從一個(gè)初始點(diǎn) θ 0 θ_0 θ0?開始迭代,每次迭代更新 θ θ θ的值,直至損失函數(shù)值下降到一定程度,或者達(dá)到固定次數(shù)的迭代次數(shù)。每次迭代的更新公式:
其中, α α α是學(xué)習(xí)率,控制每一步迭代的步長(zhǎng)。學(xué)習(xí)率太小會(huì)導(dǎo)致收斂速度慢,而學(xué)習(xí)率太大會(huì)導(dǎo)致算法發(fā)散。因此,學(xué)習(xí)率是梯度下降法中需要調(diào)整的一個(gè)超參數(shù)。
??注意,超參數(shù)是指算法運(yùn)行之前手動(dòng)設(shè)置的參數(shù),用于控制模型的行為和性能。這些超參數(shù)的選擇會(huì)影響到模型的訓(xùn)練速度、收斂性、容量和泛化能力等方面,常見的超參數(shù)如學(xué)習(xí)率、迭代次數(shù)、正則化參數(shù)、隱藏層的神經(jīng)元數(shù)量等。
2. 多元函數(shù):模型含多個(gè)參數(shù)
??對(duì)于不同參數(shù) θ i θ_i θi?,其梯度定義為:
其中,函數(shù) J ( θ ) J(θ) J(θ)即為損失函數(shù),此時(shí)每次迭代的更新公式為:
直至損失函數(shù)值下降到一定程度,或者達(dá)到固定次數(shù)的迭代次數(shù)時(shí),算法終止。
【梯度下降法案例】
初始誤差(使用均方誤差函數(shù)): J ( x 1 ) = ( 2 ? 1.731 ) 2 / 2 J(x_1)=(2-1.731)^2/2 J(x1?)=(2?1.731)2/2
完成一輪更新后,損失函數(shù)的值更加逼近0,代表預(yù)測(cè)結(jié)果更加接近真實(shí)情況。
2.3模型訓(xùn)練流程
??在完成上文的學(xué)習(xí)后,可大致梳理出模型訓(xùn)練的大致流程:
- 1.以 N N N份的輸入數(shù)據(jù) X X X及其對(duì)應(yīng)的結(jié)果 Y Y Y(同樣為 N N N)份來搭建模型,常見模型如卷積神經(jīng)網(wǎng)絡(luò)。
- 2.開始訓(xùn)練,并設(shè)置模型訓(xùn)練的超參數(shù),如學(xué)習(xí)率、訓(xùn)練輪次等。
- 2.1輸入數(shù)據(jù)集 X X X,前向傳播得到訓(xùn)練結(jié)果 Y ′ Y' Y′。
- 2.2根據(jù)真實(shí)結(jié)果 Y Y Y計(jì)算損失函數(shù) J ( Θ ) J(Θ) J(Θ),其中,訓(xùn)練結(jié)果 Y ′ Y' Y′是關(guān)于參數(shù)集合 Θ Θ Θ的函數(shù)。
- 2.3利用梯度下降法進(jìn)行反向傳播,更新參數(shù)值,并重新進(jìn)行預(yù)測(cè)。
- 2.4重復(fù)上述過程直到滿足終止條件,從而得到模型。
- 3.利用模型對(duì)測(cè)試集進(jìn)行測(cè)試,滿足條件即可正常使用,否則調(diào)整超參數(shù)、模型類別等,重新訓(xùn)練模型。
2.4全連接神經(jīng)網(wǎng)絡(luò)的Pytorch實(shí)現(xiàn)
【1.導(dǎo)入相關(guān)包】
#1.導(dǎo)入相關(guān)包
import torch
import torch.nn as nn
import copy
import time
from torchsummary import summary
import torch
from torch import nn
from torchvision.datasets import FashionMNIST
from torchvision import transforms
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import math
import torch.utils.data as Datadevice = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)
【2.加載FashionMNIST數(shù)據(jù)集】
#2.加載FashionMNIST數(shù)據(jù)集
##定義數(shù)據(jù)預(yù)處理操作
transform = transforms.Compose([transforms.ToTensor(), #將PIL圖像或NumPy ndarray 轉(zhuǎn)換為FloatTensor,并在[0.,1.]范圍內(nèi)縮放圖像的像素值。transforms.Normalize((0.5,), (0.5,)) #對(duì)張量圖像進(jìn)行標(biāo)準(zhǔn)化,給出的均值(mean)和標(biāo)準(zhǔn)差(std)應(yīng)用于所有三個(gè)通道。這里均值和標(biāo)準(zhǔn)差設(shè)置為0.5,意味著[0,1]的輸入將被標(biāo)準(zhǔn)化到[-1,1]。對(duì)于灰度圖(如MNIST),只需要給出一個(gè)通道的均值和標(biāo)準(zhǔn)差。
])
##加載訓(xùn)練集、測(cè)試集
train_data = FashionMNIST(root="./", train=True, transform=transform, download=True)
test_data = FashionMNIST(root="./", train=False, transform=transform, download=True)
##構(gòu)建訓(xùn)練集、測(cè)試集加載器
train_loader = Data.DataLoader(dataset=train_data, batch_size=64, shuffle=True)
test_loader = Data.DataLoader(dataset=test_data, batch_size=64, shuffle=False)
##可視化訓(xùn)練數(shù)據(jù)
def show_img(train_loader,batch_size):for step, (x, y) in enumerate(train_loader):if step > 0: # 恒成立breakbatch_x = x.squeeze().numpy()batch_y = y.numpy()class_label = train_data.classes# 可視化fig = plt.figure(figsize=(int(math.sqrt(batch_size)), int(math.sqrt(batch_size))))for i in range(batch_size):ax = fig.add_subplot(int(math.sqrt(batch_size)), int(math.sqrt(batch_size)), i + 1, xticks=[], yticks=[])ax.imshow(batch_x[i], cmap=plt.cm.binary)ax.set_title(class_label[batch_y[i]])
show_img(train_loader,64)
【3.建立全連接神經(jīng)網(wǎng)絡(luò)模型】
#3.建立全連接神經(jīng)網(wǎng)絡(luò)模型
class SimpleNN(nn.Module):def __init__(self):super(SimpleNN, self).__init__()#784=28*28self.fc1 = nn.Linear(784, 128) self.fc2 = nn.Linear(128, 128) #預(yù)測(cè)結(jié)果為10個(gè)類別之一self.output = nn.Linear(128, 10) #定義前向傳播過程def forward(self, x):x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.output(x)return x
model=SimpleNN().to(device)
print(summary(model,input_size=(784,)))
【4.訓(xùn)練模型】
#4.訓(xùn)練模型
##使用Adam優(yōu)化器,設(shè)置學(xué)習(xí)率為0.001,model.parameters()將模型中所有需要被訓(xùn)練的參數(shù)傳入優(yōu)化器中
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
##使用交叉熵?fù)p失函數(shù)
criterion = nn.CrossEntropyLoss()
##設(shè)置訓(xùn)練輪次
epoch = 100
def train_model(model, train_loader, optimizer, criterion, epoch, device):for e in range(epoch):start_time=time.time()for images, labels in train_loader:images = images.to(device)labels = labels.to(device)images = images.view(-1, 28*28) #梯度清除optimizer.zero_grad()#前向傳播模型預(yù)測(cè)結(jié)果output = model(images)#計(jì)算預(yù)測(cè)結(jié)果與實(shí)際值的損失函數(shù)值loss = criterion(output, labels)#反向傳播,計(jì)算所有模型參數(shù)關(guān)于損失函數(shù)的梯度loss.backward()#更新參數(shù)optimizer.step()end_time=time.time()print("輪次{} 用時(shí) : {}".format(e+1, end_time-start_time))
train_model(model, train_loader, optimizer, criterion, epoch, device)
【5.測(cè)試模型】
#5.測(cè)試模型
def evaluate_model(model, test_loader, device):model.eval()total_correct = 0total = 0with torch.no_grad():for images, labels in test_loader:images = images.view(-1, 28*28).to(device)output = model(images)_, predicted = torch.max(output.data, 1)total += labels.size(0)total_correct += (predicted == labels.to(device)).sum().item()print(f'Accuracy: {100 * total_correct / total:.2f}%')
evaluate_model(model, test_loader, device)
【6.查看模型結(jié)構(gòu)】
#6.查看模型結(jié)構(gòu)
torch.save(model,'./SimpleNN.pth')
import netronmodelData = './SimpleNN.pth' # 定義模型數(shù)據(jù)保存的路徑
netron.start(modelData) # 輸出網(wǎng)絡(luò)結(jié)構(gòu)