运用多层感知机模型实现手写数字识别(MNIST)

本文介绍了如何作为深度学习新手使用Pytorch框架复现MNIST手写数字识别,包括数据预处理、模型构建(四层全连接神经网络)、训练过程(使用ReLU激活和MSE损失函数)以及最终达到的97%左右的预测精度。
摘要由CSDN通过智能技术生成

1.介绍:

作为深度学习的小白,为了熟悉Pytorch框架,选择了复现手写数字识别的代码。应用的数据集是简单且常用的MNIST手写数字集,应用的模型是最简单的多层感知机模型,最终训练的模型达到了accuracy=97%的预测效果。

2.思路:

 MNIST数据集中已经划分好了训练集和测试集,我们实现分类的思路如下:

(1)分别对数据集中的图片和标签进行处理

图片像素为28*28、通道数为1,需要先用totensor()函数将图片转换为张量形式,接着对其进行标准化(std=0.5,mean=0.5),再应用Flatten()函数打平为1*784张量。接着应用四层全连接神经网络将其化为1*10向量。

标签需要用独热编码处理为1*10向量,以保持与模型输出结果相同的形状以便于损失函数的计算。

(2)关于多层感知机模型:

四层节点数分别设置为784、256、128、10,其中输入层和输出层的节点必须是固定的。

第二、三层输出应用激活函数 ReLu:max(0,x),最后一层输出应用softmax()函数输出分类概率。

(3)损失函数:

应用均方差(MSE)函数作为损失函数。应用随机梯度下降进行参数更新。

3.完整代码及详细注释如下:

import torch
import torch.nn as nn
import torch.optim as optim  # 引入随机梯度优化器
import torch.nn.functional as F  # one_hot_encoding
from torchvision import datasets, transforms

# 构建数据预处理组合---transforms:先化图象为张量,再对张量以(mean,std)=(0.5,0.5)标准化
transforms = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,), )])
# 加载MNIST数据集并对其进行预处理
train_dataset = datasets.MNIST(r"D:\HuaweiMoveData\Users\朱明意\Desktop\MNIST_data", train=True, download=True,
                               transform=transforms)
test_dataset = datasets.MNIST(r"D:\HuaweiMoveData\Users\朱明意\Desktop\MNIST_data", train=False, download=True,
                              transform=transforms)
# 创建数据加载器
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)  # 每批次训练样本数量设定为64
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)  # 每批次测试样本数量设定为64


# 定义多层感知机模型类
class MLP(nn.Module):  # 继承nn.Model基类
    def __init__(self):
        super(MLP, self).__init__()
        self.flatten = nn.Flatten()  # 打平数据
        self.fc1 = nn.Linear(784, 256)  # 神经网络隐藏层节点数为256
        self.relu = nn.ReLU()  # relu()激活函数
        self.fc2 = nn.Linear(256, 128)  # 神经网络输出层节点数为128
        self.fc3 = nn.Linear(128, 10)   # 神经网络输出层节点数为10

    def forward(self, x):  # 正向传播计算
        x = self.flatten(x)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        x = self.relu(x)
        x = self.fc3(x)
        x = torch.softmax(x, dim=1)  # 在最后一层使用softmax()函数
        return x


# 定义训练函数(用于模型参数更新)
def train(model, train_loader, optimizer, criterion, device):
    model.train()  # 将模型设置为训练模式(可有可无,最好有)
    for batch_idx, (data, target) in enumerate(train_loader):  # batch_idx为当前批次索引,从0开始递增;
        data, target = data.to(device), target.to(device)  # (data,target)为当前批次数据及对应目标值(label)
        optimizer.zero_grad()  # 清空优化器的累计梯度
        output = model(data)  # 进行正向传播计算:输入data,得到output
        target_one_hot = F.one_hot(target, num_classes=10).float()  # 运用独热编码函数,总类别数为10
        loss = criterion(output, target_one_hot)  # 根据输入的损失函数参数计算损失
        loss.backward()  # 反向传播
        optimizer.step()  # 根据反向传播计算的梯度更新优化模型参数()


# 定义测试函数(用于检验模型效果)
def test(model, test_loader, device):
    model.eval()  # 将模型设置为评估模式
    correct=0  # 正确分类样本数量
    with torch.no_grad():
        for data, target in test_loader:  # 遍历测试数据集
            data, target = data.to(device), target.to(device)  # 将数据和目标移动到指定的设备(cpu)
            output = model(data)  # 使用模型预测得到输出
            _, predicted = torch.max(output.data, 1)  # 获得模型最大预测概率(softmax函数)的索引值,存储到predicted
            correct += (predicted == target).sum().item()  # 统计预测正确的样本数量

            accuracy = 100. * correct / len(test_loader.dataset)
        print('Test set: Accuracy: {}/{} ({:.2f}%)'.format(correct, len(test_loader.dataset), accuracy))

model = MLP()  # 创建MLP实例
optimizer = optim.Adam(model.parameters(), lr=0.001)  # 创建优化器,其中model.parameters()源自继承的基类
criterion = nn.MSELoss()  # 创建损失函数

for epoch in range(10):
    # 训练
    train(model, train_loader, optimizer, criterion, torch.device('cpu'))

    # 测试
    test(model, test_loader, torch.device('cpu'))

    # 保存模型参数状态
    torch.save(model.state_dict(), 'model.pth')  # 保存模型参数状态

4.运行结果如下:

D:\Anaconda\python.exe D:\HuaweiMoveData\Users\朱明意\Desktop\MLorDL代码实现\手写数字识别(Minst.py 
Test set: Accuracy: 9443/10000 (94.43%)
Test set: Accuracy: 9599/10000 (95.99%)
Test set: Accuracy: 9559/10000 (95.59%)
Test set: Accuracy: 9653/10000 (96.53%)
Test set: Accuracy: 9704/10000 (97.04%)
Test set: Accuracy: 9705/10000 (97.05%)
Test set: Accuracy: 9630/10000 (96.30%)
Test set: Accuracy: 9739/10000 (97.39%)
Test set: Accuracy: 9772/10000 (97.72%)
Test set: Accuracy: 9676/10000 (96.76%)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值