PyCharm-MNIST手写数字的识别

本文是将PyTorch上的MNIST手写数字的识别、CNN网络 在PyCharm 上进行展示

可以看我这篇博客

PyTorch-CNN Model

关于MNIST数据集无法下载的问题 可以看我另一篇博客

PyTorch-MNIST数据集无法下载-采用手动下载的方式

在PyCharm中导入PyTorch环境可以看我下面这篇博客

PyTorch-用Pycharm创建项目

本实例的代码

import torch
import numpy as np
import torchvision #torch的视觉包
import torchvision.datasets as datasets
import torchvision.transforms as transforms
from torch.utils.data.dataloader import DataLoader
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt
import PIL.Image as Image
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import torch.nn as nn
import torch.nn.functional as F
import torchvision
import torch.optim as optim

mnist=torchvision.datasets.MNIST('./mnist_dataset',train=True,transform=ToTensor(),target_transform=None,download=False)
#print(mnist) #输出MNIST数据集的详细信息
data=[d[0].data.cpu().numpy() for d in mnist]
print(np.mean(data))
print(np.std(data))

bs=32
train_data_loader=torch.utils.data.DataLoader(
    dataset=torchvision.datasets.MNIST('./mnist_dataset',train=True,transform=transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.1307,),(0.3081,))]),target_transform=None,download=False),
    #其中,0.1307和0.3081是mnist数据集的均值和标准差,因为mnist数据值都是灰度图,所以图像的通道数只有一个,因此均值和标准差各一个。
    # 要是imagenet数据集的话,由于它的图像都是RGB图像,因此他们的均值和标准差各3个,分别对应其R,G,B值。
    # 例如([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])就是Imagenet dataset的标准化系数(RGB三个通道对应三组系数)。
    # 数据集给出的均值和标准差系数,每个数据集都不同的,都是数据集提供方给出的。
    batch_size=bs,
    shuffle=True,
    pin_memory=True
    #“pin_memory就是锁页内存,创建DataLoader时,设置pin_memory=True,
    # 则意味着生成的Tensor数据最开始是属于内存中的锁页内存, 这样将内存的Tensor转义到GPU的显存就会更快一些。
)

test_data_loader=torch.utils.data.DataLoader(
    dataset=torchvision.datasets.MNIST('./mnist_dataset',train=False,transform=transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.1307,),(0.3081,))]),target_transform=None,download=False),
    batch_size=bs,
    shuffle=True,
    pin_memory=True
)

class CNNModel(nn.Module):
    def __init__(self):  # 初始化
        super(CNNModel, self).__init__()  # 调用父类
        self.conv1 = nn.Conv2d(1, 20, 5, 1)  # 1维->20维 卷积核大小为5
        self.conv2 = nn.Conv2d(20, 50, 5, 1)  # 20维->50维 卷积核大小为5
        self.fc1 = nn.Linear(4 * 4 * 50, 500)  # 线性层
        self.fc2 = nn.Linear(500, 10)  # 线性层

    def forward(self, x):
        # x:1*28*28  1代表通道
        x = F.relu(self.conv1(x))  # 前向卷积 28*28 -> (28+1-5)=24 24*24
        x = F.max_pool2d(x, kernel_size=2, stride=2)  # 12*12
        x = F.relu(self.conv2(x))  # 8*8
        x = F.max_pool2d(x, kernel_size=2, stride=2)  # 4*4
        x = x.reshape(-1, 4 * 4 * 50)
        # 或者用 x = x.view(-1,4*4*50)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)

#创建网络实例
cnnmodel=CNNModel()
print(cnnmodel)

for name,param in cnnmodel.named_parameters():
    print(name,param.shape)

#准确度的评估
optimizer=torch.optim.SGD(cnnmodel.parameters(),lr=0.1,momentum=0.5)
for epoch in range(5):
    total_loss=0
    total_correct=0
    for batch in train_data_loader:
        image,labels=batch
        optimizer.zero_grad()
        out=cnnmodel(image)
        loss=F.cross_entropy(out,labels)
        total_loss+=loss.item() #把数值取出来
        loss.backward()
        optimizer.step()
        total_correct+=out.argmax(dim=1).eq(labels).sum().item()
    print("epoch:",epoch,"loss:",total_loss,"acc:",total_correct/60000)

运行结果如下所示

image

posted @ 2022-06-11 09:50  司砚章  阅读(838)  评论(0编辑  收藏  举报