使用 PyTorch 的计算机视觉简介 (3/6)

一、说明

在本单元中,我们将了解卷*积神经网络(CNN),*它是专门为计算机视觉设计的。 卷积层允许我们从图像中提取某些图像模式,以便最终分类器基于这些特征。

二、卷积神经网络

计算机视觉不同于通用分类,因为当我们试图在图片中找到某个物体时,我们正在扫描图像以寻找一些特定的图案 及其组合。比如在寻找猫的时候,我们首先可能会寻找水平线,可以形成胡须,然后一定的胡须组合可以告诉我们它实际上是猫的图片。某些图案的相对位置和存在很重要,而不是它们在图像上的确切位置。为了提取模式,我们将使用卷积过滤器的概念。但首先,让我们加载之前定义的所有依赖项和函数。

复制代码
!wget https://raw.githubusercontent.com/MicrosoftDocs/pytorchfundamentals/main/computer-vision-pytorch/pytorchcv.py
复制代码
import torch
import torch.nn as nn
import torchvision
import matplotlib.pyplot as plt
from torchinfo import summary
import numpy as np

from pytorchcv import load_mnist, train, plot_results, plot_convolution, display_dataset
load_mnist(batch_size=128)

三、卷积滤波器

卷积滤波器是在图像的每个像素上运行并计算相邻像素的加权平均值的小窗口。它们由权重系数矩阵定义。

让我们看看在 MNIST 手写数字上应用两个不同的卷积过滤器的示例:

复制代码
plot_convolution(torch.tensor([[-1.,0.,1.],[-1.,0.,1.],[-1.,0.,1.]]),'Vertical edge filter')
plot_convolution(torch.tensor([[-1.,-1.,-1.],[0.,0.,0.],[1.,1.,1.]]),'Horizontal edge filter')

第一个过滤器称为垂直边缘过滤器,它定义为:

复制代码
 -1 0 1
 -1 0 1 
 -1 0 1

当此过滤器经过相对均匀的像素字段时,所有值的总和为 0。但是,当它在图像中遇到垂直边缘时,会产生高峰值。这就是为什么在上图中,您可以看到由高值和低值表示的垂直边缘,而水平边缘则平均化。

当我们应用水平边缘滤波器时,会发生相反的事情,其中水平线被放大,垂直线被平均。

如果我们将 3 × 3 滤镜应用于大小为 28 × 28 的图像 --- 图像的大小将变为 26 × 26,因为过滤器不会超出图像边界。但是,在某些情况下,我们可能希望保持图像的大小相同,在这种情况下,图像每边都填充零。

在经典的计算机视觉中,将多个过滤器应用于图像以生成特征,然后机器学习算法使用这些特征来构建分类器 。然而,在深度学习中,我们构建的网络可以学习最佳的卷积过滤器来解决分类问题。

为此,我们引入了卷积层。

四、卷积层

卷积层使用 nn 定义。Conv2d 构造。我们需要指定以下内容:

  • in_channels --- 输入通道数。在我们的例子中,我们正在处理灰度图像,因此输入通道的数量为1。彩色图像有 3 个通道 (RGB)。
  • out_channels --- 要使用的过滤器数量。我们将使用 9 种不同的筛选器,这将为网络提供大量机会来探索哪些筛选器最适合我们的方案。
  • kernel_size是滑动窗口的大小。通常使用 3 个× 3 个或 5 个× 5 个过滤器。过滤器尺寸的选择通常通过实验选择,即通过尝试不同的过滤器尺寸并比较结果的准确性。

最简单的CNN将包含一个卷积层。给定输入大小

28 × 28,在应用 5 个 5 × 9 个过滤器后,我们最终将得到 24 × 24 × 24 的张量(空间大小较小,因为只有 5 个位置,长度为 28 的

滑动间隔可以容纳 9 像素)。在这里,每个滤波器的结果由图像中的不同通道表示。因此,第一维<>对应于滤波器的数量。

卷积后,我们将 9 × 24 × 24 张量展平为一个大小为 5184 的向量,然后添加线性层,生成 10 个类。我们还在层之间使用 relu 激活函数。

