当前位置:   article > 正文

用PyTorch进行手写数字识别_pytorch 手写数字识别 识别数字实用

pytorch 手写数字识别 识别数字实用

数据准备

torch.utils.data.Datasets是PyTorch用来表示数据集的类,它是用PyTorch进行手写数字识别的关键。
下面是加载mnist数据集并对其可视化的代码

from torchvision import datasets
from torchvision.datasets import MNIST
from matplotlib import pyplot as plt
import numpy as np

mnist = datasets.MNIST(root='C:/Users/WSY/Desktop/用pytorch进行手写数字识别',
                       train=True,download=True)

for i, j in enumerate(np.random.randint(0,len(mnist),(10,))):
    data, label = mnist[j]
    plt.subplot(2,5,i+1)
    plt.imshow(data)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这段代码中,首先实例化了Datasets对象mnist ,datasets.MNIST能够自动下载数据集保存到本地磁盘的root位置(自己设置),参数train默认为True,用于控制加载的数据集是训练集还是测试集。for循环中,使用len(mnist)调用了__len__方法,使用mnist[j]调用了__getitem__方法(在我们自己建立数据集时,需要继承Dataset,并且覆写__len__和__getitem__两个方法)。最后两行代码绘制了MNIST手写数字数据集。
运行代码,查看数据集的部分数据可视化结果
在这里插入图片描述
在变量浏览器中可以看到有关变量的内容,其中mnist就是实例化的数据集对象,它包含6000张图像内容,在for循环过程中,data读取的是28×28的Image类型图像,label是该图像对应的标签,也就是图像上表示的数字。
在这里插入图片描述
由于数据预处理是非常重要的步骤,所以PyTorch提供了torchvision.transforms用于处理数据及数据增强。在这里我们使用了torchvision.transforms.ToTensor将PIL Image或者numpy.ndarray类型的数据转换为Tensor,并且它会将数据从【0,255】映射到【0,1】。torchvision.transforms.Normalize会将数据标准化,加速模型在训练中的收敛速率。在使用中,可利用torchvision.transforms.Compose将多个transforms组合在一起,被包含的transforms会顺序执行。
数据流程处理准备完善后开始读取用于训练的数据,torch.utils.data.DataLoader提供了迭代数据、随机抽取数据、批量化数据。
下面的代码中实例化了mnist对象,定义了transforms方法trans并将其使用到数据集的实例化过程中,用于对数据集进行处理。然后定义了函数imshow,函数体的的第一行代码将数据从标准化的数据中恢复,第二行代码将Tensor类型转换为ndarray,这样才可以用matplotlib绘制出来,绘制的结果如下图所示。函数体最后一行使用transpose函数将矩阵维度从(C,W,H)转换为(W,H,C),这样才符合正常的通道顺序。

import torchvision
from torchvision import datasets,transforms
from torchvision.datasets import MNIST
from matplotlib import pyplot as plt
import numpy as np
import torch

trans = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
    ])

mnist = datasets.MNIST(root='C:/Users/WSY/Desktop/用pytorch进行手写数字识别',
                       train=True,download=True,transform=trans)

def imshow(img):
    img = img * 0.3081 + 0.1307
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1,2,0)))

dataloader = torch.utils.data.DataLoader(mnist, batch_size=4, shuffle=True, num_workers=0)
images, labels = next(iter(dataloader))

imshow(torchvision.utils.make_grid(images))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

运行代码得到的变量情况及绘制结果如下图
在这里插入图片描述

网络模型

下面构建用于识别手写数字的神经网络模型

import torch.nn as nn

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()

        self.inputlayer = nn.Sequential(nn.Linear(28*28, 256),
                                        nn.ReLU(),
                                        nn.Dropout(0.2))
        self.hiddenlayer = nn.Sequential(nn.Linear(256, 256),
                                         nn.ReLU(),
                                         nn.Dropout(0.2))
        self.outlayer = nn.Sequential(nn.Linear(256, 10))

    def forward(self, x):
        #将输入图像拉伸为一维向量
        x = x.view(x.size(0), -1)

        x = self.inputlayer(x)
        x = self.hiddenlayer(x)
        x = self.outlayer(x)
        return x
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

