基于PyTorch的CNN卷积神经网络识别MNIST手写数字

本篇博客主要介绍基于PyTorch深度学习框架来实现MNIST经典的手写数字,运用CNN卷积神经网络。

MNIST数据集来自美国国家标准与技术研究所,其中训练数据有60000张,测试数据有10000张,每张图片的大小是28*28像素

我们可以基于PyTorch直接下载该数据集。该识别程序先使用一层卷积层(卷积核数量16,卷积核大小5*5,步长为1,允许边缘扩充),紧接着激活层使用ReLU函数,之后紧跟着一个max pooling层,大小是2*2. 之后再设置同样的卷积层(卷积核为2种)、激活层、降采样层,最后跟一个全连接层,输出为10个神经元表示有十类,分别是0,1,2,3……9

在各层网络中数据的规模变化如下:

初始情况:1*28*28             (表示只有一个颜色通道,一张图片像素大小是28*28)

第一层卷积之后:16*28*28  (使用了16种卷积核,步长为1,两边各扩充1格,大小不变28*28)

第一层max pooling之后: 16*14*14 (使用2*2的大小进行降采样,图的大小迅速缩小一半)

第二层卷积之后:32*14*14

第二层max pooling之后:32*7*7

全连接层:10  (共有十个类别)


扫描二维码关注公众号,回复: 196301 查看本文章

代码展示:

import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt

torch.manual_seed(1)   #结果可复现

#设置超参数
EPOCH = 5
BATCH_SIZE= 50
LR = 0.01
DOWNLOAD_MNIST = True #是否下载数据

train_data = torchvision.datasets.MNIST(
    root = './mnist/', #保存的位置
    train = True,   #表示是训练数据
    transform=torchvision.transforms.ToTensor(),
    download = DOWNLOAD_MNIST,
)

test_data = torchvision.datasets.MNIST(root='./mnist/',train=False)

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

test_x = Variable(torch.unsqueeze(test_data.test_data,dim=1),volatile=True).type(torch.FloatTensor)[:2000]/255
test_y = test_data.test_labels[:2000]

class CNN(nn.Module):
    def __init__(self):
        super(CNN,self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels=1,    #高度是1,就一个通道
                out_channels=16,  #卷积核数量
                kernel_size=5,    #卷积核大小
                stride=1,         #设置步长为1
                padding=2,        #边缘扩充两格
            ),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(16,32,5,1,2),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.out = nn.Linear(32*7*7,10)

    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0),-1)  #展平多维的卷积图
        output = self.out(x)
        return output

cnn = CNN()
print(cnn)

optimizer = torch.optim.Adam(cnn.parameters(),lr=LR)
loss_func = nn.CrossEntropyLoss()

for epoch in range(EPOCH):
    for step,(x,y) in enumerate(train_loader):
        b_x = Variable(x)
        b_y = Variable(y)

        output = cnn(b_x)
        loss = loss_func(output,b_y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    test_output=cnn(test_x)
    pred_y = torch.max(test_output,1)[1].data.squeeze()
    accuracy = sum(pred_y==test_y) / float(test_y.size(0))
    print('Epoch: ',epoch, '| train loss: %.4f' %loss.data[0],'| test accuracy: %.2f' %accuracy)

test_output = cnn(test_x[:10])
pre_y = torch.max(test_output,1)[1].data.numpy().squeeze()
print(pre_y,'prediction number')
print(test_y[:10].numpy(),'real number')

输出CNN卷积网路的形态:


输出前2000个测试数据的准确率:


输出前10个测试数据的预测数据和真实值:


猜你喜欢

转载自blog.csdn.net/jaster_wisdom/article/details/79892550