pytorch学习笔记——网络架构再调整(6)

之前使用了BatchNorm方案进行正则化,效果尚不是很好。是不是我们的网络没有提升空间了呢?我们换一个角度对我们之前的网络架构进行审视。之前的架构,每次卷积层的padding都为0,从某个层面上来说我们并没有充分利用好图像的边缘信息,于是我们对网络的架构进行了再次的调整。将部卷积层的padding置为1,并使用大卷积核,与此同时在末尾增加了池化层。改良后的网络架构如下:

        Layer (type)               Output Shape         Param #
            Conv2d-1 3*3              [-1, 4, 8, 8]              40
       BatchNorm2d-2              [-1, 4, 8, 8]               8
            Conv2d-3 3*3             [-1, 8, 8, 8]             296
       BatchNorm2d-4              [-1, 8, 8, 8]              16
              ReLU-5              [-1, 8, 8, 8]               0
         MaxPool2d-6              [-1, 8, 4, 4]               0
            Conv2d-7 3*3            [-1, 16, 4, 4]           1,168
       BatchNorm2d-8             [-1, 16, 4, 4]              32
              ReLU-9             [-1, 16, 4, 4]               0
        MaxPool2d-10             [-1, 16, 2, 2]               0
           Linear-11                   [-1, 10]             650
Total params: 2,210
Trainable params: 2,210
Non-trainable params: 0

训练结果如下:
pytorch学习笔记——网络架构再调整(6)_第1张图片
果然,训练效果相比之前的架构又有所提升,最好的测试集准确率超过了99%,说明我们之前的判断是准确的。
附网络架构改变以后的代码:

import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
from sklearn.datasets import load_digits
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
import torch as t
import torch.nn as nn
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt
from graphviz import Digraph
import torch
from torch.autograd import Variable
from torchsummary import summary

class train_mini_mnist(t.utils.data.Dataset):
    def __init__(self):
        self.X,self.y=load_digits(return_X_y=True)
        self.X_train,self.X_test,self.y_train,self.y_test=train_test_split(self.X,self.y,random_state=0)
        
    def __getitem__(self, index):
        return t.tensor(self.X_train[index].reshape(1,8,8),dtype=torch.float32),self.y_train[index]
    def __len__(self):
        return len(self.y_train)

class test_mini_mnist(t.utils.data.Dataset):
    def __init__(self):
        self.X,self.y=load_digits(return_X_y=True)
        self.X_train,self.X_test,self.y_train,self.y_test=train_test_split(self.X,self.y,random_state=0)
    def __getitem__(self, index):
        return t.tensor(self.X_test[index].reshape(1,8,8),dtype=torch.float32),self.y_test[index]
    def __len__(self):
        return len(self.y_test)

BATCH_SIZE=4
LEARNING_RATE=3e-3
EPOCHES=100

train_data=train_mini_mnist()
test_data=test_mini_mnist()

train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
test_loader = Data.DataLoader(dataset=test_data, batch_size=BATCH_SIZE, shuffle=True)

class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.conv1 = nn.Sequential(#(1, 8, 8)
            nn.Conv2d(in_channels=1, out_channels=4, kernel_size=3, stride=1, padding=1),#(4, 8, 8) 
            nn.BatchNorm2d(4),
            nn.Conv2d(in_channels=4, out_channels=8, kernel_size=3, stride=1, padding=1),#(8, 8, 8) 
            nn.BatchNorm2d(8),
            nn.ReLU(),#(8,8,8)
            nn.MaxPool2d(kernel_size=2)#(8,4,4)
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(in_channels=8, out_channels=16, kernel_size=3, stride=1, padding=1),#(16, 4, 4) 
            nn.BatchNorm2d(16),
            nn.ReLU(),#(16,2,2)
            nn.MaxPool2d(kernel_size=2)#(16,2,2)
        )
        self.fc = nn.Linear(16*2*2, 10)
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)#相当于Flatten
        x = self.fc(x)
        return x

def eval_on_dataloader(name,loader,len):
    acc = 0.0
    with torch.no_grad():
        for data in loader:
            images, labels = data
            outputs = net(images)
            predict_y = torch.max(outputs, dim=1)[1]#torch.max返回两个数值,一个是最大值,一个是最大值的下标
            acc += (predict_y == labels).sum().item()
        accurate = acc / len
        return accurate

def plot_train_and_test_result(train_accs,test_accs):
    epoches=np.arange(1,len(train_accs)+1,dtype=np.int32)
    plt.plot(epoches,train_accs,label="train_accuracy")
    plt.plot(epoches,test_accs,label="test_accuracy")
    plt.xlabel('epoches')
    plt.ylabel('accuracy')
    plt.legend()



net = SimpleNet()



summary(net, (1, 8, 8))


loss_fn = nn.CrossEntropyLoss()
optim = torch.optim.Adam(net.parameters(), lr = LEARNING_RATE)


for name,parameters in net.named_parameters():
    print(name,":",parameters.size())
best_acc = 0.0

train_accs,test_accs=[],[]
for epoch in range(EPOCHES):

    net.train()#切换到训练模式

    for step, data in enumerate(train_loader, start=0):
        images, labels = data
        optim.zero_grad()#将优化器的梯度清零
        logits = net(images)#网络推断的输出
        loss = loss_fn(logits, labels.long())#计算损失函数
        loss.backward()#反向传播求梯度
        optim.step()#优化器进一步优化

        rate = (step+1)/len(train_loader)
        a = "*" * int(rate * 50)
        b = "." * int((1 - rate) * 50)
        print("\rtrain loss: {:^3.0f}%[{}->{}]{:.4f}".format(int(rate*100), a, b, loss), end="")
    print()

    net.eval()#切换到测试模式

    train_acc=eval_on_dataloader("train",train_loader,train_data.__len__())
    test_acc=eval_on_dataloader("test",test_loader,test_data.__len__())
    train_accs.append(train_acc)
    test_accs.append(test_acc)
    print("epoch:",epoch,"train_acc:",train_acc," test_acc:",test_acc)

print('Finished Training')
plot_train_and_test_result(train_accs,test_accs)
plt.show()

你可能感兴趣的:(pytorch,神经网络,卷积核,深度学习,手写数字识别)