這篇文章主要介紹“利用Pytorch進行CNN分析”,在日常操作中,相信很多人在利用Pytorch進行CNN分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”利用Pytorch進行CNN分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
成都創(chuàng)新互聯(lián)公司公司2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務公司,擁有項目成都網(wǎng)站制作、成都網(wǎng)站設(shè)計、外貿(mào)營銷網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元豐都做網(wǎng)站,已為上家服務,為豐都各地企業(yè)和個人服務,聯(lián)系電話:18980820575
工具
開源深度學習庫: PyTorch
數(shù)據(jù)集: MNIST
實現(xiàn)
初始要求
首先建立基本的BASE網(wǎng)絡,在Pytorch中有如下code:
class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1), padding=0) self.conv2 = nn.Conv2d(20, 50, kernel_size=(5, 5), stride=(1, 1), padding=0) self.fc1 = nn.Linear(4*4*50, 500) self.fc2 = nn.Linear(500, 10) def forward(self, x): x = F.max_pool2d(self.conv1(x), 2) x = F.max_pool2d(self.conv2(x), 2) x = x.view(-1, 4*4*50) x = F.relu(self.fc1(x)) x = self.fc2(x) return F.log_softmax(x)
這部分代碼見 base.py 。
問題A:預處理
即要求將MNIST數(shù)據(jù)集按照規(guī)則讀取并且tranform到適合處理的格式。這里讀取的代碼沿用了BigDL Python Support的讀取方式,無需細說,根據(jù)MNIST主頁上的數(shù)據(jù)格式可以很快讀出,關(guān)鍵block有讀取32位比特的函數(shù):
def _read32(bytestream): dt = numpy.dtype(numpy.uint32).newbyteorder('>') # 大端模式讀取,***字節(jié)在前(MSB first) return numpy.frombuffer(bytestream.read(4), dtype=dt)[0]
讀出后是(N, 1, 28, 28)的tensor,每個像素是0-255的值,首先做一下歸一化,將所有值除以255,得到一個0-1的值,然后再Normalize,訓練集和測試集的均值方差都已知,直接做即可。由于訓練集和測試集的均值方差都是針對歸一化后的數(shù)據(jù)來說的,所以剛開始沒做歸一化,所以forward輸出和grad很離譜,后來才發(fā)現(xiàn)是這里出了問題。
這部分代碼見 preprocessing.py 。
問題B:BASE模型
將random seed設(shè)置為0,在前10000個訓練樣本上學習參數(shù),***看20個epochs之后的測試集錯誤率。***結(jié)果為:
Test set: Average loss: 0.0014, Accuracy: 9732/10000 (97.3%)
可以看到,BASE模型準確率并不是那么的高。
問題C:Batch Normalization v.s BASE
在前三個block的卷積層之后加上Batch Normalization層,簡單修改網(wǎng)絡結(jié)構(gòu)如下即可:
class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1), padding=0) self.conv2 = nn.Conv2d(20, 50, kernel_size=(5, 5), stride=(1, 1), padding=0) self.fc1 = nn.Linear(4*4*50, 500) self.fc2 = nn.Linear(500, 10) self.bn1 = nn.BatchNorm2d(20) self.bn2 = nn.BatchNorm2d(50) self.bn3 = nn.BatchNorm1d(500) def forward(self, x): x = self.conv1(x) x = F.max_pool2d(self.bn1(x), 2) x = self.conv2(x) x = F.max_pool2d(self.bn2(x), 2) x = x.view(-1, 4*4*50) x = self.fc1(x) x = F.relu(self.bn3(x)) x = self.fc2(x) return F.log_softmax(x)
同樣的參數(shù)run一下,得出加了BN的結(jié)果為:
Test set: Average loss: 0.0009, Accuracy: 9817/10000 (98.2%)
由此可見,有明顯的效果提升。
關(guān)于Batch Normalization的更多資料參見[2],[5]。
問題D: Dropout Layer
在***一層即 fc2 層后加一個 Dropout(p=0.5) 后,在BASE和BN上的結(jié)果分別為:
BASE:Test set: Average loss: 0.0011, Accuracy: 9769/10000 (97.7%) BN: Test set: Average loss: 0.0014, Accuracy: 9789/10000 (97.9%)
觀察得知,dropout能夠?qū)ASE模型起到一定提升作用,但是對BN模型卻效果不明顯反而降低了。
原因可能在于,BN模型中本身即包含了正則化的效果,再加一層Dropout顯得沒有必要反而可能影響結(jié)果。
問題E:SK model
SK model: Stacking two 3x3 conv. layers to replace 5x5 conv. layer
如此一番改動后,搭建的SK模型如下:
class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1_1 = nn.Conv2d(1, 20, kernel_size=(3, 3), stride=(1, 1), padding=0) self.conv1_2 = nn.Conv2d(20, 20, kernel_size=(3, 3), stride=(1, 1), padding=0) self.conv2 = nn.Conv2d(20, 50, kernel_size=(3, 3), stride=(1, 1), padding=0) self.fc1 = nn.Linear(5*5*50, 500) self.fc2 = nn.Linear(500, 10) self.bn1_1 = nn.BatchNorm2d(20) self.bn1_2 = nn.BatchNorm2d(20) self.bn2 = nn.BatchNorm2d(50) self.bn3 = nn.BatchNorm1d(500) self.drop = nn.Dropout(p=0.5) def forward(self, x): x = F.relu(self.bn1_1(self.conv1_1(x))) x = F.relu(self.bn1_2(self.conv1_2(x))) x = F.max_pool2d(x, 2) x = self.conv2(x) x = F.max_pool2d(self.bn2(x), 2) x = x.view(-1, 5*5*50) x = self.fc1(x) x = F.relu(self.bn3(x)) x = self.fc2(x) return F.log_softmax(x)
在20個epoch后,結(jié)果如下,
SK: Test set: Average loss: 0.0008, Accuracy: 9848/10000 (98.5%)
測試集準確率得到了少許的提高。
這里利用2個3x3的卷積核來代替大的5x5卷積核,參數(shù)個數(shù)由5x5=25變?yōu)榱?x3x3=18。實踐表明,這樣使得計算更快了,并且小的卷積層之間的ReLU也很有幫助。
VGG中就使用了這種方法。
問題F:Change Number of channels
通過將特征圖大小乘上一個倍數(shù),再通過shell程序執(zhí)行,得到如下結(jié)果:
SK0.2: 97.7% SK0.5: 98.2% SK1: 98.5% SK1.5: 98.6% SK2: 98.5% (max 98.7%)
在特征圖分別為4,10, 30, 40時,最終的準確度基本是往上提升的。這在一定程度上說明,在沒有達到過擬合前,增大特征圖的個數(shù),即相當于提取了更多的特征,提取特征數(shù)的增加有助于精度的提高。
這部分代碼見 SK_s.py 和 runSK.sh 。
問題G:Use different training set sizes
同樣通過腳本運行,增加參數(shù)
parser.add_argument('--usedatasize', type=int, default=60000, metavar='SZ', help='use how many training data to train network')
表示使用的數(shù)據(jù)大小,從前往后取 usebatchsize 個數(shù)據(jù)。
這部分程序見 SK_s.py 和 runTrainingSize.sh 。
運行的結(jié)果如下:
500: 84.2% 1000: 92.0% 2000: 94.3% 5000: 95.5% 10000: 96.6% 20000: 98.4% 60000: 99.1%
由此可以明顯地看出,數(shù)據(jù)越多,結(jié)果的精度越大。
太少的數(shù)據(jù)無法準確反映數(shù)據(jù)的整體分布情況,而且容易過擬合,數(shù)據(jù)多到一定程度效果也會不明顯,不過,大多數(shù)時候我們總還是嫌數(shù)據(jù)太少,而且更多的數(shù)據(jù)獲取起來也有一定難度。
問題H:Use different training sets
采用腳本完成,這部分程序見 SK_0.2.py 和 diffTrainingSets.sh 。
運行結(jié)果如下:
0-10000: 98.0% 10000-20000: 97.8% 20000-30000: 97.8% 30000-40000: 97.4% 40000-50000: 97.5% 50000-60000: 97.7%
由此可見,采用不同的訓練樣本集合訓練出來的網(wǎng)絡有一定的差異,雖不是很大,但是畢竟顯示出了不穩(wěn)定的結(jié)果。
問題I:Random Seed’s effects
采用 runSeed.sh 腳本完成,用到了全部60000個訓練集。
運行的結(jié)果如下:
Seed 0: 98.9% Seed 1: 99.0% Seed 12: 99.1% Seed 123: 99.0% Seed 1234: 99.1% Seed 12345: 99.0% Seed 123456: 98.9%
事實上在用上整個訓練集的時候,隨機數(shù)生成器的種子設(shè)置對于***結(jié)果的影響不大。
問題J:ReLU or Sigmoid?
將ReLU全部換成Sigmoid后,用全部60000個訓練集訓練,有對比結(jié)果如下:
ReLU SK_0.2: 99.0% igmoid SK_0.2: 98.6%
由此可以看出,在訓練CNN時,使用ReLU激活單元比Sigmoid激活單元要更好一些。原因可能在于二者機制的差別,sigmoid在神經(jīng)元輸入值較大或者較小時,輸出值會近乎0或者1,這使得許多地方的梯度幾乎為0,權(quán)重幾乎得不到更新。而ReLU雖然增加了計算的負擔,但是它能夠顯著加速收斂過程,并且也不會有梯度飽和問題。
到此,關(guān)于“利用Pytorch進行CNN分析”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
當前標題:利用Pytorch進行CNN分析
文章網(wǎng)址:http://m.rwnh.cn/article20/jepoco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、響應式網(wǎng)站、網(wǎng)站營銷、企業(yè)網(wǎng)站制作、電子商務、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)