pytorch卷积神经网络_「深度学习」卷积神经网络-图片分类案例(pytorch实现)

前言

前文已经介绍过卷积神经网络的基本概念【深度学习】卷积神经网络-CNN简单理论介绍[1]。下面开始动手实践吧。本文任务描述如下: 从公开数据集CIFAR10中创建训练集、测试集数据,使用Pytorch构建CNN模型对训练集数据进行训练,然后在测试集中测试,查看简单的CNN模型训练效果如何。 CIFAR10公开数据地址:http://www.cs.toronto.edu/~kriz/cifar.html[2]。CIFAR-10数据集包含 60000 张 32x32 的彩色 10 中类型的数据, 其中50000张训练图片和10000测试图片。下面是每个类别随机10张图片的结果。

5d2f19d3231aa248514658849b66743e.png

在这里插入图片描述

下面就根据CNN的原理:【深度学习】卷积神经网络-CNN简单理论介绍[3]设计相关的网络和程序,建议使用jupyter。

1 数据集

这里结合torchvision包下载相关数据集并进行数据的预处理。代码如下:

import torchimport torchvisionimport torchvision.transforms as transforms# 数据预处理转换器transform = transforms.Compose([    transforms.ToTensor(),    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 构建训练集数据,使用transform处理数据集供模型直接使用train_set = torchvision.datasets.CIFAR10('./data', train=True, download=True, transform=transform)# 将数据集转成可迭代的批次处理数据train_loader = torch.utils.data.DataLoader(train_set, batch_size=4, shuffle=True, num_workers=1)# 同理构建测试集数据test_set = torchvision.datasets.CIFAR10('./data', train=False, download=True, transform=transform)test_loader = torch.utils.data.DataLoader(test_set, batch_size=4, shuffle=True, num_workers=1)# 数据对应标签classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

注: 如果数据下载较慢,可以在官网下载(cifar-10-python.tar.gz),然后放在data目录下,再将download改为False即可。

另外:transforms.Compose组合两种处理图片的方法,一种是将图片转成模型输入的张量格式数据,另一个则为数据标准化函数。

到此数据应该处理好了。下面我们可以查看一下数据,代码如下:

import matplotlib.pyplot as pltimport numpy as np%matplotlib inlinedef imshow(img):    """    展示图片    img:图片数据    """    img = img / 2 + 0.5  # 反标准化    npimg = img.numpy()  # 将数据转换成numpy格式    plt.imshow(np.transpose(npimg, (1, 2, 0))) # 随机获取部分训练数据dataiter = iter(train_loader)images, labels = dataiter.next()# 显示图像imshow(torchvision.utils.make_grid(images))# 打印标签print(" ".join('%5s' % classes[labels[j]] for j in range(4))) # 结果:car  ship truck horse

我这边随机显示的图片如下:

02ca9ae73c2f33d16994f4d287f9dfcf.png

到这里数据已基本上没什么问题了。

注: 这里暂不考究图像预处理的内容,感兴趣的可以深入了解。

2 构建网络

下面就是构建CNN网络了,根据之前的介绍以及pytorch,代码如下:

import torch.nn as nnimport torch.nn.functional as F# 如果有gpu的可使用GPU加速device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")class CNNNet(nn.Module):    def __init__(self):        super(CNNNet, self).__init__()        # 定义第一个卷积层        self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5, stride=1)        # 定义第一个池化层        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)        # 定义第二个卷积层        self.conv2 = nn.Conv2d(in_channels=16, out_channels=36, kernel_size=3, stride=1)        # 定义第二个池化层        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)        # 定义第一个全连接层        self.fc1 = nn.Linear(1296, 128)        # 定义第二个全连接层        self.fc2 = nn.Linear(128, 10)        def forward(self, x):        # 连接各个cnn各个模块        x = self.pool1(F.relu(self.conv1(x)))        x = self.pool2(F.relu(self.conv2(x)))        # print(x.shape)        x=x.view(-1, 36*6*6)        x=F.relu(self.fc2(F.relu(self.fc1(x))))        # 返回运算后的结果        return x# 实例化模型net = CNNNet()net.to(device)  # 模型设备转移# 查看模型print(net)

打印的模型输出结果如下:

CNNNet(  (conv1): Conv2d(3, 16, kernel_size=(5, 5), stride=(1, 1))  (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)  (conv2): Conv2d(16, 36, kernel_size=(3, 3), stride=(1, 1))  (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)  (fc1): Linear(in_features=1296, out_features=128, bias=True)  (fc2): Linear(in_features=128, out_features=10, bias=True))

