PyTorch学习笔记三——搭建简单的CNN手写数字识别网络

本文学习自莫烦的教程

import torch
import torch.nn as nn
import torch.utils.data as Data
from torch.autograd import Variable
import torchvision
torch.manual_seed(1)  # 保证生成的随机数不发生改变

EPOCH = 1               # 迭代轮数
BATCH_SIZE = 50         # 批量大小
LR = 0.001              # 学习率
DOWNLOAD_MNIST = True   # 允许下载 MNIST 数据集

train_data = torchvision.datasets.MNIST(
                    root='./MNIST/',
                    train=True,   # 训练数据
                    transform=torchvision.transforms.ToTensor(),  # shape=(C x H x W),dtype=torch.FloatTensor,并标准化到[0.0-1.0]
                    download=DOWNLOAD_MNIST   # 如果没有数据集,需要下载
)

print(train_data.train_data.size())     # torch.Size([60000, 28, 28])
print(train_data.train_labels.size())   # torch.Size([60000])

train_loader = Data.DataLoader(train_data, BATCH_SIZE, shuffle=True)
	# 将数据集50个50个的打包,一个batch的size是(50, 1, 28, 28),50是批量大小,1是通道数(灰度图1个通道),28,28分别是图片的宽高尺寸
test_data = torchvision.datasets.MNIST(root='./MNIST/', train=False)
test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1)).type(torch.FloatTensor)[:2000] / 255.
	# 准备测试数据,从训练集中选前2000个数据,并在dim=1处增加1维,使得size变为(2000, 1, 28, 28)的四维数据,并对其进行归一化
test_y = test_data.test_labels[:2000]  # 测试数据的标签

# 定义CNN模型
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels=1,    # 输入通道数
                out_channels=16,  # 输出通道数
                kernel_size=5,    # 卷积核的尺寸是(5,5),如果尺寸一样,可以只写一个数
                stride=1,         # 步长为1
                padding=2         # 零填充保持图片宽高不变,公式:padding = (kernel_size - stride) / 2
            ),
            nn.ReLU(),
            nn.BatchNorm2d(16),   # 批量标准化
            nn.MaxPool2d(kernel_size=2)   # 最大池化层,卷积核尺寸是(2,2),该层输出的样本尺寸:16x14x14
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(16, 32, 5, 1, 2),
            nn.ReLU(),
            nn.BatchNorm2d(32),
            nn.MaxPool2d(2)              # 该层输出样本尺寸:32x7x7
        )
        self.out = nn.Linear(32 * 7 * 7, 10)   # 全连接层输出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
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)  # 定义优化器Adam
loss_func = nn.CrossEntropyLoss()                      # 定义交叉熵损失函数
# 训练
for epoch in range(EPOCH):
    for step, (x, y) in enumerate(train_loader):
        b_x = Variable(x)
        b_y = Variable(y)
        output = cnn(b_x)
        loss = loss_func(output, b_y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if step % 100 == 0:
            test_output = cnn(test_x)   # 验证模型
            print(test_output.shape)    # size=(2000, 10)
            pred_y = torch.max(test_output, 1)[1].data.squeeze()
            accuracy = (pred_y == test_y).sum().item() / float(test_y.size(0))
            print('Epoch: ', epoch, '| train loss: %.4f' % loss, '| test accuracy: %.2f' % accuracy)
# 测试
test_output = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
print('Predict Number: ', pred_y)
print('Real NUmber: ', test_y[:10].numpy())

你可能感兴趣的:(PyTorch)