利用pytorch搭建卷积神经网络(CNN)训练简单手写数字数据集(MNIST)(相应代码和数据集在文章顶部)

1.MNIST手写数字数据集介绍

        MNIST数据集是学习图像处理接手的第一个数据集,其地位相当于我们学习C语言的第一个源程序“Hello World!”只不过你需要提前掌握图像处理基础知识和pytorch的基本语法规则。

        MNIST数据集构成:60000张训练数据集和10000张测试数据集。 

        每一张灰度图包含28*28个像素,且其通道数为1。MNIST数据集的内容为0-9数字,由不同的人手写在纸上后,经过大小标准化处理和中心化处理呈现为以下形式: (以8*8个图像组成为例)                                                                                                                     

                                               

官方介绍原文:MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges

2.网络模型介绍

        因为MNIST数据集已经经过中心化处理,且为单通道图像,所以没有必要选取大型的深度神经网络对其进行处理,这里选取了一个较为简单的神经网络模型对其进行训练:                                     

参考模型介绍:MNIST Handwritten Digits Classification using a Convolutional Neural Network (CNN) | by Krut Patel | Towards Data Science

3.模型训练 

        新建神经网络模型:(新建文件model.py)

# 搭建mnist神经网络模型
import torch
from torch import nn

class mnist_Model(nn.Module):
    def __init__(self):
        super(mnist_Model, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(1, 32, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(32, 64, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            nn.Flatten(),
            nn.Linear(7*7*64, 128),
            nn.Dropout2d(p=0.5),
            nn.Linear(128, 10)
        )
    def forward(self, x):
        x = self.model(x)
        return x

用MNIST手写数据集训练上述模型:(新建文件model.py,名称无所谓,注意import别引用错)

# 训练网络并测试
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from model import*
import time

writer = SummaryWriter("mnist_model")  # tensorboard查看运行结果

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  #有gpu则用gpu进行训练,否则用cpu

# 读取数据并转化为tensor类型
train_data = torchvision.datasets.MNIST("./dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.MNIST("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)

# 数据长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练集的长度为:{}".format(train_data_size))
print("测试集的长度为:{}".format(test_data_size))

# 定义一次取多少张图片
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

# 读取CNN并令CNN在gpu上运行
mnist_model = mnist_Model()
mnist_model = mnist_model.to(device)

# 定义损失函数并令其在gpu上运行
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)

# 定义优化器和学习率
learning_rate = 0.01
optimizer = torch.optim.SGD(mnist_model.parameters(), lr=learning_rate)

# 定义训练前初值
train_step = 0
test_step = 0
epoch = 30
start_time = time.time()

for i in range(epoch):  # i为训练轮数
    print("第{}轮训练开始".format(i+1))
    mnist_model.train()  # 置为训练状态
    for data in train_dataloader:  # 取数据并令其在gpu上运行  一轮为一整个训练集经过一次网络
        imgs, targets = data
        imgs = imgs.to(device)
        targets = targets.to(device)  # 将图片输入模型
        outputs = mnist_model(imgs)
        loss = loss_fn(outputs, targets)  # 计算模型输出值和目标值的交叉熵
        optimizer.zero_grad()  # 优化器梯度置零
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数
        train_step += 1
        if train_step % 100 == 0:  # 输出每一轮训练中的训练情况
            end_time = time.time()
            print("训练次数:{},Loss:{},所用时间:{}".format(train_step, loss, end_time-start_time))
    mnist_model.eval()  # 置为测试状态
    test_loss = 0
    test_accuracy = 0  # 定义损失值和正确率
    with torch.no_grad():  # 测试集不进行训练
        for data in test_dataloader:  # 一轮为一整个测试集经过一次网络正向
            imgs, targets = data
            imgs = imgs.to(device)
            targets = targets.to(device)  # 取数据并令其在gpu上运行
            outputs = mnist_model(imgs)  # 将图片输入模型
            loss = loss_fn(outputs, targets)  # 计算损失值
            test_loss += loss  # 计算每一轮的总损失值
            accuracy = (outputs.argmax(1) == targets).sum()  # 输出10个数中的最大值是否对应targets,是则为1,否则为0,最后总和
            test_accuracy += accuracy
        print("整体测试集上的Loss:{},Accuracy:{}".format(test_loss, test_accuracy/test_data_size))  # 输出正确率和损失值
    writer.add_scalar("test_accuracy", test_accuracy/test_data_size, i+1)
    test_step += 1

在上述代码中设置了30轮训练和测试,其在测试集上的正确率随轮数的变化关系 :

        因为手写数字数据集经过中心化处理,且为单通道图像,其特征图较易提取,在第一轮训练结束后模型在测试集上的正确率便可达到90%,经过30轮训练可以达到99.2%.

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,让我们开始。首先,需要准备 MNIST 数据集。可以使用 PyTorch 内置的 torchvision.datasets 库来下载并加载数据集。 ```python import torch import torchvision import torchvision.transforms as transforms transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=2) testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False, num_workers=2) ``` 接下来,我们可以定义我们的卷积神经网络模型。这里我们定义了两个卷积层和两个全连接层。 ```python import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, 3, 1) self.conv2 = nn.Conv2d(32, 64, 3, 1) self.dropout1 = nn.Dropout2d(0.25) self.dropout2 = nn.Dropout2d(0.5) self.fc1 = nn.Linear(9216, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = self.conv1(x) x = F.relu(x) x = self.conv2(x) x = F.relu(x) x = F.max_pool2d(x, 2) x = self.dropout1(x) x = torch.flatten(x, 1) x = self.fc1(x) x = F.relu(x) x = self.dropout2(x) x = self.fc2(x) output = F.log_softmax(x, dim=1) return output net = Net() ``` 接下来,我们可以定义损失函数和优化器。在这个例子中,我们使用交叉熵损失函数和随机梯度下降优化器。 ```python import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) ``` 现在,我们可以开始训练我们的模型。在每个 epoch 中,我们将遍历整个训练集,并使用随机梯度下降进行优化。此外,我们还将计算模型在测试集上的准确率。 ```python for epoch in range(10): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 100 == 99: # 每 100 个 mini-batches 输出一次损失 print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100)) running_loss = 0.0 correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the 10000 test images: %d %%' % ( 100 * correct / total)) ``` 训练完成后,我们可以保存模型并测试它在新数据上的性能。 ```python PATH = './cnn.pth' torch.save(net.state_dict(), PATH) net = Net() net.load_state_dict(torch.load(PATH)) # 测试 dataiter = iter(testloader) images, labels = dataiter.next() outputs = net(images) _, predicted = torch.max(outputs, 1) print('Predicted: ', ' '.join('%5s' % predicted[j] for j in range(10))) ``` 恭喜你,现在你已经成功地使用 PyTorch 搭建了一个卷积神经网络,并且能够对手写数字进行识别!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

憨八龟巨豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值