使用PyTorch构建卷积神经网络

2023年09月26日 由 camellia 发表 386 0

介绍


卷积神经网络(CNN或ConvNet)是一种专门设计用于对象识别至关重要的任务的深度学习算法,如图像分类、检测和分割。CNN可以在复杂的视觉任务上实现最先进的准确率,驱动许多实际应用,如监控系统、仓库管理等。


作为人类,我们可以通过分析图案、形状和颜色来轻松识别图像中的物体。CNN也可以通过学习哪些图案对区分非常重要来执行这种识别。例如,在试图区分猫和狗的照片时,我们的大脑会关注独特的形状、纹理和面部特征。CNN学会了捕捉这些不同类型的特征。即使对于非常细粒度的分类任务,CNN也能够直接从像素中学习复杂的特征表示。


在这篇文章中,我们将学习卷积神经网络以及如何使用它们在PyTorch中构建图像分类器。


卷积神经网络是如何工作的?


卷积神经网络(CNN)通常用于图像分类任务。从高层次上看,CNN包含三种主要类型的层:


  1. 卷积层。将卷积滤波器应用于输入图像以提取特征。这些层中的神经元称为滤波器,它们捕捉输入中的空间模式。
  2. 池化层。对卷积层的特征图进行下采样以合并信息。最大池化和平均池化是常用的策略。
  3. 全连接层。将卷积层和池化层的高层特征作为分类的输入。可以堆叠多个全连接层。


卷积滤波器充当特征探测器,学会在看到特定类型的图案或形状时激活。当这些滤波器应用于图像时,它们产生突出表示某些特征存在的特征图。


例如,一个滤波器在看到垂直线时激活,产生一个显示图像中垂直线的特征图。将多个滤波器应用于相同的输入会产生一组特征图,捕捉图像的不同方面。


2.1

通过堆叠多个卷积层,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)

正如我们所看到的,我们有汽车、动物、飞机和船只的图像。


2.2

接下来,我们将构建我们的 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。


  1. 我们使用模型的前向函数进行正向传递,然后使用损失函数进行向后传递,最后更新权重。此步骤在所有类型的神经网络模型中几乎相似。
  2. 之后,我们使用测试数据加载器在每个纪元结束时评估模型性能。
  3. 计算模型的准确性并打印结果。
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 架构的核心组件-用于特征提取的卷积层、用于下采样的池化层以及用于预测的全连接层。

文章来源:https://www.kdnuggets.com/building-a-convolutional-neural-network-with-pytorch
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
写评论取消
回复取消