欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

用PyTorch搭建CNN模型,轻松识别MNIST手写数字数据集

最编程 2024-02-12 21:20:58
...

主要分五步:
1.数据块的加载处理
2.模型的建立
3.训练模型
4.预测测试模型
5.保存模型

参考:https://zhuanlan.zhihu.com/p/45500657 (写的不错)
另补小知识:标量,向量,矩阵它们三个也是张量,标量是零维的张量,向量是一维的张量,矩阵是二维的张量 https://zhuanlan.zhihu.com/p/45497796

import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
import torchvision
import time

# import matplotlib.pyplot as plt

torch.manual_seed(1)

#超参数
EPOCH = 1
BATCH_SIZE = 50
LR = 0.001
# DOWNLOAD_MNIST = False
if_use_gpu = 1

# 获取训练集dataset
training_data = torchvision.datasets.MNIST(
    root='./mnist/',  # dataset存储路径
    train=True,  # True表示是train训练集,False表示test测试集
    transform=torchvision.transforms.ToTensor(),  # 将原数据规范化到(0,1)区间
    download=False,
)

# 打印MNIST数据集的训练集及测试集的尺寸
print(training_data.train_data.size())
print(training_data.train_labels.size())
# torch.Size([60000, 28, 28])
# torch.Size([60000])

# plt.imshow(training_data.train_data[0].numpy(), cmap='gray')
# plt.title('%i' % training_data.train_labels[0])
# plt.show()

# 通过torchvision.datasets获取的dataset格式可直接可置于DataLoader
train_loader = Data.DataLoader(dataset=training_data, batch_size=BATCH_SIZE,
                               shuffle=True)

# 获取测试集dataset

test_data = torchvision.datasets.MNIST(
    root='./mnist/',  # dataset存储路径
    train=False,  # True表示是train训练集,False表示test测试集
    transform=torchvision.transforms.ToTensor(),  # 将原数据规范化到(0,1)区间
    download=False,
)
# 取前全部10000个测试集样本
test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1).float(), requires_grad=False)
# test_x = test_x.cuda()
## (~, 28, 28) to (~, 1, 28, 28), in range(0,1)
test_y = test_data.test_labels


# 创建模型
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=16, kernel_size=5,
                      stride=1, padding=2),  # (16,28,28)
            # 想要con2d卷积出来的图片尺寸没有变化, padding=(kernel_size-1)/2
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)  # (16,14,14)
        )
        self.conv2 = nn.Sequential(  # (16,14,14)
            nn.Conv2d(16, 32, 5, 1, 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)  # 将(batch,32,7,7)展平为(batch,32*7*7)
        output = self.out(x)
        return output

#损失
cnn = CNN()
# if if_use_gpu:
#     cnn = cnn.cuda()
loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)

#训练
for epoch in range(EPOCH):
    start = time.time()
    for step, (x, y) in enumerate(train_loader):
        b_x = Variable(x, requires_grad=False)
        b_y = Variable(y, requires_grad=False)
        # if if_use_gpu:
        b_x = b_x
        b_y = b_y
        print(step)
        output = cnn(b_x)
        loss = loss_function(output, b_y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if step % 10 == 0:
            print('Epoch:', epoch, '|Step:', step,
                  '|train loss:%d' % loss.item())

#测试
test_output = cnn(test_x)
pred_y = torch.max(test_output, 1)[1].data.squeeze()
print(pred_y,test_y)
accuracy = sum(pred_y == test_y) / test_y.size(0)
print('Test Acc: %.4f'%accuracy)