利用pytorch搭建第一个卷积神经网络,实现minst手写数字识别

利用pytorch搭建第一个卷积神经网络,实现minst手写数字识别

注意:若未安装GPU版本的pytorch,记得删掉代码中所有的 .cuda() 。
( .cuda() 为网络模型、输入图片、输入标签移至GPU的操作)
库函数的导入
import torchvision: torchvision包是服务于pytorch深度学习框架的,用来生成图片,视频数据集,和一些流行的模型类和预训练模型,包含以下四个模块
      1. **torchvision.datasets** : 用于流行视觉数据集的数据加载器
      2. **torchvision.models** : 流行模型架构的定义,例如 alexnet、 vgg 和 resnet 以及预先训练的模型。
      3. **torchvision.transforms** :常见的图像转换,如随机作物,旋转等。
      4. **torchvision.utils** : 有用的东西,如保存张量(3 x h x w)作为图像到磁盘,给定一个小批创建一个图像网格,等等。
import torch.utils.data as Data :加载数据用
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'//防止出现内核错误
import torch
import torchvision
import matplotlib.pyplot as plt
import torch.nn as nn
import torch.utils.data as Data #加载数据用
下载数据并批量加载备用
EPOCH = 1  # 训练整批数据多少次
BATCH_SIZE = 64  # 每次批数的数据量
LR = 0.001  # 学习率,学习率的设置直接影响着神经网络的训练效果
#下载数据
train_data = torchvision.datasets.MNIST(  # 训练数据
    root='./mnist_data/',//数据集的根目录在哪里MNIST/processed/training.pt 和 MNIST/processed/test.pt存在哪里
    train=True,// 如果为True,则创建数据集training.pt,否则创建数据集test.pt
    transform=torchvision.transforms.ToTensor(),
    download=True//如果为true,则从Internet下载数据集并将其放在根目录中
)
test_data = torchvision.datasets.MNIST(
    root='./mnist_data/',
    train=False,
    transform=torchvision.transforms.ToTensor(),//将图像像素由0-255(除以255)变为0-1的范围等一系列操作。同时将原本的图像维度由(imagesize,imagesize,channels)转为(channels,imagesize,imagesize)
    download=True
)
# 批量加载
train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
test_loader = Data.DataLoader(dataset=test_data, batch_size=BATCH_SIZE, shuffle=False)
数据可视化,读取一个批次的数据(64张图片),并单独显示第一张图片
# 数据可视化
images, label = next(iter(train_loader))
images_example = torchvision.utils.make_grid(images)//make_grid的作用是将若干幅图像拼成一幅图像。其中padding(参数)的作用就是子图像与子图像之间的pad有多宽。nrow(参数,默认为8)是一行放入八个图片。
images_example = images_example.numpy().transpose(1, 2, 0)  //将图像的通道值置换到最后的维度,符合图像的格式(channels,imagesize,imagesize)转为(imagesize,imagesize,channels)来符合plt.imshow()读取格式
mean = [0.5,0.5,0.5]
std = [0.5,0.5,0.5]
images_example = images_example * std + mean
plt.imshow(images_example)
plt.show()

image_array, _ = train_data[0]  # 把一个批数的训练数据的第一个取出
image_array = image_array.reshape(28, 28)  //转换成28*28的矩阵
plt.imshow(image_array)
plt.show()
搭建卷积神经网络,规定前向传播过程,选择优化函数和损失函数
#创建卷积神经网络类
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(  # input shape (1, 28, 28)
            nn.Conv2d(
                in_channels=1,  # input height输入
                out_channels=16,  # n_filters输出
                kernel_size=5,  # filter size滤波核大小
                stride=1,  # filter movement/step步长
                padding=2,  // 如果想要 con2d 出来的图片长宽没有变化, padding=,(kernel_size-1)/2 当 stride=1填充
            ),  // output shape (16, 28, 28) , W或H=[(输入大小-卷积核大小+2*P)/步长]  +1
            nn.ReLU(),  # activation
            nn.MaxPool2d(kernel_size=2),  // 在 2x2 空间里向下采样, output shape (16, 14, 14)
        )
        self.conv2 = nn.Sequential(  // input shape (16, 14, 14)
            nn.Conv2d(16, 32, 5, 1, 2),  // output shape (32, 14, 14)
            nn.ReLU(),  # activation
            nn.MaxPool2d(2),  # output shape (32, 7, 7)
        )
        self.out = nn.Linear(32 * 7 * 7, 10)  # fully connected layer, output 10 classes

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)  //展平多维的卷积图成 (batch_size, 32 * 7 * 7),x的维度为(batch_size,channal,height,width)
        output = self.out(x)
        return output


cnn = CNN().cuda()
print(cnn)  # 显示神经网络
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)  # Adam优化函数
loss_func = nn.CrossEntropyLoss()  # 损失函数(损失函数分很多种,CrossEntropyLoss适用于作为多分类问题的损失函数)
训练并测试神经网络
# training and testing
for epoch in range(EPOCH):  # 训练批数
    for step, (x, y) in enumerate(train_loader):  # 每个批数的量
        b_x = x.cuda()  # batch x
        b_y = y.cuda()  # batch y
        output = cnn(b_x)  # cnn output
        loss = loss_func(output, b_y)  # cross entropy loss
        print('epoch: %s   step: %s   loss: %s' % (epoch, step, loss))
        optimizer.zero_grad()  # 梯度清零
        loss.backward()  # 损失函数的反向传导
        optimizer.step()  # 对神经网络中的参数进行更新


print('**********************开始测试************************')
for step, (x, y) in enumerate(test_loader):# 在测试集上测试,并计算准确率
    test_x, test_y = x.cuda(), y.cuda()
    test_output = cnn(test_x)
    # 以下三行为pytorch标准计算准确率的方法,十分推荐,简洁明了易操作
    pred_y = torch.max(test_output.cpu(), 1)[1].numpy() //torch.max(a,1) 返回每一行中最大值的那个元素,且返回其索引(返回最大元素在这一行的列索引);troch.max()[1], 只返回最大值的索引;'.numpy()' 把数据转化成numpy ndarry
    label_y = test_y.cpu().numpy()
    accuracy = (pred_y == label_y).sum() / len(label_y)

print(test_output)  # 查看一下预测输出值
print('acc: ', accuracy)

你可能感兴趣的:(深度学习,pytorch,卷积神经网络,分类算法)