针对模型中一些层的参数介绍如下:

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1,bias=True, padding_model='zeros') 其中主要参数释义:

  • in_channels(int):输入图片的通道数目,彩色图片的通道数为3(RGB)
  • out_channels(int): 卷积产生的通道数
  • kernel_size(int or tuple):卷积核的尺寸,单个值则认为卷积核长宽相同
  • stride(int or tuple):卷积步长
  • padding(int or tuple, optional):输入的每一条边填充0的圈数,参数可选,默认为0
  • bias(bool, optional):如果bias=True,添加偏置。

这里需要补充一下多维数据中卷积是如何计算的

2936417af9d888f5b954b033e3437338.png

对于一张三通道的图片,每个通道对应一个卷积核,最后计算得到三个结果矩阵,三个结果矩阵对应值相加到最后的结果,即为一个输出通道。输出形状的计算可参考前文。

torch.nn.MaxPool2d(kernel_size,stride=None,padding=0,diltion=1,return_indices=False,ceil_mode=False) 其中主要参数如下:

  • kernel_size:池化窗口的大小[height, weight],如果一个数,则两者相等
  • stride:窗口在每个维度上滑动的步长,一般为[stride_h, stride_w],如果两者相等,则可为一个数字

输出形状的计算可参考前文。

3 选择优化器和损失函数

由于是分类问题,以及做个简单的模型实现,选择交叉熵损失函数以及带动量的随机梯度下降算法,如下:

## 选择优化器import torch.optim as optimcriterion = nn.CrossEntropyLoss()optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

4 模型训练

模型训练10轮,使用train_loader构建的mini-batch迭代器进行mini-batch的数据训练,每2000个mini-batch打印一次。代码如下:

## 训练模型for epoch in range(10):    running_loss = 0.0    # 迭代,批次训练    for i, data in enumerate(train_loader, 0):        # 获取训练数据        inputs, labels = data        inputs, labels = inputs.to(device), labels.to(device)        # 权重参数梯度清零        optimizer.zero_grad()                # 正向传播        outputs = net(inputs)        # 计算损失值        loss = criterion(outputs, labels)        # 反向传播        loss.backward()        # 参数更新        optimizer.step()        # 损失值累加        running_loss += loss.item()        # 每2000个mini-batch显示一次损失值        if i % 2000 == 1999:            print('[%d, %d] loss:%.3f' % (epoch + 1, i + 1, running_loss / 2000))            running_loss = 0.0print('Finished Training')

对应的训练过程如下图:

c32d064bae4d1a540d3fb606e9d4f565.png

训练过程

5 模型测试

模型训练结束之后,就可以进行模型的测试了。模型使用时,不需要进去相关梯度计算,则需要使用torch.no_grad()方法。

correct = 0    # 预测正确数目total = 0     # 测试样本总数with torch.no_grad():    for data in test_loader:        images, labels = data        images, labels = images.to(device), labels.to(device)        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))# Accuracy of the network on the 10000 test images: 68 %

最后得到的结果是:这个简单的CNN模型对10分类的数据正确率达到68%,总体还是可以的。我们可以看看各个类别预测的正确率,使用代码如下:

## 各类别的准确率class_correct = list(0. for i in range(10))class_total = list(0. for i in range(10))with torch.no_grad():    for data in test_loader:        images, labels = data        images, labels = images.to(device), labels.to(device)        outputs = net(images)        _, predicted = torch.max(outputs, 1)        c = (predicted == labels).squeeze()        for i in range(4):            label = labels[i]            class_correct[label] += c[i].item()            class_total[label] += 1            for i in range(10):    print('Accuracy of %5s: %2d %%' %(classes[i], 100 * class_correct[i] /class_total[i]))

结果如下:

Accuracy of plane: 74 %Accuracy of   car: 83 %Accuracy of  bird: 56 %Accuracy of   cat: 41 %Accuracy of  deer: 65 %Accuracy of   dog: 61 %Accuracy of  frog: 75 %Accuracy of horse: 73 %Accuracy of  ship: 78 %Accuracy of truck: 71 %

6 总结

总体来说,CNN是一个简单而高效的神经网络算法,当前也有很多基于经典CNN改进的卷积神经网络,感兴趣的可以深入学习,后面我们可以看看CNN是如何今学期文本分类的,也就是textcnn模型。

[1]【深度学习】卷积神经网络-CNN简单理论介绍: https://piqiandong.blog.csdn.net/article/details/109905697

[2] http://www.cs.toronto.edu/~kriz/cifar.html: http://www.cs.toronto.edu/~kriz/cifar.html

[3]【深度学习】卷积神经网络-CNN简单理论介绍: https://piqiandong.blog.csdn.net/article/details/109905697

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值