复制代码
class OneConv(nn.Module):
    def __init__(self):
        super(OneConv, self).__init__()
        self.conv = nn.Conv2d(in_channels=1,out_channels=9,kernel_size=(5,5))
        self.flatten = nn.Flatten()
        self.fc = nn.Linear(5184,10)

    def forward(self, x):
        x = nn.functional.relu(self.conv(x))
        x = self.flatten(x)
        x = nn.functional.log_softmax(self.fc(x),dim=1)
        return x

net = OneConv()

summary(net,input_size=(1,1,28,28))
复制代码
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
├─Conv2d: 1-1                            [1, 9, 24, 24]            234
├─Flatten: 1-2                           [1, 5184]                 --
├─Linear: 1-3                            [1, 10]                   51,850
==========================================================================================
Total params: 52,084
Trainable params: 52,084
Non-trainable params: 0
Total mult-adds (M): 0.18
==========================================================================================
Input size (MB): 0.00
Forward/backward pass size (MB): 0.04
Params size (MB): 0.21
Estimated Total Size (MB): 0.25
==========================================================================================

您可以看到,该网络包含大约 50k 的可训练参数,而在完全连接的多层网络中,则包含大约 80k 个参数。这使我们能够在较小的数据集上获得良好的结果,因为卷积网络的泛化效果要好得多。

请注意,卷积层的参数数量非常少,并且不依赖于图像的分辨率!在我们的例子中,我们使用了 9 个维度为 5 × 5 的过滤器,因此参数的数量为

9 × 5 × 5 + 9 = 234。尽管我们在上面的讨论中错过了这一点,但卷积过滤器也有偏见。我们网络的大部分参数来自最终的密集层。

复制代码
hist = train(net,train_loader,test_loader,epochs=5)
plot_results(hist)
复制代码
Epoch  0, Train acc=0.947, Val acc=0.969, Train loss=0.001, Val loss=0.001
Epoch  1, Train acc=0.979, Val acc=0.975, Train loss=0.001, Val loss=0.001
Epoch  2, Train acc=0.985, Val acc=0.977, Train loss=0.000, Val loss=0.001
Epoch  3, Train acc=0.988, Val acc=0.975, Train loss=0.000, Val loss=0.001
Epoch  4, Train acc=0.988, Val acc=0.976, Train loss=0.000, Val loss=0.001

如您所见,与以前的全连接网络相比,我们能够实现更高的精度和更快的速度。我们还可以可视化经过训练的卷积层的权重,以尝试更有意义地了解正在发生的事情:

复制代码
fig,ax = plt.subplots(1,9)
with torch.no_grad():
    p = next(net.conv.parameters())
    for i,x in enumerate(p):
        ax[i].imshow(x.detach().cpu()[0,...])
        ax[i].axis('off')

您可以看到其中一些过滤器看起来可以识别一些倾斜的笔划,而另一些则看起来非常随机。

五、小结

卷积层允许我们从图像中提取某些图像模式,以便最终分类器基于这些特征。但是,我们可以使用相同的方法来提取特征空间内的模式,方法是在第一个卷积层之上堆叠另一个卷积层。我们将在下一个单元中学习多层卷积网络。

相关推荐
galileo201629 分钟前
LLM与金融
人工智能
DREAM依旧1 小时前
隐马尔科夫模型|前向算法|Viterbi 算法
人工智能
GocNeverGiveUp1 小时前
机器学习2-NumPy
人工智能·机器学习·numpy
B站计算机毕业设计超人2 小时前
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
大数据·人工智能·爬虫·python·机器学习·课程设计·数据可视化
学术头条2 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
18号房客2 小时前
一个简单的机器学习实战例程,使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集(Iris Dataset)**的分类
人工智能·深度学习·神经网络·机器学习·语言模型·自然语言处理·sklearn
feifeikon2 小时前
机器学习DAY3 : 线性回归与最小二乘法与sklearn实现 (线性回归完)
人工智能·机器学习·线性回归
游客5202 小时前
opencv中的常用的100个API
图像处理·人工智能·python·opencv·计算机视觉
古希腊掌管学习的神2 小时前
[机器学习]sklearn入门指南(2)
人工智能·机器学习·sklearn
凡人的AI工具箱3 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite