PyTorch初探MNIST数据集

1,131 阅读4分钟

前言

本文主要描述了如何使用现在热度和关注度比较高的Pytorch(深度学习框架)构建一个简单的卷积神经网络,并对MNIST数据集进行了训练和测试。MNIST数据集是一个28*28的手写数字图片集合,使用测试集来验证训练出的模型对手写数字的识别准确率。

PyTorch资料

PyTorch的官方文档链接:PyTorch documentation,在这里不仅有 API的说明还有一些经典的实例可供参考。

PyTorch官网论坛:vision,里面会有很大资料分享和一些热门问题的解答。

PyTorch搭建神经网络实践

在一开始导入需要导入PyTorch的两个核心库文件torch和torchvision,这两个库基本包含了PyTorch会用到的许多方法和函数

import torchvision
import torch
from torchvision import datasets, transforms

其中值得一提的是torchvision的datasets可以很方便的自动下载数据集,这里使用的是MNIST数据集。另外的COCO,ImageNet,CIFCAR等数据集也可以很方的下载并使用,导入命令也非常简单

data_train = datasets.MNIST(root = "./data/",
                            transform=transform,
                            train = True,
                            download = True)

data_test = datasets.MNIST(root="./data/",
                           transform = transform,
                           train = False)

root指定了数据集存放的路径,transform指定导入数据集时需要进行何种变换操作,train设置为True说明导入的是训练集合,否则为测试集合。

transform里面还有很多好的方法,可以用在图片资源较少的数据集做Data Argumentation操作,这里只是做了个简单的Tensor格式转换和Batch Normalize

transform = transforms.Compose([transforms.ToTensor(),
                               transforms.Normalize(mean=[0.5,0.5,0.5],std=[0.5,0.5,0.5])])

数据下载完成后还需要做数据装载操作

data_loader_train = torch.utils.data.DataLoader(dataset=data_train,
                                                batch_size = 64,
                                                shuffle = True)

data_loader_test = torch.utils.data.DataLoader(dataset=data_test,
                                               batch_size = 64,
                                               shuffle = True)

batch_size设置了每批装载的数据图片为64个,shuffle设置为True在装载过程中为随机乱序

下图为一个batch数据集(64张图片)的显示,可以看出来都为28*28的1维图片

MNIST数据集图片预览

完成数据装载后就可以构建核心程序了,这里构建的是一个包含了卷积层和全连接层的神经网络,其中卷积层使用torch.nn.Conv2d来构建,激活层使用torch.nn.ReLU来构建,池化层使用torch.nn.MaxPool2d来构建,全连接层使用torch.nn.Linear来构建

class Model(torch.nn.Module):
    
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = torch.nn.Sequential(torch.nn.Conv2d(1,64,kernel_size=3,stride=1,padding=1),
                                         torch.nn.ReLU(),
                                         torch.nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),
                                         torch.nn.ReLU(),
                                         torch.nn.MaxPool2d(stride=2,kernel_size=2))
        self.dense = torch.nn.Sequential(torch.nn.Linear(14*14*128,1024),
                                         torch.nn.ReLU(),
                                         torch.nn.Dropout(p=0.5),
                                         torch.nn.Linear(1024, 10))
    def forward(self, x):
        x = self.conv1(x)
        x = x.view(-1, 14*14*128)
        x = self.dense(x)
        return x

其中定义了torch.nn.Dropout(p=0.5)防止模型的过拟合

forward函数定义了前向传播,其实就是正常卷积路径。首先经过self.conv1(x)卷积处理,然后进行x.view(-1, 14*14*128)压缩扁平化处理,最后通过self.dense(x)全连接进行分类

之后就是对Model对象进行调用,然后定义loss计算使用交叉熵,优化计算使用Adam自动化方式,最后就可以开始训练了

model = Model()
cost = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters())

在训练前可以查看神经网络架构了,print输出显示如下

Model (
  (conv1): Sequential (
    (0): Conv2d(1, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU ()
    (2): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU ()
    (4): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))
  )
  (dense): Sequential (
    (0): Linear (25088 -> 1024)
    (1): ReLU ()
    (2): Dropout (p = 0.5)
    (3): Linear (1024 -> 10)
  )
)

定义训练次数为5次,开始跑神经网络,训练完成后输入测试集合得到的结果如下

Epoch 0/5
----------
Loss is:0.0003, Train Accuracy is:99.4167%, Test Accuracy is:98.6600
Epoch 1/5
----------
Loss is:0.0002, Train Accuracy is:99.5967%, Test Accuracy is:98.9200
Epoch 2/5
----------
Loss is:0.0002, Train Accuracy is:99.6667%, Test Accuracy is:98.7700
Epoch 3/5
----------
Loss is:0.0002, Train Accuracy is:99.7133%, Test Accuracy is:98.9600
Epoch 4/5
----------
Loss is:0.0001, Train Accuracy is:99.7317%, Test Accuracy is:98.7300

从结果上看还不错,训练准确率最高达到了99.73%,测试最高准确率为98.96%。结果有轻微的过拟合迹象,如果使用更加健壮的卷积模型测试集会取得更加好的结果。

随机对几张测试集的图片进行预测,并做可视化展示

Predict Label is: [3, 4, 9, 3]
Real Label is: [3, 4, 9, 3]

训练完成后还可以保存训练得到的参数,方便下次导入后可供直接使用

torch.save(model.state_dict(), "model_parameter.pkl")

完整代码链接:JaimeTang/Pytorch-and-mnist(model_parameter.pkl文件较大未做上传)