【Pytorch实战】CNN多分类 (MNIST图片数据集分类)

1、【网络结构分析】bash

手写数字识别数据集,数据集训练样本是60000张28 * 28的灰度图,测试集是10000张28 * 28的灰度图,作10分类,即0-9。 主要目的是练习使用CNN搭建网络框架,采用4个卷积层,1个池化层和一个全链接层的方式。因为训练集的batch——size是128,因此每一step训练样本是128个,本例中每步训练过程当中数据变化过程以下: 网络

2、【知识点整理】app

1.每一个卷积层中是包含激活函数的:框架

每一个conv表明一个卷积层,卷积层内不止是进行了nn.Conv2d二维卷积操做,还有激活函数,不要忘记了。ide

2.torch.nn.BatchNorm2d():函数

在每一个卷积层中,nn.Conv2d以后,先进行nn.BatchNorm2d作数据的归一化处理,再加入激活函数,做用是使得数据在进行Relu以前不会由于数据过大而致使网络性能的不稳定。公式以下:性能

3.在与全链接层衔接时,对数据作维度拉伸处理:测试

将最后一次卷积的输出拉伸为一行,每个输入都拉成一个维度以知足全链接层的输入要求,即将128 * 1 * 1 * 64的矩阵x变为128 * 64:优化

x=x.view(x.size(0),-1)ui

3、【源代码】

# 定义网络结构
import torch 
import numpy as np
from torch.utils import data # 获取迭代数据
from torch.autograd import Variable # 获取变量
import torchvision
from torchvision.datasets import mnist # 获取数据集
import matplotlib.pyplot as plt
class CNNnet(torch.nn.Module):
    def __init__(self):
        super(CNNnet,self).__init__()
        self.los=torch.nn.CrossEntropyLoss()
        self.conv1 = torch.nn.Sequential(
            torch.nn.Conv2d(in_channels=1,
                            out_channels=16,
                            kernel_size=3,
                            stride=2,
                            padding=1),
            torch.nn.BatchNorm2d(16),
            torch.nn.ReLU()
        )
        self.conv2 = torch.nn.Sequential(
            torch.nn.Conv2d(16,32,3,2,1),
            torch.nn.BatchNorm2d(32),
            torch.nn.ReLU()
        )
        self.conv3 = torch.nn.Sequential(
            torch.nn.Conv2d(32,64,3,2,1),
            torch.nn.BatchNorm2d(64),
            torch.nn.ReLU()
        )
        self.conv4 = torch.nn.Sequential(
            torch.nn.Conv2d(64,64,2,2,0),
            torch.nn.BatchNorm2d(64),
            torch.nn.ReLU()
        )
        self.maxpool=torch.nn.AdaptiveMaxPool2d((1,1))
        self.mlp1 = torch.nn.Linear(1*1*64,10)
        #self.mlp2 = torch.nn.Linear(100,10)
        self.opt=torch.optim.Adam(params=self.parameters(),lr=0.1)
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x=self.maxpool(x)
        x = self.mlp1(x.view(x.size(0),-1))
        #x = self.mlp2(x)
        return x
    def train(self,x,label):
        out=self.forward(x)# 获取最后输出
        loss=self.los(out,label) # 获取损失
        #利用优化器优化损失
        self.opt.zero_grad()  # 清空上一步残余更新参数值
        loss.backward() # 偏差反向传播,计算参数更新值
        self.opt.step() # 将参数更新值施加到net的parmeters上
        return loss
def getdata():
    data_tf = torchvision.transforms.Compose(
    [
        torchvision.transforms.ToTensor(),
        torchvision.transforms.Normalize([0.5],[0.5])
    ]
    )
    train_data = mnist.MNIST('./dataset/mnist/train',train=True,transform=data_tf,download=True)#60000张图片,每张28*28
    test_data = mnist.MNIST('./dataset/mnist/test',train=False,transform=data_tf,download=True)#10000张图片
    return train_data,test_data
if __name__=='__main__':
    train_data,test_data=getdata()
    train_loader=data.DataLoader(train_data,batch_size=128,shuffle=True)
    test_loader=data.DataLoader(test_data,batch_size=1000,shuffle=True) 
    model = CNNnet()
    loss_count = []
    acc=[]
    for epoch in range(2):
        for i,(x,y) in enumerate(train_loader):
            loss=model.train(x,y)
            if i%20 == 0:
                loss_count.append(loss)
            if i % 100 == 0:
                for a,b in test_loader:
                    test_x = Variable(a)
                    test_y = Variable(b)
                    out = model.forward(test_x)
                    pred_y=torch.max(out, 1)[1]
                    accuracy =(pred_y.data.numpy() == test_y.data.numpy()).astype(int).sum()/float(test_y.numpy().size)
                    acc.append(accuracy)
                    break
    #每20*128个数据量,即每20step计算一次损失值
    plt.figure('PyTorch_CNN_Loss')
    plt.plot(loss_count,label='Loss')
    plt.legend()
    plt.show()
    #训练集每100step,对1000个训练数据作预测,计算准确率
    plt.figure('accuracy')
    plt.plot(acc,label='accuracy')
    plt.legend()
    plt.show
复制代码

相关文章
相关标签/搜索