通过nn.Module对象看到其网络结构,如下

In [12]: print(MLP())
MLP(
  (inputlayer): Sequential(
    (0): Linear(in_features=784, out_features=256, bias=True)
    (1): ReLU()
    (2): Dropout(p=0.2, inplace=False)
  )
  (hiddenlayer): Sequential(
    (0): Linear(in_features=256, out_features=256, bias=True)
    (1): ReLU()
    (2): Dropout(p=0.2, inplace=False)
  )
  (outlayer): Sequential(
    (0): Linear(in_features=256, out_features=10, bias=True)
  )
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

完整实现

准备好数据和模型后,就可以进行训练模型了。下面分别定义了数据处理和加载流程、模型、优化器、损失函数以及用准确率评估模型能力。训练过程持续10个epoch

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torch import optim 
from tqdm import tqdm
from torchvision import datasets,transforms
import matplotlib.pylab as plt

#数据处理和加载
trans = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
    ])
mnist_train = datasets.MNIST(root='C:/Users/WSY/Desktop/用pytorch进行手写数字识别',
                       train=True,download=True,transform=trans)
mnist_val = datasets.MNIST(root='C:/Users/WSY/Desktop/用pytorch进行手写数字识别',
                       train=False,download=True,transform=trans)

trainloader = DataLoader(mnist_train, batch_size=16, shuffle=True, num_workers=0)
valloader = DataLoader(mnist_val, batch_size=16, shuffle=True, num_workers=0)

#定义网络模型
class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()

        self.inputlayer = nn.Sequential(nn.Linear(28*28, 256),
                                        nn.ReLU(),
                                        nn.Dropout(0.2))
        self.hiddenlayer = nn.Sequential(nn.Linear(256, 256),
                                         nn.ReLU(),
                                         nn.Dropout(0.2))
        self.outlayer = nn.Sequential(nn.Linear(256, 10))

    def forward(self, x):
        #将输入图像拉伸为一维向量
        x = x.view(x.size(0), -1)

        x = self.inputlayer(x)
        x = self.hiddenlayer(x)
        x = self.outlayer(x)
        return x

model = MLP()

#优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

#损失函数
celoss = nn.CrossEntropyLoss()

#计算准确率
def accuracy(pred, target):
    pred_label = torch.argmax(pred, 1)
    correct = sum(pred_label == target).to(torch.float)

    return correct, len(pred)

acc = {'train':[], 'val':[]}
loss_all = {'train':[], 'val':[]}

for epoch in tqdm(range(10)):
    #设置为验证模式
    model.eval()
    numer_val, denumer_val, loss_tr = 0., 0., 0.
    with torch.no_grad():
        for data, target in valloader:
            output = model(data)
            loss = celoss(output, target)
            loss_tr += loss.data

            num, denum = accuracy(output, target)
            numer_val += num
            denumer_val += denum
    
    #设置为训练模式
    model.train()
    numer_tr, denumer_tr, loss_val = 0., 0., 0.
    for data, target in trainloader:
        optimizer.zero_grad()
        output = model(data)
        loss = celoss(output, target)
        loss_val += loss.data
        loss.backward()
        optimizer.step()
        num, denum = accuracy(output, target)
        numer_tr += num
        denumer_tr += denum

    loss_all['train'].append(loss_tr/len(trainloader))
    loss_all['val'].append(loss_val/len(valloader))
    acc['train'].append(numer_tr/denumer_tr)
    acc['val'].append(numer_val/denumer_val)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

运行完成,如下
在这里插入图片描述
设计到的变量情况如下
在这里插入图片描述
在这里插入图片描述
查看模型训练迭代过程的损失图像

plt.plot(loss_all['train'])
plt.plot(loss_all['val'])
  • 1
  • 2

在这里插入图片描述
查看训练迭代过程的准确率图

plt.plot(acc['train'])
plt.plot(acc['val'])
  • 1
  • 2

在这里插入图片描述
O V E R !

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号