简介
卷积神经网络(CNN或ConvNet)是一种专门设计用于需要进行对象识别的任务的深度学习算法,如图像分类、检测和分割。CNN能够在复杂的视觉任务上实现最先进的准确性,驱动许多现实生活应用,如监控系统、仓库管理等。
作为人类,我们可以通过分析图案、形状和颜色来轻松识别图像中的对象。CNN也可以通过学习哪些模式对于区分是重要的来进行此识别。例如,在试图区分猫和狗的照片时,我们的大脑专注于独特的形状、纹理和面部特征。CNN学会了捕捉这些相同类型的区分特征。即使对于非常细粒度的分类任务,CNN也能够直接从像素中学习复杂的特征表示。
在本博客文章中,我们将学习关于卷积神经网络以及如何使用它们来构建一个基于PyTorch的图像分类器。
卷积神经网络的工作原理
卷积神经网络(CNN)常用于图像分类任务。从高层次上看,CNN包含三种主要类型的层:
- 卷积层。对输入应用卷积过滤器以提取特征。这些层中的神经元称为过滤器,并捕捉输入中的空间模式。
- 池化层。对来自卷积层的特征图进行下采样以合并信息。常用的策略有最大池化和平均池化。
- 全连接层。以卷积和池化层的高级特征作为分类的输入。可以堆叠多个全连接层。
卷积过滤器充当特征检测器,学会在看到特定类型的模式或形状时激活。当这些过滤器应用于图像时,它们产生突出显示特定特征存在的特征图。
例如,一个过滤器在看到垂直线时激活,产生一个显示图像中垂直线的特征图。多个过滤器应用于同一输入会产生一组特征图,捕捉图像的不同方面。
通过堆叠多个卷积层,CNN可以学习特征的层次结构-从简单的边缘和模式到更复杂的形状和对象。池化层有助于合并特征表示并提供平移不变性。
最后的全连接层将这些学到的特征表示用于分类。对于图像分类任务,输出层通常使用softmax激活函数产生类别的概率分布。
在PyTorch中,我们可以定义卷积、池化和全连接层来构建CNN架构。下面是一些示例代码:
# 卷积层
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size)
self.conv2 = nn.Conv2d(in_channels, out_channels, kernel_size)
# 池化层
self.pool = nn.MaxPool2d(kernel_size)
# 全连接层
self.fc1 = nn.Linear(in_features, out_features)
self.fc2 = nn.Linear(in_features, out_features)
然后,我们可以使用反向传播和优化算法在图像数据上训练CNN。卷积和池化层将自动学习有效的特征表示,使网络能够在视觉任务上取得强大的性能。
开始使用CNN
在本部分中,我们将加载CIFAR10数据集,并使用PyTorch构建和训练基于CNN的分类模型。CIFAR10数据集提供了32×32的RGB图像,涵盖了十个类别,非常适合测试图像分类模型。类别以0到9的整数标记。
注意:示例代码是从MachineLearningMastery.com博客修改而来。
首先,我们将使用torchvision下载和加载CIFAR10数据集。我们还将使用torchvision将测试和训练集都转换为张量。
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
transform = torchvision.transforms.Compose(
[torchvision.transforms.ToTensor()]
)
train = torchvision.datasets.CIFAR10(
root="data", train=True, download=True, transform=transform
)
test = torchvision.datasets.CIFAR10(
root="data", train=False, download=True, transform=transform
)
正在下载 https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 到 data/cifar-10-python.tar.gz
100%|██████████| 170498071/170498071 [00:10<00:00, 15853600.54it/s]
正在解压缩 data/cifar-10-python.tar.gz 至 data
文件已经下载并验证完毕
接下来,我们将使用数据加载器将图像分成批次。
batch_size = 32
trainloader = torch.utils.data.DataLoader(
train, batch_size=batch_size, shuffle=True
)
testloader = torch.utils.data.DataLoader(
test, batch_size=batch_size, shuffle=True
)
为了将批次中的图像可视化,我们将使用matplotlib和torchvision的实用函数。
from torchvision.utils import make_grid
import matplotlib.pyplot as plt
def show_batch(dl):
for images, labels in dl:
fig, ax = plt.subplots(figsize=(12, 12))
ax.set_xticks([]); ax.set_yticks([])
ax.imshow(make_grid(images[:64], nrow=8).permute(1, 2, 0))
break
show_batch(trainloader)
如我们所见,我们有汽车、动物、飞机和船只的图像。
接下来,我们将构建我们的CNN模型。为此,我们必须创建一个Python类并初始化卷积、最大池化和全连接层。我们的架构有2个具有池化和线性层的卷积层。
初始化后,我们将在前向函数中按顺序连接所有层。如果您对PyTorch不熟悉,您应该阅读《使用PyTorch进行可解释的神经网络》以了解每个组件的详细信息。
class CNNModel(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=(3,3), stride=1, padding=1)
self.act1 = nn.ReLU()
self.drop1 = nn.Dropout(0.3)
self.conv2 = nn.Conv2d(32, 32, kernel_size=(3,3), stride=1, padding=1)
self.act2 = nn.ReLU()
self.pool2 = nn.MaxPool2d(kernel_size=(2, 2))
self.flat = nn.Flatten()
self.fc3 = nn.Linear(8192, 512)
self.act3 = nn.ReLU()
self.drop3 = nn.Dropout(0.5)
self.fc4 = nn.Linear(512, 10)
def forward(self, x):
# 输入 3x32x32, 输出 32x32x32
x = self.act1(self.conv1(x))
x = self.drop1(x)
# 输入 32x32x32, 输出 32x32x32
x = self.act2(self.conv2(x))
# 输入 32x32x32, 输出 32x16x16
x = self.pool2(x)
# 输入 32x16x16, 输出 8192
x = self.flat(x)
# 输入 8192, 输出 512
x = self.act3(self.fc3(x))
x = self.drop3(x)
# 输入 512, 输出 10
x = self.fc4(x)
return x
我们现在将初始化我们的模型,设置损失函数和优化器。
model = CNNModel()
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
在训练阶段,我们将对模型进行10个周期的训练。
- 我们使用模型的前向函数进行前向传递,然后使用损失函数进行反向传递,最后更新权重。这一步在所有类型的神经网络模型中几乎是相似的。
- 之后,我们使用一个测试数据加载器在每个周期结束时评估模型性能。
- 计算模型的准确率并打印结果。
n_epochs = 10
for epoch in range(n_epochs):
for i, (images, labels) in enumerate(trainloader):
# 前向传递
outputs = model(images)
loss = loss_fn(outputs, labels)
# 反向传递和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('第 %d 个周期:准确率:%d %%' % (epoch,(100 * correct / total)))
我们的简单模型达到了57%的准确率,这很差。但是,您可以通过添加更多层、运行更多周期和进行超参数优化来提高模型性能。
第 0 个周期:准确率:41 %
第 1 个周期:准确率:46 %
第 2 个周期:准确率:48 %
第 3 个周期:准确率:50 %
第 4 个周期:准确率:52 %
第 5 个周期:准确率:53 %
第 6 个周期:准确率:53 %
第 7 个周期:准确率:56 %
第 8 个周期:准确率:56 %
第 9 个周期:准确率:57 %
使用PyTorch,您不必从头开始创建卷积神经网络的所有组件,因为它们已经可用。如果使用`torch.nn.Sequential`,甚至更简单。PyTorch被设计成模块化的,并在构建、训练和评估神经网络方面提供了更大的灵活性。
结论
在本文中,我们探讨了如何使用PyTorch构建和训练卷积神经网络进行图像分类。我们介绍了卷积层用于特征提取、池化层用于降采样以及全连接层用于预测的CNN架构的核心组件。
我希望本文提供了有关使用PyTorch实现卷积神经网络的概述。CNN是计算机视觉中深度学习的基本架构,而PyTorch使我们能够快速构建、训练和评估这些模型。
Abid Ali Awan(@1abidaliawan)是一位获得认证的数据科学家,热衷于构建机器学习模型。目前,他专注于内容创作,并在机器学习和数据科学技术方面撰写技术博客。Abid拥有技术管理硕士学位和电信工程学士学位。他的愿景是利用图神经网络为患有心理疾病的学生构建一个AI产品。