【AI学习笔记9】基于pytorch实现CNN或MLP识别mnist, Mnist recognition using CNN & MLP based on pytorch

基于pytorch实现CNN或MLP识别mnist, Mnist recognition using CNN & MLP based on pytorch

 

一、CNN识别mnist

如图,CNN网络由2层卷积层(Convolutional layer)、2层池化层(Pooling layer)、1层全连接层(FCN layer)组成。【1】

 

二、用CNN识别mnist的代码 【2】【3】【4】【5】

 

# 加载必要库 load lib

import torch

from torchvision import transforms

from torchvision import datasets

from torch.utils.data import DataLoader

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim

import matplotlib.pyplot as plt

 

# 定义超参数 hyperparameter

Batch_Size = 64 #每批处理的数据

Epochs = 100 #训练数据集的轮次

Learning_Rate = 0.01 #学习率

 

# prepare dataset

transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])

 

# read mnist dataset

train_dataset = datasets.MNIST(root='./dataset/mnist/', train=True, download=True, transform=transform)

train_loader = DataLoader(train_dataset, shuffle=True, batch_size=Batch_Size)  # 下载训练集 MNIST 手写数字训练集

test_dataset = datasets.MNIST(root='./dataset/mnist/', train=False, download=True, transform=transform)

test_loader = DataLoader(test_dataset, shuffle=False, batch_size=Batch_Size)  #下载测试集 MNIST 手写数字测试集

 

# design model using class

class CNN(torch.nn.Module):

    def __init__(self):

        super(CNN, self).__init__()

        self.conv1 = torch.nn.Sequential(       # 原始图片为灰度图(1,28,28)

            # 卷积: 输入通道数1,输出通道数10,卷积核3×3,步长1,不填充 (10,24,24)

            torch.nn.Conv2d(in_channels=1, out_channels=10, kernel_size=5, stride=1, padding=0),  

            torch.nn.ReLU(),                    # ReLU激活函数

            torch.nn.MaxPool2d(2),              # 最大池化,池化核2×2,步长2, (10,12,12)

        )

        self.conv2 = torch.nn.Sequential(

            torch.nn.Conv2d(in_channels=10, out_channels=20, kernel_size=5, stride=1, padding=0),      # (20,8,8)

            torch.nn.ReLU(),

            torch.nn.MaxPool2d(2),              # (20,4,4)

        )

        self.fc = torch.nn.Linear(20*4*4, 10)  # 全连接层将它展平flatten,  分成10类(0-9)  classification

 

# 前向传播

    def forward(self, x):

        x = self.conv1(x)

        x = self.conv2(x)

        x = x.view(x.size(0), -1)

        output = self.fc(x)

        return output

 

model = CNN()

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")   # 用CPU还是GPU

print(device)

model.to(device)

 

# construct loss and optimizer

criterion = torch.nn.CrossEntropyLoss()

optimizer = optim.SGD(model.parameters(), lr=Learning_Rate, momentum=0.5)

 

# training cycle forward, backward, update

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

 

def test():

    correct = 0

    total = 0

    with torch.no_grad():

        for data in test_loader:

            images, labels = data

            images, labels = images.to(device), labels.to(device)

            outputs = model(images)

            predicted = torch.max(outputs.data, dim=1)

            total += labels.size(0)

            correct += (predicted == labels).sum().item()

    print('accuracy on test set: %d %% ' % (100 * correct / total))

    return correct / total

 

if __name__ == '__main__':

    epoch_list = []

    acc_list = []

 

    for epoch in range(Epochs):

        train(epoch)

        acc = test()

        epoch_list.append(epoch)

        acc_list.append(acc)

 

    plt.plot(epoch_list, acc_list)

    plt.ylabel('accuracy')

    plt.xlabel('epoch')

    plt.show()

 

运行结果:

cuda:0

[1,   300] loss: 0.588

[1,   600] loss: 0.182

[1,   900] loss: 0.135

accuracy on test set: 97 %

...

...

[100,   300] loss: 0.000

[100,   600] loss: 0.001

[100,   900] loss: 0.001

accuracy on test set: 99 %

 

三、用MLP识别mnist的代码 【6】

 

用如下代码替换 # design model using class 代码块即可:

 

# 定义网络结构

class FC(torch.nn.Module):

    def __init__(self):

        super(FC, self).__init__()

        self.l1 = torch.nn.Linear(784, 15)

        self.l2 = torch.nn.Linear(15, 10)

        self.relu = torch.nn.ReLU()

 

#前向传播

    def forward(self, x):

        x = x.view(-1, 784)

        x = self.l1(x)

        x = self.relu(x)

        x = self.l2(x)

        return x

 

运行结果:

cuda:0

[1,   300] loss: 0.783

[1,   600] loss: 0.385

[1,   900] loss: 0.326

accuracy on test set: 91 %

...

...

[100,   300] loss: 0.087

[100,   600] loss: 0.088

[100,   900] loss: 0.095

accuracy on test set: 94 %

 

 

参考文献(References):

【1】 架构师带你玩转AI 《大模型开发 - 一文搞懂CNNs工作原理(卷积与池化)》

https://www.53ai.com/news/qianyanjishu/594.html

 

【2】 山山而川 《Pytorch实现手写数字识别 | MNIST数据集(CNN卷积神经网络)》

https://www.cnblogs.com/xinyangblog/p/16326476.html

 

【3】 月球背面 《深度学习入门——卷积神经网络CNN基本原理+实战》

https://juejin.cn/post/7238627611265253434

 

【4】 Tom2Code 《手撕CNN的MNIST手写数字识别》

https://cloud.tencent.com/developer/article/2216568

 

【5】 全栈程序员站长 《详解 Pytorch 实现 MNIST[通俗易懂]》

https://cloud.tencent.com/developer/article/2055189

 

【6】 martin-wmx 《MNIST-pytorch

https://github.com/martin-wmx/MNIST-pytorch/blob/master/FC/model.py

 

posted on 2025-02-23 18:45  JasonQiuStar  阅读(217)  评论(0)    收藏  举报