Pytorch实现MNIST图像数据集进行多分类问题

使用Pytorch读取图像时,这与用PIL或者OpenCV读取图像有所区别;在使用PIL和OpenCV读取图像数据时,该图像常常是WHC的形式(宽度高度通道),但是在Pytorch读取图像的时候,需要先转换成图像张量,转成CWH的形式(通道宽度高度);
同时先将图像标准化成0-1分布,这样当传入神经网络时效果会比较好。

多分类问题:
在多分类问题中,不像二分类问题那样只有0,1;该分类有多个输出,为此可以用Softmax函数保证每个类别的概率都>=0,且所有类别之和等于1;为此在Pytorch当中采用CrossEntropyLoss()函数将Softmax和NLLloss进行整合。

图像数据集进行分类步骤:
(1)读取MNIST数据集,并构造训练集和测试集,其中在训练集当中数据需要进行Shuffle,同时设置batch_size为64
(2)创建模型,这里网络中主要有Linear Layer、ReLU Layer以及对最后一个Linear Layer的输出进行Softmax;
(3)构造损失函数和优化器
(4)进行训练、并对数据进行测试,在验证准确类别

ps:
输入层中我们需要将图片进行转化,图片集是(N,1,28,28)4阶张量,其中N代表图片集中有N个样本,这里我们需要将12828这3阶张量转变成1阶向量;就是将图片中每一行拼成一串。

代码实现:

# -*- coding: utf-8 -*-
# @Time : 2022/1/27 14:59
# @Author : CH339
# @FileName: Test1_27_1.py
# @Software: PyCharm
# @Blog :https://blog.csdn.net/weixin_56068397/article/

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim

batch_size = 64
# 将图片转换成pytorch当中的张量
transform = transforms.Compose([
    # 转变成张量
    transforms.ToTensor(),
    # 进行标准化,转换成0-1分布
    transforms.Normalize((0.1307,),(0.3081,))
])
# 构造训练集
train_dataset = datasets.MNIST(root='../dataset/mnist/',train=True,download=True,transform=transform)
train_loader = DataLoader(train_dataset,shuffle=True,batch_size=batch_size)

# 构造测试机
test_dataset = datasets.MNIST(root='../dataset/mnist/',train=False,download=True,transform=transform)
test_loader = DataLoader(test_dataset,shuffle=False,batch_size=batch_size)

# 编写模型类
# 首先需要将c*w*H转换成1阶向量
class LinearNet(torch.nn.Module):
    def __init__(self):
        super(LinearNet, self).__init__()
        # 构造LinearLayer
        self.x1 = torch.nn.Linear(784,512)
        self.x2 = torch.nn.Linear(512,256)
        self.x3 = torch.nn.Linear(256,128)
        self.x4 = torch.nn.Linear(128,64)
        self.x5 = torch.nn.Linear(64,10)

    # 重写前馈函数
    def forward(self,x):
        # 将三阶张量转换成1阶向量
        x = x.view(-1,784)
        # 使用激活函数进行分线性转化
        x = F.relu(self.x1(x))
        x = F.relu(self.x2(x))
        x = F.relu(self.x3(x))
        x = F.relu(self.x4(x))
        # 最后一层LinearLayer输出后不需要激活函数,直接输入到softmax进行转换
        return self.x5(x)
# 创建模型对象
model = LinearNet()

# 创建损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
# 定义训练函数
def train(epoch):
    sum_loss = 0
    for batch_index,data in enumerate(train_loader,0):
        # 特征值和目标值
        inputs,target = data
        # 梯度清零
        optimizer.zero_grad()
        outputs = model(inputs)
        # 计算损失
        loss = criterion(outputs,target)
        loss.backward()
        # 权重更新
        optimizer.step()
        # 将损失累加
        sum_loss += loss.item()
        if batch_index%100 == 99:
            # 每100次进行输出
            print('[%d,%5d]loss:%.3f'%(epoch+1,batch_index+1,sum_loss/100))
            # 重新将损失设为0
            sum_loss = 0

# 定义测试函数
def test():
    # 准确分类的数量
    sum_correct = 0
    total = 0
    # 在测试的时候只需要计算即可,不需要进行反向传播
    with torch.no_grad():
        for data in test_loader:
            images,label = data
            # 获得估计结果
            output = model(images)
            _,predict = torch.max(output.data,dim=1)
            total += label.size(0)
            sum_correct += (predict==label).sum().item()
    print('准确率:%d%%'%(100*sum_correct/total))

if __name__ == "__main__":
    for epoch in range(10):
        train(epoch)
        test()

这里我们只采用10次迭代进行初步分类,也可增加迭代次数。

前两次迭代:
在这里插入图片描述
迭代到第10轮:
在这里插入图片描述

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值