Pytorch框架下MNIST手写数字分类简单实现

Pytorch框架下MNIST手写数字分类简单实现

一.环境配置

配置好Pytroch框架,然后引入库

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torch.utils.data as Data

二.数据集准备与数据预处理

在torchvision库中已经为我们准备大量的数据集,MNIST手写字体数据集也在其中。

首先导入所需要的库

from torchvision import datasets, transforms  
##datasets包含与数据相关的模块,transforms包含数据预处理模块

对数据集做一些简单的预处理,pytorch中的数据都是以张量形式参与运算,所以读入数据必须转化为张量,而transforms.Compose()函数可以将多个transform组合使用

##数据处理方式
transformation = transforms.Compose([
       transforms.ToTensor(),              ##将数据集像素转换至[0,1]之间,并转化为张量
       transforms.RandomHorizontalFlip(),  ##随机翻转
       transforms.Normalize((0.5,), (0.5,))##数据标准化
])

引入数据集

##引入训练数据集
train_dataset = datasets.MNIST(
                                'data/',     ##数据的路径,放在当前data文件夹下
                                train=True,  ##引入训练数据集
                                transform=transformation, ##数据处理方式
                                download=True  ##是否下载数据集
)

##引入测试数据集
test_dataset = datasets.MNIST(
                               'data/',
                               train=False,
                               transform=transformation,
                               download=True
)

##定义数据加载器
train_loader = Data.DataLoader(
    		train_dataset,         ##使用的训练数据集
            batch_size=64,         ##批处理样本大小
            shuffle=True           ##对训练数据集做乱序处理
)

test_loader = Data.DataLoader(
    		test_dataset,
            batch_size=64,
            shuffle=False          ##测试数据集就没有必要乱序处理
)

三.定义网络结构.

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(   
            nn.Conv2d(
                in_channels=1,             ## 输入大小 (1, 28, 28)
                out_channels=6,           
                kernel_size=5,              ## 卷积核大小
                stride=1,                   ## 步长
                padding=2,               
            ),                               ## 输出的特征图为 (6, 28, 28)
            nn.ReLU(),                     
            nn.MaxPool2d(kernel_size=2),    ## 进行池化操作(2x2 区域), 输出结果为: (6, 14, 14)
        )
        self.conv2 = nn.Sequential(         ## 下一次的输入 (6, 14, 14)
            nn.Conv2d(
                in_channels=6,            
                out_channels=32,           
                kernel_size=5,             
                stride=1,                
                padding=2, 
            ),                              ## 输出 (32, 14, 14)
            nn.ReLU(),                   
            nn.MaxPool2d(2),                ## 输出 (32, 7, 7)
        )
        self.out = nn.Linear(32 * 7 * 7, 10)## 全连接层,

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)          ##将卷积图拉伸得到向量
        output = self.out(x)
        return output

四.定义优化器和损失函数。

net = CNN() 
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  ##将模型迁移到GPU
net.to(device)
criterion = nn.CrossEntropyLoss()       ##交叉熵做为Loss
optimizer = optim.Adam(net.parameters(), lr=0.01)  ##Adam作为优化器

五.编写正确率函数

参考https://blog.csdn.net/qq_40210586/article/details/103874000?utm_source=app&app_version=5.5.0&code=app_1562916241&uLinkId=usr1mkqgl919blen

def accuracy(predict, label):
    _,pred_y = torch.max(predict, 1)   
    acc = (pred_y == label).type(torch.float32).mean().item()
    return acc

六.训练网络并输出

#开始训练循环
for epoch in range(3):                                            ##训练次数epoch += 1
    epoch += 1
    for batch_idx, (data, target) in enumerate(train_loader):  
        net.train()  
        data = data.to(device)
        target = target.to(device)
        output = net(data) 
        train_right = accuracy(output,target)
        loss = criterion(output, target) 
        optimizer.zero_grad() 
        loss.backward() 
        optimizer.step() 
        
        if batch_idx % 100 == 0:
             net.eval()                                            ##验证模型
         
             for (data, target) in test_loader:
                    data = data.to(device)
                    target = target.to(device)
                    output = net(data) 
                    test_right = accuracy(output, target) 
            
             print('当前epoch: {} [{}/{} ({:.0f}%)]\t损失: {:.6f}\t训练集准确率: {:.2f}%\t测试集正确率: {:.2f}%'.format(
                epoch, batch_idx * 64, len(train_loader.dataset),
                100. * batch_idx / len(train_loader), 
                loss.item(), 
                100. * train_right, 
                100. * test_right  ))

        

