欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PyTorch(手写数字识别)

程序员文章站 2024-01-22 11:02:10
...

先简单梳理一下理论的部分:

                            PyTorch(手写数字识别)

从上图可以看到整个手写数字网络的结构。

 

 关键技术说明:

1.卷积(卷积神经网络中,将二维的图像直接作为输入,要区别其他神经网络)

             类比经典图像处理的卷积操作,很好理解卷积的概念。

             卷积都需要一个mask(掩膜),卷积的结果会产生一个特征图;

             每个mask.都可以产生不同的特征图(如边缘+纹理)

为什么卷积?卷积的过程中为什么用到padding

              全连接采用的非常大的权重参数,卷积速度快。 

              因为mask在滑动的过程中,中间像素参与计算的次数多,忽略了边缘像素。

2.池化(类似下采样)

下面就是实战看pytorch代码:  

#coding=utf-8
import os
import torch
from torch import nn,optim
import torch.nn.functional as F
#from torch.autograd import Variable
from torchvision import datasets, transforms

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

trainset = datasets.MNIST('data', train=True, download=True, transform=transform)
testset = datasets.MNIST('data', train=False, download=True, transform=transform)


class LeNet(nn.Module):
    # 定义Net的初始化函数,本函数定义了神经网络的基本结构
    def __init__(self):
        # 继承父类的初始化方法,即先运行nn.Module的初始化函数
        super(LeNet,self).__init__()
        # C1卷积层:输入1张灰度图片,输出6张特征图,卷积核5x5
        self.c1 = nn.Conv2d(1,6,(5,5))
        # C3卷积层:输入6张特征图,输出16张特征图,卷积核5x5
        self.c3 = nn.Conv2d(6,16,5)
        # 全连接层S4->C5:从S4到C5是全连接,S4层中16*4*4个节点全连接到C5层的120个节点上
        self.fc1 = nn.Linear(16*4*4,120)
        # 全连接层C5->F6:C5层的120个节点全连接到F6的84个节点上
        self.fc2 = nn.Linear(120,84)
        # 全连接层F6->OUTPUT:F6层的84个节点全连接到OUTPUT层的10个节点上,10个节点的输出代表着0到9的不同分值。
        self.fc3 = nn.Linear(84,10)

    # 定义向前传播函数
    def forward(self,x):
        # 输入的灰度图片x经过c1的卷积之后得到6张特征图,然后使用relu函数,增强网络的非线性拟合能力,接着使用2x2窗口的最大池化,然后更新到x
        x = F.max_pool2d(F.relu(self.c1(x)),2)
        # 输入x经过c3的卷积之后由原来的6张特征图变成16张特征图,经过relu函数,并使用最大池化后将结果更新到x
        x = F.max_pool2d(F.relu(self.c3(x)),2)
        # 使用view函数将张量x(S4)变形成一维向量形式,总特征数不变,为全连接层做准备
        x = x.view(-1,self.num_flat_features(x))
        # 输入S4经过全连接层fc1,再经过relu,更新到x
        x = F.relu(self.fc1(x))
        # 输入C5经过全连接层fc2,再经过relu,更新到x
        x = F.relu(self.fc2(x))
        # 输入F6经过全连接层fc3,更新到x
        x = self.fc3(x)
        return x

    # 计算张量x的总特征量
    def num_flat_features(self,x):
        # 由于默认批量输入,第零维度的batch剔除
        size = x.size()[1:]
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

CUDA = torch.cuda.is_available()
if CUDA:
    lenet = LeNet().cuda()
else:
    lenet = LeNet()

criterion=nn.CrossEntropyLoss()
optimizer = optim.SGD(lenet.parameters(),lr=0.001,momentum=0.9)

trainloader = torch.utils.data.DataLoader(trainset,batch_size=4, shuffle=True, num_workers=2)
testloader = torch.utils.data.DataLoader(testset,batch_size=4, shuffle=False, num_workers=2)

def train(model,criterion,optimizer,epochs=1):
    for epoch in range(epochs):
        running_loss = 0.0
        for i, data in enumerate(trainloader,0):
            inputs,labels = data
            if CUDA:
                inputs,labels = inputs.cuda(),labels.cuda()
            optimizer.zero_grad()
            outputs = model(inputs)
            
            loss = criterion(outputs,labels)
            loss.backward()
            optimizer.step()
    
            running_loss += loss.item()  
            
            if i%1000==999:
                print('[Epoch:%d, Batch:%5d] Loss: %.3f' % (epoch+1, i+1, running_loss / 1000))
                running_loss = 0.0

    print('Finished Training')

def test(testloader,model):
    correct = 0
    total = 0
    for data in testloader:
        images, labels = data
        if CUDA:
            images = images.cuda()
            labels = labels.cuda()
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1) 
        total += labels.size(0)
        correct += (predicted == labels).sum()
    print('Accuracy on the test set: %d %%' % (100 * correct / total))

def load_param(model,path):
    if os.path.exists(path):
        model.load_state_dict(torch.load(path))

def save_param(model,path):
    torch.save(model.state_dict(),path)

load_param(lenet,'model.pkl')

train(lenet,criterion,optimizer,epochs=2)

save_param(lenet,'model.pkl')

test(testloader,lenet)

 

 

最后看一下结果:

 

             PyTorch(手写数字识别)

 

 

 

 

上一篇: 秒杀系统:商品列表

下一篇: