深度學習之PyTorch —— CNN實現MNIST手寫數字分類
阿新 • • 發佈:2018-12-20
# 運用CNN分析MNIST手寫數字分類 import torch import numpy as np from torch.utils.data import DataLoader from torchvision.datasets import mnist from torch import nn from torch.autograd import Variable from torch import optim from torchvision import transforms # 定義CNN class CNN(nn.Module): def __init__(self): super(CNN,self).__init__() self.layer1 = nn.Sequential( nn.Conv2d(1,16,kernel_size=3), # 16, 26 ,26 nn.BatchNorm2d(16), nn.ReLU(inplace=True)) self.layer2 = nn.Sequential( nn.Conv2d(16,32,kernel_size=3),# 32, 24, 24 nn.BatchNorm2d(32), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2,stride=2)) # 32, 12,12 (24-2) /2 +1 self.layer3 = nn.Sequential( nn.Conv2d(32,64,kernel_size=3), # 64,10,10 nn.BatchNorm2d(64), nn.ReLU(inplace=True)) self.layer4 = nn.Sequential( nn.Conv2d(64,128,kernel_size=3), # 128,8,8 nn.BatchNorm2d(128), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2,stride=2)) # 128, 4,4 self.fc = nn.Sequential( nn.Linear(128 * 4 * 4,1024), nn.ReLU(inplace=True), nn.Linear(1024,128), nn.ReLU(inplace=True), nn.Linear(128,10)) def forward(self,x): x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = x.view(x.size(0),-1) x = self.fc(x) return x # 使用內建函式下載mnist資料集 train_set = mnist.MNIST('./data',train=True) test_set = mnist.MNIST('./data',train=False) # 預處理=>將各種預處理組合在一起 data_tf = transforms.Compose( [transforms.ToTensor(), transforms.Normalize([0.5],[0.5])]) train_set = mnist.MNIST('./data',train=True,transform=data_tf,download=True) test_set = mnist.MNIST('./data',train=False,transform=data_tf,download=True) train_data = DataLoader(train_set,batch_size=64,shuffle=True) test_data = DataLoader(test_set,batch_size=128,shuffle=False) net = CNN() criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(),1e-1) nums_epoch = 20 # 開始訓練 losses =[] acces = [] eval_losses = [] eval_acces = [] for epoch in range(nums_epoch): train_loss = 0 train_acc = 0 net = net.train() for img , label in train_data: #img = img.reshape(img.size(0),-1) img = Variable(img) label = Variable(label) # 前向傳播 out = net(img) loss = criterion(out,label) # 反向傳播 optimizer.zero_grad() loss.backward() optimizer.step() # 記錄誤差 train_loss += loss.item() # 計算分類的準確率 _,pred = out.max(1) num_correct = (pred == label).sum().item() acc = num_correct / img.shape[0] train_acc += acc losses.append(train_loss / len(train_data)) acces.append(train_acc / len(train_data)) eval_loss = 0 eval_acc = 0 # 測試集不訓練 for img , label in test_data: #img = img.reshape(img.size(0),-1) img = Variable(img) label = Variable(label) out = net(img) loss = criterion(out,label) # 記錄誤差 eval_loss += loss.item() _ , pred = out.max(1) num_correct = (pred==label).sum().item() acc = num_correct / img.shape[0] eval_acc += acc eval_losses.append(eval_loss / len(test_data)) eval_acces.append(eval_acc / len(test_data)) print('Epoch {} Train Loss {} Train Accuracy {} Teat Loss {} Test Accuracy {}'.format( epoch+1, train_loss / len(train_data),train_acc / len(train_data), eval_loss / len(test_data), eval_acc / len(test_data)))
輸出:
Epoch 1 Train Loss 0.14103838276348388 Train Accuracy 0.9574893390191898 Teat Loss 0.03636252877738657 Test Accuracy 0.9888251582278481 Epoch 2 Train Loss 0.03642434606165774 Train Accuracy 0.9888059701492538 Teat Loss 0.0744408220288497 Test Accuracy 0.9761669303797469 Epoch 3 Train Loss 0.025223525594483053 Train Accuracy 0.9920542377398721 Teat Loss 0.02412710657131068 Test Accuracy 0.9920886075949367 Epoch 4 Train Loss 0.020014993536637535 Train Accuracy 0.9937533315565032 Teat Loss 0.022930343906524816 Test Accuracy 0.9923852848101266 Epoch 5 Train Loss 0.015570432650668027 Train Accuracy 0.9948694029850746 Teat Loss 0.019973596770174896 Test Accuracy 0.992879746835443 Epoch 6 Train Loss 0.011754893727584688 Train Accuracy 0.99605210554371 Teat Loss 0.01934802131373671 Test Accuracy 0.9936708860759493
因個人用CPU運算速度問題,這次僅訓練六次。相比上篇部落格,比只簡單用全連線神經網路準確率要高,達到99%。
有什麼問題歡迎評論。