Pytorch实现手写数字识别【基于卷积神经网络】

说明

本案例在上一次案例的基础之上对神经网络模型进行了修改,在全连接层之前加入了特征提取层(卷积层+池化层),其他基本保持一致。

卷积神经网络模型设计如下:
在这里插入图片描述

1、导入各类需要的包

import torch
import numpy as np

#导入 pytorch 内置的mnist数据集
from torchvision.datasets import mnist

#导入对图像的预处理模块
import torchvision.transforms as transforms

#导入dataset的分批读取包
from torch.utils.data import DataLoader

#导入神经网络包nn(可用来定义和运行神经网络)
from torch import nn

#functional这个包中包含了神经网络中使用的一些常用函数,这些函数的特点是:不具有可学习的参数(如ReLU,pool,DropOut等)
import torch.nn.functional as F

#optim中实现了大多数的优化方法来更新网络权重和参数,如SGD、Adam
import torch.optim as optim

#导入可视化绘图库
import matplotlib.pyplot as plt

2、定义超参数

#2定义代码中用到的各个超参数

train_batch_size = 64  #指定DataLoader在训练集中每批加载的样本数量
test_batch_size = 128  #指定DataLoader在测试集中每批加载的样本数量
num_epoches = 15 # 模型训练轮数
lr = 0.01  #设置SGD中的初始学习率
momentum = 0.5 #设置SGD中的冲量

3、预处理数据

#3对数据进行预处理
# Compose方法即是将两个操作合并一起
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.1307], [0.3081])])

4、加载数据集

#4下载和分批加载数据集

#将训练和测试数据集下载到同目录下的data文件夹下
train_dataset = mnist.MNIST('.\data', train=True, transform=transform, download=False)
test_dataset = mnist.MNIST('.\data', train=False, transform=transform, download=False)

#dataloader是一个可迭代对象,可以使用迭代器一样使用。
#其中shuffle参数为是否打乱原有数据顺序
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)

5、定义神经网络模型并实例化

在定义神经网络模型中需要注意的是,我们需要确定全连接层输入层的张量大小,也就是需要计算出最后一层特征提取层输出的张量大小,此计算方式有两种,一个是我们根据通道数、卷积核大小、池化核大小来一层一层手动推导出输出的张量大小,另外一个就是我们先不定义全连接层,实例化模型后让程序自己输出最后一层的张量大小

#5定义一个神经网络模型

class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()  
        self.conv1 = nn.Conv2d(1,10,kernel_size=5)     #灰度图像单通道
        self.conv2 = nn.Conv2d(10,20,kernel_size=5)
        self.pooling = nn.MaxPool2d(2)     #kernel_size=2的最大池化
        self.fc1 = nn.Linear(20*4*4,70)
        self.fc2 = nn.Linear(70,10)
    def forward(self,x):
        batch_size = x.size(0)
        x = self.pooling(F.relu(self.conv1(x)))
        x = self.pooling(F.relu(self.conv2(x)))
        x = x.view(batch_size,-1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x
        
#实例化网络模型

#检测是否有可用的GPU,否则使用cpu
device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') 

model=Net()
model.to(device)

#定义模型训练中用到的损失函数和优化器
criterion = nn.CrossEntropyLoss() #交叉熵损失函数
optimizer = optim.SGD(model.parameters(),lr=lr,momentum=momentum)
# parameters()将model中可优化的参数传入到SGD中

6、模型训练

def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        inputs, target = data
        inputs, target  = inputs.to(device), target.to(device)
        optimizer.zero_grad() # 清除上一轮的梯度
        
        outputs = model(inputs)  #前向传播
        loss = criterion(outputs, target)
        loss.backward()  # 反向传播
        optimizer.step() # 优化参数
        
        running_loss += loss.item()
        if batch_idx % 300 == 299:
            print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0

7、模型测试

def test():
    correct = 0
    total = 0
    model.eval()  # 测试不需要反向传播
    for data in test_loader:
        inputs, target = data
        inputs, target  = inputs.to(device), target.to(device)
        outputs = model(inputs)
        _, predicted = torch.max(outputs.data, dim = 1) # predicted为最大概率的下标,_为最大的概率值
        total += target.size(0) #将每一批样本数量相加
        correct += (predicted == target).sum().item()
    print('Accuracy of the network on the 10000 test images: %.3f %%' % ( 100 * correct / total))
        

进行多轮

for epoch in range(num_epoches):
    train(epoch)
    test()

训练及测试结果如下:

由下图训练结果与上一篇基于全连接神经网络的模型相比,可见先使用卷积和最大池化对图像进行特征提取,再使用全连接神经网络进行分类,可以很大程度上提升分类器性能。
在这里插入图片描述

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面是一个基于PyTorch字符识别的卷神经网络的代码示例。 首先,我们需要导入需要的库和模块: ```python import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchvision import datasets, transforms ``` 然后,我们需要定义一个卷神经网络模型: ```python class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1) self.dropout1 = nn.Dropout2d(0.25) self.dropout2 = nn.Dropout2d(0.5) self.fc1 = nn.Linear(64 * 7 * 7, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = F.relu(self.conv1(x)) x = F.max_pool2d(x, 2) x = F.relu(self.conv2(x)) x = F.max_pool2d(x, 2) x = self.dropout1(x) x = torch.flatten(x, 1) x = F.relu(self.fc1(x)) x = self.dropout2(x) x = self.fc2(x) return F.log_softmax(x, dim=1) ``` 接下来,我们需要定义一些超参数和数据预处理: ```python batch_size = 64 test_batch_size = 1000 epochs = 10 lr = 0.01 momentum = 0.5 n_classes = 10 input_size = 28 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) ``` 然后,我们需要加载数据集: ```python train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform) test_dataset = datasets.MNIST('./data', train=False, transform=transform) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=test_batch_size, shuffle=True) ``` 接下来,我们需要定义优化器和损失函数: ```python model = Net() optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum) criterion = nn.CrossEntropyLoss() ``` 最后,我们可以开始训练模型: ```python for epoch in range(1, epochs + 1): model.train() for batch_idx, (data, target) in enumerate(train_loader): optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() optimizer.step() if batch_idx % 100 == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item())) model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: output = model(data) test_loss += criterion(output, target).item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format( test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset))) ``` 这个模型将会训练10个epochs,并输出训练和测试集的准确率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值