以Mnist為例從頭開始自己建立數據集,搭建resnet34,識別Mnist
- 2019 年 11 月 7 日
- 筆記
寫在前面:
本人小白研一,剛開始學習深度學習,將自己的第一個實驗過程總結下來,看了很多的大牛的部落格,在下面的程式中也參考了很多大牛的部落格。在剛開始入門的學習的時候,直接編寫程式下載數據集,但是後來覺得可能會用到自己手動構建數據集。所以自己參考了一些部落格,嘗試了從自己手動構造數據集——搭建Resnet34網路——訓練——驗證的一整個過程。下面將自己的實驗過程記錄如下。本文重點介紹自己構建數據集與神經網路搭建部分
本人才疏學淺,剛入門,有錯誤紕漏的地方懇請各位批評指正。
第一章:
首先需要自己構建Mnist數據集,當然也可以自己從網路上下載。在這裡,由於本人有點作,想嘗試自己構造數據集,話不多說,直接貼程式碼
1 #!/usr/bin/env python 3.6 2 #_*_coding:utf-8 _*_ 3 #@Time :2019/11/7 9:10 4 #@Author :控制工程小白 5 #@FileName: 自己製作Mnist數據集.py 6 7 #@Software: PyCharm 8 import torch 9 import torchvision 10 from skimage import io 11 #import os 12 mnist_train=torchvision.datasets.MNIST('./make_mnistdata',train=True,download=True)#首先下載數據集,並數據分割成訓練集與數據集 13 mnist_test=torchvision.datasets.MNIST('./make_mnistdata',train=False,download=True) 14 print('testset:',len(mnist_test)) 15 #txt_path = "G:/Mnist_Recognition/mnist_label.txt" 16 # if not os.path.exists(txt_path): 17 # os.makedirs(txt_path) 18 f=open("./mnist_test.txt",'w')#在指定路徑之下生成.txt文件 19 for i,(img,label) in enumerate(mnist_test): 20 img_path = "./mnist_test/" + str(i) + ".jpg" 21 io.imsave(img_path, img)#將圖片數據以圖片.jpg格式存在指定路徑下 22 img_paths=img_path+str(i)+".jpg" 23 f.write(img_path+' '+str(label)+'n')#將路徑與標籤組合成的字元串存在.txt文件下 24 f.close()#關閉文件
注意,在運行這段程式碼之前應該在根目錄下新建一個mnist_train文件夾用於存放訓練集的圖片,新建mnist_test文件夾用於存放測試集的圖片,運行這段程式碼之後會生成一個mnist_test.txt與mnist_train.txt 文件,用來儲存各個字元串,這個字元串由每個圖片的路徑與對應的標籤組成,至於這樣做有什麼用,請看下文。貼一下上述程式碼運行結果
第二章:
下面將會用到上一章生成的.txt 文件,先上程式碼
1 #!/usr/bin/env python 3.6 2 #_*_coding:utf-8 _*_ 3 #@Time :2019/11/7 11:38 4 #@Author :控制工程小白 5 #@FileName: My_dataset.py 6 7 #@Software: PyCharm 8 from PIL import Image 9 import torch 10 from torch.utils import data 11 import torchvision.transforms as transforms 12 from torch.utils.data import DataLoader 13 import matplotlib.pyplot as plt 14 class MyDataset(data.Dataset): 15 def __init__(self,datatxt,transform=None,target_transform=None): 16 super(MyDataset,self).__init__() 17 fh=open(datatxt,'r')#讀取標籤文件.txt 18 imgs=[]#暫時定義一個空的列表 19 for line in fh: 20 line.strip('n')#出去字元串末尾的空格、製表符 21 words=line.split()#將路徑名與標籤分離出來 22 imgs.append((words[0],int(words[1])))#word[0]表示圖片的路徑名,word[1]表示該數字圖片對應的標籤 23 self.imgs=imgs 24 self.transform=transform 25 self.target_transform=target_transform 26 #self.loader=loader 27 def __getitem__(self, index): 28 fn,label=self.imgs[index]#fn表示圖片的路徑 29 img = Image.open(fn)#.convert('RGB'),這裡時候需要轉換成RGB影像視神經網路結構而定,讀取文件的路徑名,也即打開圖片 30 if self.transform is not None: 31 img=self.transform(img) 32 return img,label#返回圖片與標籤 33 def __len__(self): 34 return len(self.imgs)
這段程式碼構造了一個類,用於獲取剛剛建立的數據集,思想就是讀取剛剛建立的.txt文件,將其中的圖片的路徑名與該圖片對應的標籤分離,然後根據根據圖片的路徑名獲取數據集。
第三章:
搭建神經網路,隨著深度學習的發展,已經出現了很多種神經網路,一般而言,神經網路越深越好,但是神經網路的維度太深的話,會導致神經網路過擬合,於是開發者開發了一種殘差神經網路Resnet,它是由很多個殘差快組成,每個殘差塊都包含跳連接,防止過擬合,這樣可以達到網路更深同時性能不會受到過擬合的影響。
下面直接貼Resnet34程式碼
#!/usr/bin/env python 3.6 #_*_coding:utf-8 _*_ #@Time :2019/11/7 15:44 #@Author :hujinzhou #@FileName: neural_network4.py #@Software: PyCharm import torch.nn as nn class Reslock(nn.Module): def __init__(self, in_channels, out_channels, stride=1): super(Reslock, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1) self.bn1 = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1) self.bn2 = nn.BatchNorm2d(out_channels) if in_channels != out_channels: self.downsample = nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=2), nn.BatchNorm2d(out_channels) ) else: self.downsample = None def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out class ResNet34(nn.Module): def __init__(self, num_classes=10): super(ResNet34, self).__init__() self.first = nn.Sequential( nn.Conv2d(1, 64, 7, 2, 3), nn.BatchNorm2d(64), nn.ReLU(inplace=True), nn.MaxPool2d(3, 1, 1) ) self.layer1 = self.make_layer(64, 64, 3, 1) self.layer2 = self.make_layer(64, 128, 4, 2) self.layer3 = self.make_layer(128, 256, 6, 2) self.layer4 = self.make_layer(256, 512, 3, 2) self.avg_pool = nn.AvgPool2d(2) self.fc = nn.Linear(512, num_classes) def make_layer(self, in_channels, out_channels, block_num, stride): layers = [] layers.append(Reslock(in_channels, out_channels, stride)) for i in range(block_num - 1): layers.append(Reslock(out_channels, out_channels, 1)) return nn.Sequential(*layers) def forward(self, x): x = self.first(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = self.avg_pool(x) # x.size()[0]: batch size x = x.view(x.size()[0], -1) x = self.fc(x) return x
第四章:
上述過程弄好了,下面的過程就非常簡單了,下面直接訓練並識別驗證就可以了,訓練程式碼與驗證程式碼就很簡單了,在本文中直接貼訓練結果圖與識別精度圖