【深度学习】卷积神经网络-图片分类案例(pytorch实现)
文章目录
前言
前文已经介绍过卷积神经网络的基本概念【深度学习】卷积神经网络-CNN简单理论介绍。下面开始动手实践吧。本文任务描述如下:
从公开数据集CIFAR10中创建训练集、测试集数据,使用Pytorch构建CNN模型对训练集数据进行训练,然后在测试集中测试,查看简单的CNN模型训练效果如何。
CIFAR10公开数据地址:http://www.cs.toronto.edu/~kriz/cifar.html。 CIFAR-10数据集包含 60000 张 32x32 的彩色 10 中类型的数据, 其中50000张训练图片和10000测试图片。下面是每个类别随机10张图片的结果。
下面就根据CNN的原理:【深度学习】卷积神经网络-CNN简单理论介绍设计相关的网络和程序,建议使用jupyter。
1. 数据集
这里结合torchvision包下载相关数据集并进行数据的预处理。代码如下:
import torch
import torchvision
import 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 plt
import numpy as np
%matplotlib inline
def 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
我这边随机显示的图片如下:
到这里数据已基本上没什么问题了。
注: 这里暂不考究图像预处理的内容,感兴趣的可以深入了解。
2. 构建网络
下面就是构建CNN网络了,根据之前的介绍以及pytorch,代码如下:
import torch.nn as nn
import 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,添加偏置。
这里需要补充一下多维数据中卷积是如何计算的
对于一张三通道的图片,每个通道对应一个卷积核,最后计算得到三个结果矩阵,三个结果矩阵对应值相加到最后的结果,即为一个输出通道。输出形状的计算可参考前文。
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 optim
criterion = 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.0
print('Finished Training')
对应的训练过程如下图:
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模型。
- 分享
- 举报
-
浏览量:4249次2021-04-19 14:54:23
-
浏览量:3931次2018-02-14 10:30:11
-
浏览量:664次2023-09-06 11:12:55
-
浏览量:4945次2021-07-26 11:28:05
-
浏览量:6541次2021-05-31 17:02:05
-
浏览量:670次2024-02-06 11:56:53
-
浏览量:765次2023-07-05 10:11:45
-
浏览量:5245次2021-08-13 15:39:02
-
浏览量:440次2024-02-01 14:20:47
-
浏览量:5220次2021-05-21 17:03:03
-
浏览量:903次2024-02-06 11:41:16
-
浏览量:487次2023-07-18 13:41:23
-
浏览量:6109次2021-07-05 16:39:40
-
浏览量:500次2023-07-05 10:11:51
-
浏览量:5028次2021-04-15 15:51:43
-
2023-09-27 15:48:35
-
浏览量:4892次2021-04-23 14:09:37
-
浏览量:445次2023-09-06 10:09:13
-
浏览量:723次2023-07-05 10:11:54
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
ladoo
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明