深度学习的hello world--mnist手写数字识别代码实现

本文详细介绍了一种基于PyTorch框架的手写数字识别模型构建过程。从数据预处理到模型训练,再到最终的模型测试,全面展示了如何利用深度学习技术解决实际问题。

第一步:下载数据源并进行预处理

import torch
import torchvision
import torchvision.transforms as transforms


# # 定义预处理函数,这些预处理一次放在compose函数中
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5], [0.5])])
# 导入mnist数据源
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=train_batch_size, shuffle=True)
# 将数据源转化为可迭代的 训练集和测试集
testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=test_batch_size, shuffle=False)

 第二步:定义超参数

# 训练集分组大小
train_batch_size = 64
# 测试集分组大小
test_batch_size = 8
# 学习率
learning_rate = 0.01
# 训练次数
num_epoches = 10
# SGD算法的动量参数
momentum = 0.5

 第三步:定义神经网络结构

我们先架构好神经网络的结构:卷积层和池化层如下,全连接层略

整个网络结构为:输入→卷积层1→池化层1→卷积层2→池化层2→全连接层1→全连连接层2→全连接层3→输出

注:分类器如softmax等一般不写在网络结构中

代码:

import torch.nn as nn
import torch.nn.functional as F


# 神经网络的类
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(16 * 4 * 4, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
        
    def forward(self, x):
        # 卷积层1
        x = F.relu(self.conv1(x))
        # 池化层1
        x = self.pool1(x)
        # 卷积层2
        x = F.relu(self.conv2(x))
        # 池化层2
        x = self.pool2(x)
        # 将输出展平
        x = x.view(-1, 16 * 4 * 4)
        # 全连接层1
        x = F.relu(self.fc1(x))
        # 全连接层2
        x = F.relu(self.fc2(x))
        # 全连接层3
        x = F.relu(self.fc3(x))
        return x
        
    
# 定义神经网络
net = Net()

注:池化层理论上是可以不用写入神经网络结构的(因为没有参数),在这里为了方便理解,我把池化层加到了神经网络结构中(其实就是一个函数)

第四步:定义损失函数和优化器

import torch.optim as optim


# 定义损失函数(分类问题一般使用交叉熵损失函数
criterion = nn.CrossEntropyLoss()
# 定义优化器(使用随机梯度下降算法,并加入动量)
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=momentum)

第五步:开始训练网络并输出每一次训练的损失值

# ================================train========================================
for epoch in range(num_epoches):
    running_loss = 0.0
    num = 0
    for i, data in enumerate(trainloader, 0):
        # 获取输入和输出
        inputs, labels = data
    
        # 参数梯度清零
        optimizer.zero_grad()
        
        # 向前传播
        outputs = net(inputs)
        # 反向传播,计算梯度
        loss = criterion(outputs, labels)
        loss.backward()
        # 执行优化器,使用SGD算法更新参数
        optimizer.step()
        
        running_loss += loss.item()
        num += 1
        
    # 输出每一回合训练的平均损失值    
    print('epoch:%d loss: %.3f' % (epoch + 1, running_loss / num))
            
print('Finished Training')

对应输出:

 

第六步:测试模型

可视化的测试:(只用测试集的一组数据)

import matplotlib.pyplot as plt
import numpy as np


# ================================test=========================================
# 将模型改为测试模式
net.eval()

# 定义一个显示图像的函数
def imgshow(img):
    npimg = img.numpy()
    # transpose对高维矩阵进行轴对换
    plt.imshow(np.transpose(npimg, (1, 2, 0))) 
    plt.show()  
    
    
# 从测试集中获得一组数据
dataiter = iter(testloader)
images, labels = dataiter.next()

# torchvision.utils.make_grid函数将获的的数据合并为一张图像
imgshow(torchvision.utils.make_grid(images))
# 输出相应的标签
print('target:', ' '.join('%d' % labels[j] for j in range(8)))

# 使用训练的模型进行预测
outputs = net(images)
_, predicted = torch.max(outputs, 1)
# 输出预测结果
print('Predict:', ' '.join('%d' % predicted[j] for j in range(8)))

对应输出:

用测试集全部数据进行测试,并输出每组测试的精确率

# ================================test=========================================
for i, data in enumerate(testloader, 0):
    inputs, labels = data
    outputs = net(inputs)
    _, predicted = outputs.max(1)
    acc_num = (labels == predicted).sum().item()
    acc = acc_num / labels.size(0)
    if i % 64 == 0:
        print('acc:%.3f' % acc)
    

对应输出: 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值