介绍
卷积神经网络(CNN或ConvNet)是一种专门设计用于对象识别至关重要的任务的深度学习算法,如图像分类、检测和分割。CNN可以在复杂的视觉任务上实现最先进的准确率,驱动许多实际应用,如监控系统、仓库管理等。
作为人类,我们可以通过分析图案、形状和颜色来轻松识别图像中的物体。CNN也可以通过学习哪些图案对区分非常重要来执行这种识别。例如,在试图区分猫和狗的照片时,我们的大脑会关注独特的形状、纹理和面部特征。CNN学会了捕捉这些不同类型的特征。即使对于非常细粒度的分类任务,CNN也能够直接从像素中学习复杂的特征表示。
在这篇文章中,我们将学习卷积神经网络以及如何使用它们在PyTorch中构建图像分类器。
卷积神经网络是如何工作的?
卷积神经网络(CNN)通常用于图像分类任务。从高层次上看,CNN包含三种主要类型的层:
卷积滤波器充当特征探测器,学会在看到特定类型的图案或形状时激活。当这些滤波器应用于图像时,它们产生突出表示某些特征存在的特征图。
例如,一个滤波器在看到垂直线时激活,产生一个显示图像中垂直线的特征图。将多个滤波器应用于相同的输入会产生一组特征图,捕捉图像的不同方面。
通过堆叠多个卷积层,CNN可以学习特征的层次结构,从简单的边缘和图案逐渐建立起更复杂的形状和物体。池化层有助于整合特征表示并提供平移不变性。
最终的全连接层接受这些学到的特征表示并将其用于分类。对于图像分类任务,输出层通常使用softmax激活函数产生类别的概率分布。
在PyTorch中,我们可以定义卷积、池化和全连接层来构建CNN架构。下面是一些示例代码:
# Conv layers
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size)
self.conv2 = nn.Conv2d(in_channels, out_channels, kernel_size)
# Pooling layer
self.pool = nn.MaxPool2d(kernel_size)
# Fully-connected layers
self.fc1 = nn.Linear(in_features, out_features)
self.fc2 = nn.Linear(in_features, out_features)
然后,我们可以使用反向传播和优化来训练CNN模型,卷积和池化层将自动学习有效的特征表示,使网络在视觉任务上获得强大的性能。
CNN入门
在本节中,我们将加载CIFAR10数据集,并使用PyTorch构建和训练基于CNN的分类模型。CIFAR10数据集提供了32x32的RGB图像,涵盖了十个类别,非常适用于测试图像分类模型。这些类别以0到9的整数进行标记。
首先,我们将使用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
)
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to data/cifar-10-python.tar.gz
100%|██████████| 170498071/170498071 [00:10<00:00, 15853600.54it/s]
Extracting data/cifar-10-python.tar.gz to data
Files already downloaded and verified
之后,我们将使用数据加载器并将图像拆分为批次。
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 类并初始化卷积层、maxpool 层和全连接层。我们的架构有2个卷积层,分别包含池化层和线性层。
初始化后,我们不会在前向函数中按顺序连接所有层。如果你是 PyTorch 的新手,你应该阅读 Interpretable Neural Networks with 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):
# input 3x32x32, output 32x32x32
x = self.act1(self.conv1(x))
x = self.drop1(x)
# input 32x32x32, output 32x32x32
x = self.act2(self.conv2(x))
# input 32x32x32, output 32x16x16
x = self.pool2(x)
# input 32x16x16, output 8192
x = self.flat(x)
# input 8192, output 512
x = self.act3(self.fc3(x))
x = self.drop3(x)
# input 512, output 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 个 epoch。
n_epochs = 10
for epoch in range(n_epochs):
for i, (images, labels) in enumerate(trainloader):
# Forward pass
outputs = model(images)
loss = loss_fn(outputs, labels)
# Backward pass and optimize
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('Epoch %d: Accuracy: %d %%' % (epoch,(100 * correct / total)))
我们的简单模型已经达到了57%的准确率,这很糟糕。但是,你可以通过添加更多层、运行更多纪元和超参数优化来提高模型性能。
Epoch 0: Accuracy: 41 %
Epoch 1: Accuracy: 46 %
Epoch 2: Accuracy: 48 %
Epoch 3: Accuracy: 50 %
Epoch 4: Accuracy: 52 %
Epoch 5: Accuracy: 53 %
Epoch 6: Accuracy: 53 %
Epoch 7: Accuracy: 56 %
Epoch 8: Accuracy: 56 %
Epoch 9: Accuracy: 57 %
使用 PyTorch,你不必从头开始创建卷积神经网络的所有组件,因为它们已经可用。如果你使用'torch.nn.Sequential',它会变得更简单。PyTorch 被设计为模块化的,在构建、训练和评估神经网络方面提供了更大的灵活性。
结论
在这篇文章中,我们探讨了如何使用 PyTorch 构建和训练用于图像分类的卷积神经网络。我们介绍了 CNN 架构的核心组件-用于特征提取的卷积层、用于下采样的池化层以及用于预测的全连接层。