最近在學(xué)習(xí)pytorch矩动,在學(xué)過了linear分類以后嘗試入門cnn,但是網(wǎng)上的教程基本都是使用別人標注好的手寫數(shù)據(jù)集篮迎。于是我看了下讀入圖片的數(shù)據(jù)格式甜橱,發(fā)現(xiàn)是一個n*1*size*size的數(shù)組栈戳,了解到這個基本情況以后,我們可以嘗試不用導(dǎo)入mnist數(shù)據(jù)集而使用自己的訓(xùn)練模型來幫助我們更好的理解相關(guān)參數(shù)的意義镊掖。
我們主要使用pytorch包裝好的nn.Module來訓(xùn)練我們的神經(jīng)網(wǎng)絡(luò)堰乔,手工做的暫不做討論脐恩,同時我也推薦使用這種方式來訓(xùn)練神經(jīng)網(wǎng)絡(luò)驶冒。
由于簡書不支持代碼塊的引入,我會把代碼放在文末鏈接崇猫。
本教程適用于pytorch 0.3.0 python 3.6.5
首先在開頭把需要的包引入
隨后我們寫下第一行:
torch.set_default_tensor_type("torch.DoubleTensor")
如果沒有這句代碼pytorch就會提示RuntimeError: Expected object of type torch.DoubleTensor but found type torch.FloatTensor for argument #2 'weight',大家可以試試去掉這一句
隨后诅炉,我們就要開始定義我們的“訓(xùn)練模型了”
trainx就是兩張要作為輸入的5*5的圖片涕烧,一個是1汗洒,一個是2溢谤。我先解釋為什么有一個數(shù)字是0.0,因為pytorch要求均是小數(shù)格式阀参,加了一個0.0瞻坝,整個數(shù)組就會自動轉(zhuǎn)換成為float了湿镀。trainy也有兩組數(shù)據(jù),第一組輸出[1,0]表示輸出的是1,第二組輸出的是[0,1]表示輸出的是2,10的話就往上推廣即可赫模。至此我們的訓(xùn)練數(shù)據(jù)就準備好了蒸矛。按照前面所說是一個n*1*size*size的數(shù)組,滿足這個條件就可以了斩祭,因為從mnist里面讀取進來的數(shù)據(jù)也是這樣的摧玫。
準備好訓(xùn)練數(shù)據(jù)以后,就要開始定義最重要的類了:
先來講解__init__ 的內(nèi)容:
第一步是執(zhí)行父類的構(gòu)造函數(shù),沒毛病
13行坏挠,定義第一個卷積層降狠,我比較推薦使用nn.Sequential方式,這樣當(dāng)在調(diào)用的時候conv1(x)否纬,他就會自動按照順序執(zhí)行括號里的步驟:卷積歸一激活池化
18行定義第二個卷積層烦味,同上
23行定義一層全連接層壁拉,輸出2個結(jié)果,即[1,0]還是[0,1]的形式
關(guān)鍵我要詳細說說前兩個卷積層的結(jié)構(gòu)
第一個卷積層,1,16,其含義是我們將會給他輸入一張5*5的圖片痘昌,他會輸出16個特征層辆苔,什么是特征層呢驻啤?類似下圖
特征層就是左邊第一個conv,看到了吧【當(dāng)然這張圖是我在網(wǎng)上找來參考的】,一張圖片連了16根線到16個conv層上赊瞬,這就是第一個步驟,代碼中我們定義了kernel_size=5,padding=1薯蝎,那么經(jīng)過這一步以后占锯,一張5*5的圖片會輸出3*3的一個結(jié)果
所謂padding,就是在圖片周圍補上一圈其他的數(shù)闷供,kernel就是視野大小歪脏,如果不太清楚這兩個概念的可以百度一下補補概念
在經(jīng)過卷積以后婿失,5*5變成了3*3,隨后是歸一化和激活啄寡,在最后一步是最大池化挺物,池化的kernel為2,那么一個3*3的會變?yōu)?*2的輸出
那么經(jīng)過self.conv1函數(shù)以后砚著,現(xiàn)在得到了16張2*2的特征圖
那么給下一層的輸入就是16張2*2的特征圖了稽穆,第二個卷積層就要對輸入作出一點改變了
我們可以看到舌镶,第二個卷積層接受來自上一層的16個特征圖輸入豪娜,同時輸出32個特征圖瘤载,那么此時kernel_size就要按照2*2來設(shè)計了,我們可以設(shè)置 kernel_size=2,padding=1,那么輸出就為32個3*3的特征圖坟冲,再經(jīng)過池化以后,得到32個1*1的輸出?
那么最后一層就是一個全連接層把32個輸出連接到2個輸出節(jié)點來,這就是整個網(wǎng)絡(luò)的結(jié)構(gòu)
網(wǎng)絡(luò)定義好了脐嫂,我們接下來就要定義數(shù)據(jù)正向傳播的forward函數(shù)紊遵,pytorch內(nèi)部擁有自動求導(dǎo)機制暗膜,所以求導(dǎo)的機制不用我們特別理解,我們只需定義好正向傳播即可
我們依次來解說:
第一步娃善,直接把x放入conv1中運算
第二步聚磺,接著把第一層的輸出放到第二層中運算
第三部炬丸,最重要的稠炬,out.view,在out=self.conv2(out)捣鲸,經(jīng)過第二層卷積操作以后闽坡,現(xiàn)在我們得到的是一個2*32*1*1的矩陣疾嗅,我們?nèi)粢B接外厂,則要把矩陣從2*32*1*1化為2*32,那么我們就要用到view函數(shù)
其實pytorch和numpy里面關(guān)于矩陣reshape的函數(shù)很多代承,視情況使用汁蝶。
在我們統(tǒng)一了矩陣以后,就可以接著把結(jié)果放入FullConnection層中進行運算了,函數(shù)的最后返回結(jié)果。
好了掖棉,這就是CLASS的核心定義墓律,我們開始訓(xùn)練這個神經(jīng)網(wǎng)絡(luò)。
好了那大概就是這樣了~滑稽
代碼地址?點我進入a:ァ3芊怼E撩蕖U敕省!
有問題希望一起討論香伴。
碼字不易慰枕,如果你覺得對你有幫助,希望可以動手贊助一下~你的支持是更新的動力