附原代码

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torch.utils.data as Data

from torchvision import datasets, transforms 
##datasets包含与数据相关的模块,transforms包含数据预处理模块

transformation = transforms.Compose([
       transforms.ToTensor(),              ##将数据集像素转换至[0,1]之间,并转化为张量
       transforms.RandomHorizontalFlip(),  ##随机反转
       transforms.Normalize((0.5,), (0.5,))##数据标准化
])

##引入训练数据集
train_dataset = datasets.MNIST(
                                'data/',     ##数据的路径,放在当前data文件夹下
                                train=True,  ##引入训练数据集
                                transform=transformation, ##数据处理方式
                                download=True  ##是否下载数据集
)

##引入测试数据集
test_dataset = datasets.MNIST(
                               'data/',
                               train=False,
                               transform=transformation,
                               download=True
)

##定义数据加载器
train_loader = Data.DataLoader(
    		train_dataset,         ##使用的训练数据集
            batch_size=64,         ##批处理样本大小
            shuffle=True           ##对训练数据集做乱序处理
)

test_loader = Data.DataLoader(
    		test_dataset,
            batch_size=64,
            shuffle=False          ##测试数据集就没有必要乱序处理
)

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(        ## 输入大小 (1, 28, 28)
            nn.Conv2d(
                in_channels=1,            
                out_channels=6,           
                kernel_size=5,              ## 卷积核大小
                stride=1,                   ## 步长
                padding=2,               
            ),                               ## 输出的特征图为 (6, 28, 28)
            nn.ReLU(),                     
            nn.MaxPool2d(kernel_size=2),    ## 进行池化操作(2x2 区域), 输出结果为: (6, 14, 14)
        )
        self.conv2 = nn.Sequential(         ## 下一次的输入 (6, 14, 14)
            nn.Conv2d(
                in_channels=6,            
                out_channels=32,           
                kernel_size=5,             
                stride=1,                
                padding=2, 
            ),                              ## 输出 (32, 14, 14)
            nn.ReLU(),                   
            nn.MaxPool2d(2),                ## 输出 (32, 7, 7)
        )
        self.out = nn.Linear(32 * 7 * 7, 10)## 全连接层,

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)          ##将卷积图拉伸得到向量
        output = self.out(x)
        return output
    
net = CNN() 
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
criterion = nn.CrossEntropyLoss()                  ##交叉熵做为Loss
optimizer = optim.Adam(net.parameters(), lr=0.01)  ##Adam作为优化器

def accuracy(predict, label):
    _,pred_y = torch.max(predict, 1)   
    acc = (pred_y == label).type(torch.float32).mean().item()
    return acc


#开始训练循环
for epoch in range(3):                                            ##训练次数epoch += 1
    epoch += 1
    for batch_idx, (data, target) in enumerate(train_loader):  
        net.train()  
        data = data.to(device)
        target = target.to(device)
        output = net(data) 
        train_right = accuracy(output,target)
        loss = criterion(output, target) 
        optimizer.zero_grad() 
        loss.backward() 
        optimizer.step() 
        
        if batch_idx % 100 == 0:
             net.eval()
         
             for (data, target) in test_loader:
                    data = data.to(device)
                    target = target.to(device)
                    output = net(data) 
                    test_right = accuracy(output, target) 
            
             print('当前epoch: {} [{}/{} ({:.0f}%)]\t损失: {:.6f}\t训练集准确率: {:.2f}%\t测试集正确率: {:.2f}%'.format(
                epoch, batch_idx * 64, len(train_loader.dataset),
                100. * batch_idx / len(train_loader), 
                loss.item(), 
                100. * train_right, 
                100. * test_right  ))

你可能感兴趣的:(pytorch,分类,深度学习)