目录

0. 前言

1. 从全连接层到卷积(第1节)

1.1 不变性

1.2 多层感知机的限制 (卷积是改进版)

1.2.1 改进1:平移不变性

1.2.2 改进2:局部性

1.3 卷积(花书直接从这里开讲)

1.4 “沃尔多在哪里”回顾

1.4.1 通道(第4节会细讲)

1.5 小结

2. 图像卷积(第2节)

2.1 互相关运算 (核心)

2.2 卷积层 (重点)

2.3 图像中目标的边缘检测

2.4 学习卷积核 (更新权重参数)

2.5 互相关和卷积 (补充)

2.6 特征映射和感受野 (补充)

2.7 一维和三维 (2D的补充)

2.8 小结


0. 前言

  • 课程全部代码(pytorch版)已上传到附件
  • 本章节为原书第6章,共分为6节,本篇是第1-2节:从全连接到卷积层 + 卷积层

这两节的代码位置分别为:

  • chapter_convolutional-neural-networks/why-conv.ipynb
  • chapter_convolutional-neural-networks/conv-layer.ipynb

本章的视频链接:19 卷积层【动手学深度学习v2】_哔哩哔哩_bilibili

69da20a07edd4c40bc058de99b77fc4d.gif

1. 从全连接层到卷积(第1节)

:label:sec_why-conv

我们之前讨论的多层感知机十分适合处理表格数据,其中行对应样本,列对应特征。 对于表格数据,我们寻找的模式可能涉及特征之间的交互,但是我们不能预先假设任何与特征交互相关的先验结构。 此时,多层感知机可能是最好的选择,然而对于高维感知数据,这种缺少结构的网络可能会变得不实用。

例如,在之前猫狗分类的例子中:假设我们有一个足够充分的照片数据集,数据集中是拥有标注的照片,每张照片具有百万级像素,这意味着网络的每次输入都有一百万个维度。 即使将隐藏层维度降低到1000,这个全连接层也将有10^6×10^3=10^9个参数。

笔记:1000×1000是假定的图像输入层,每个前一层的每个元素(神经元)都与隐藏层的每个神经元有一个连接权重

想要训练这个模型将不可实现,因为需要有大量的GPU、分布式优化训练的经验和超乎常人的耐心。

笔记:关于连接权重的细节,可参考softmax那里,相当于一个全连接层:286a87431cb34824a145f0b27f7f55c9.png笔记:这就是参数量为啥是输入元素量×输出元素量

有些读者可能会反对这个观点,认为要求百万像素的分辨率可能不是必要的。 然而,即使分辨率减小为十万像素,使用1000个隐藏单元的隐藏层也可能不足以学习到良好的图像特征,在真实的系统中我们仍然需要数十亿个参数。 此外,拟合如此多的参数还需要收集大量的数据。 然而,如今人类和机器都能很好地区分猫和狗:这是因为图像中本就拥有丰富的结构,而这些结构可以被人类和机器学习模型使用。 卷积神经网络(convolutional neural networks,CNN)是机器学习利用自然图像中一些已知结构的创造性方法。

1.1 不变性

想象一下,假设我们想从一张图片中找到某个物体。 合理的假设是:无论哪种方法找到这个物体,都应该和物体的位置无关。 理想情况下,我们的系统应该能够利用常识:猪通常不在天上飞,飞机通常不在水里游泳。 但是,如果一只猪出现在图片顶部,我们还是应该认出它。 我们可以从儿童游戏”沃尔多在哪里”( :numref:img_waldo)中得到灵感: 在这个游戏中包含了许多充斥着活动的混乱场景,而沃尔多通常潜伏在一些不太可能的位置,读者的目标就是找出他。 尽管沃尔多的装扮很有特点,但是在眼花缭乱的场景中找到他也如大海捞针。 然而沃尔多的样子并不取决于他潜藏的地方,因此我们可以使用一个“沃尔多检测器”扫描图像。 该检测器将图像分割成多个区域,并为每个区域包含沃尔多的可能性打分。 卷积神经网络正是将空间不变性(spatial invariance)的这一概念系统化,从而基于这个模型使用较少的参数来学习有用的表示。

42ab991f07d84e0baad18879a772f1a8.png

:width:400px :label:img_waldo

现在,我们将上述想法总结一下,从而帮助我们设计适合于计算机视觉的神经网络架构。

  1. 平移不变性(translation invariance):不管检测对象出现在图像中的哪个位置,神经网络的前面几层应该对相同的图像区域具有相似的反应,即为“平移不变性”。
  2. 局部性(locality):神经网络的前面几层应该只探索输入图像中的局部区域,而不过度在意图像中相隔较远区域的关系,这就是“局部性”原则。最终,可以聚合这些局部特征,以在整个图像级别进行预测。

让我们看看这些原则是如何转化为数学表示的。

1.2 多层感知机的限制 (卷积是改进版)

首先,多层感知机的输入是二维图像𝐗,其隐藏表示𝐇在数学上是一个矩阵,在代码中表示为二维张量。 其中𝐗和𝐇具有相同的形状。 为了方便理解,我们可以认为,无论是输入还是隐藏表示都拥有空间结构。

使用[𝐗]𝑖,𝑗和[𝐇]𝑖,𝑗分别表示输入图像和隐藏表示中位置(𝑖,𝑗)处的像素。 为了使每个隐藏神经元都能接收到每个输入像素的信息,我们将参数从权重矩阵(如同我们先前在多层感知机mlp中所做的那样)替换为四阶权重张量𝖶。假设𝐔包含偏置参数,我们可以将全连接层形式化地表示为

7544a6b780684e1c9ee25ebb95779dca.png

(笔记:这里相当于是重写了全连接层,并限制输入X和输出H都是二维的)

(笔记:隐藏表示,mlp中提到过,是隐藏层的输出H;这里讲的是全连接的限制-权重W太大难算起来很难)

(笔记:W的形状是i×j×k×l四阶张量,其中k×l是输入的形状,i×j是输出形状,但这里给出的(k,l)是某个输入像素的位置,(i,j)是某个输出神经元的位置)

(笔记:基于(k,l)求和,相当于每个神经元都会遍历一遍形状为k×l的输入X)

其中,从𝖶𝑊到𝖵𝑉的转换只是形式上的转换,因为在这两个四阶张量的元素之间存在一一对应的关系。 我们只需重新索引下标(𝑘,𝑙),使𝑘=𝑖+𝑎、𝑙=𝑗+𝑏,由此可得[𝖵]𝑖,𝑗,𝑎,𝑏=[𝖶]𝑖,𝑗,𝑖+𝑎,𝑗+𝑏。 索引𝑎和𝑏通过在正偏移和负偏移之间移动覆盖了整个图像。 对于隐藏表示中任意给定位置(𝑖,𝑗)处的像素值[𝐇]𝑖,𝑗,可以通过在𝑥中以(𝑖,𝑗)为中心对像素进行加权求和得到,加权使用的权重为[𝖵]𝑖,𝑗,𝑎,𝑏。

(笔记:这里的a和b像是在给每个神经元(i,j)划定输入的框框)

1.2.1 改进1:平移不变性

现在引用上述的第一个原则:平移不变性。 这意味着检测对象在输入𝐗中的平移,应该仅导致隐藏表示𝐇中的平移。也就是说,𝖵和𝐔实际上不依赖于(𝑖,𝑗)的值,即[𝖵]𝑖,𝑗,𝑎,𝑏=[𝐕]𝑎,𝑏。并且𝐔是一个常数,比如𝑢。因此,我们可以简化𝐇定义为:

9fa381436bea4f97ac97f1aa57ccd50a.png

(笔记:相当比全连接MLP中每个神经元都与上一层的所有神经元相连,卷积核𝐕只关注图像的一小部分区域,通过在整个图像上滑动,提取不同位置的局部特征;[𝖵]𝑖,𝑗,𝑎,𝑏=[𝐕]𝑎,𝑏中舍去的i,j就是在把全连接转换为“局部连接”)

这就是卷积(convolution)。我们是在使用系数[𝐕]𝑎,𝑏对位置(𝑖,𝑗)附近的像素(𝑖+𝑎,𝑗+𝑏)进行加权得到[𝐇]𝑖,𝑗。 注意,[𝐕]𝑎,𝑏的系数比[𝖵]𝑖,𝑗,𝑎,𝑏少很多,因为前者不再依赖于图像中的位置。这就是显著的进步!

1.2.2 改进2:局部性

现在引用上述的第二个原则:局部性。如上所述,为了收集用来训练参数[𝐇]𝑖,𝑗的相关信息,我们不应偏离到距(𝑖,𝑗)很远的地方。这意味着在|𝑎|>Δ或|𝑏|>Δ|的范围之外,我们可以设置[𝐕]𝑎,𝑏=0。因此,我们可以将[𝐇]𝑖,𝑗重写为

4613eb6f671841b28047cbb678f07709.png

:eqlabel:eq_conv-layer

简而言之, :eqref:eq_conv-layer是一个卷积层(convolutional layer),而卷积神经网络是包含卷积层的一类特殊的神经网络。 在深度学习研究社区中,𝐕被称为卷积核(convolution kernel)或者滤波器(filter),亦或简单地称之为该卷积层的权重,通常该权重是可学习的参数。 当图像处理的局部区域很小时,卷积神经网络与多层感知机的训练差异可能是巨大的:以前,多层感知机可能需要数十亿个参数来表示网络中的一层,而现在卷积神经网络通常只需要几百个参数,而且不需要改变输入或隐藏表示的维数。 参数大幅减少的代价是,我们的特征现在是平移不变的,并且当确定每个隐藏活性值时,每一层只包含局部的信息。 以上所有的权重学习都将依赖于归纳偏置。当这种偏置与现实相符时,我们就能得到样本有效的模型,并且这些模型能很好地泛化到未知数据中。 但如果这偏置与现实不符时,比如当图像不满足平移不变时,我们的模型可能难以拟合我们的训练数据。

1.3 卷积(花书直接从这里开讲)

在进一步讨论之前,我们先简要回顾一下为什么上面的操作被称为卷积。在数学中,两个函数(比如𝑓,𝑔:ℝ𝑑→ℝ)之间的“卷积”被定义为

27a24b4bc55143a9a497d394228ea717.png

也就是说,卷积是当把一个函数“翻转”并移位𝐱时,测量𝑓和𝑔之间的重叠。当为离散对象时,积分就变成求和。

(笔记:二次函数定积分的几何意义就是求面积,而且面积有正负之分)

(笔记:𝐱是函数的输入-比如图片像素的位置;𝐳是个变量-卷积核中的对应像素位置)

例如,对于由索引为𝑍的、平方可和的、无限维向量集合中抽取的向量,我们得到以下定义:

506515a2c79646998c4ed99190521d1e.png

对于二维张量,则为𝑓的索引(𝑎,𝑏)和𝑔的索引(𝑖−𝑎,𝑗−𝑏)上的对应加和:

b17b0239f9a446e1adb0a261b1da8241.png

:eqlabel:eq_2d-conv-discrete

这看起来类似于 :eqref:eq_conv-layer,但有一个主要区别:这里不是使用(𝑖+𝑎,𝑗+𝑏),而是使用差值。然而,这种区别是表面的,因为我们总是可以匹配 :eqref:eq_conv-layer和 :eqref:eq_2d-conv-discrete之间的符号。我们在 :eqref:eq_conv-layer中的原始定义更正确地描述了互相关(cross-correlation),这个问题将在下一节中讨论。

1.4 “沃尔多在哪里”回顾

回到上面的“沃尔多在哪里”游戏,让我们看看它到底是什么样子。卷积层根据滤波器𝐕选取给定大小的窗口,并加权处理图片,如 :numref:fig_waldo_mask中所示。我们的目标是学习一个模型,以便探测出在“沃尔多”最可能出现的地方。

6737f5c587f0465abec8cae98050510d.png

:width:400px :label:fig_waldo_mask

1.4.1 通道(第4节会细讲)

:label:subsec_why-conv-channels

然而这种方法有一个问题:我们忽略了图像一般包含三个通道/三种原色(红色、绿色和蓝色)。 实际上,图像不是二维张量,而是一个由高度、宽度和颜色组成的三维张量,比如包含1024×1024×3个像素。 前两个轴与像素的空间位置有关,而第三个轴可以看作每个像素的多维表示。 因此,我们将𝖷索引为[𝖷]𝑖,𝑗,𝑘。由此卷积相应地调整为[𝖵]𝑎,𝑏,𝑐,而不是[𝐕]𝑎,𝑏。

此外,由于输入图像是三维的,我们的隐藏表示𝖧也最好采用三维张量。 换句话说,对于每一个空间位置,我们想要采用一组而不是一个隐藏表示。这样一组隐藏表示可以想象成一些互相堆叠的二维网格。 因此,我们可以把隐藏表示想象为一系列具有二维张量的通道(channel)。 这些通道有时也被称为特征映射(feature maps),因为每个通道都向后续层提供一组空间化的学习特征。 直观上可以想象在靠近输入的底层,一些通道专门识别边缘,而一些通道专门识别纹理。

为了支持输入𝖷和隐藏表示𝖧中的多个通道,我们可以在𝖵中添加第四个坐标,即[𝖵]𝑎,𝑏,𝑐,𝑑。

综上所述,

c5aed498a3cf4c2ab447c8309f8f08db.png

:eqlabel:eq_conv-layer-channels

其中隐藏表示𝖧中的索引𝑑表示输出通道,而随后的输出将继续以三维张量𝖧作为输入进入下一个卷积层。 所以, :eqref:eq_conv-layer-channels可以定义具有多个通道的卷积层,而其中𝖵是该卷积层的权重。

然而,仍有许多问题亟待解决。 例如,图像中是否到处都有存在沃尔多的可能?如何有效地计算输出层?如何选择适当的激活函数?为了训练有效的网络,如何做出合理的网络设计选择?我们将在本章的其它部分讨论这些问题。

1.5 小结

  • 图像的平移不变性使我们以相同的方式处理局部图像,而不在乎它的位置。
  • 局部性意味着计算相应的隐藏表示只需一小部分局部图像像素。
  • 在图像处理中,卷积层通常比全连接层需要更少的参数,但依旧获得高效用的模型。
  • 卷积神经网络(CNN)是一类特殊的神经网络,它可以包含多个卷积层。
  • 多个输入和输出通道使模型在每个空间位置可以获取图像的多方面特征。

2. 图像卷积-代码实现(第2节)

:label:sec_conv_layer

上节我们解析了卷积层的原理,现在我们看看它的实际应用。由于卷积神经网络的设计是用于探索图像数据,本节我们将以图像为例。

2.1 互相关运算 (核心)

严格来说,卷积层是个错误的叫法,因为它所表达的运算其实是互相关运算(cross-correlation),而不是卷积运算。 根据 :numref:sec_why-conv中的描述,在卷积层中,输入张量和核张量通过(互相关运算)产生输出张量。

首先,我们暂时忽略通道(第三维)这一情况,看看如何处理二维图像数据和隐藏表示。在 :numref:fig_correlation中,输入是高度为3、宽度为3的二维张量(即形状为3×3)。卷积核的高度和宽度都是2,而卷积核窗口(或卷积窗口)的形状由内核的高度和宽度决定(即2×2)。

71b43b00b0aa4f65b471b0753c76ffcf.png

:label:fig_correlation

在二维互相关运算中,卷积窗口从输入张量的左上角开始,从左到右、从上到下滑动。

(动图是三维互相关,和本书的例子不太一样,输入是5×5,核K与输出H都是3×3的,仅用来方便理解卷积窗口“滑动”的概念)

bb8ff9a018b4488c87bea451a9e85c28.gif

当卷积窗口滑动到新一个位置时,包含在该窗口中的部分张量与卷积核张量进行按元素相乘,得到的张量再求和得到一个单一的标量值,由此我们得出了这一位置的输出张量值。 在如上例子中,输出张量的四个元素由二维互相关运算得到,这个输出高度为2、宽度为2,如下所示:

0×0+1×1+3×2+4×3=19,

1×0+2×1+4×2+5×3=25,

3×0+4×1+6×2+7×3=37,

4×0+5×1+7×2+8×3=43.

3787af148d4a47cfafcb7e896fac3323.png

笔记:输出隐藏层H的宽w,就是卷积核窗口能在输入图像里头横向滑动“档位”数

这是因为我们需要足够的空间在图像上“移动”卷积核。稍后,我们将看到如何通过在图像边界周围填充零来保证有足够的空间移动卷积核,从而保持输出大小不变。 接下来,我们在corr2d函数中实现如上过程,该函数接受输入张量X和卷积核张量K,并返回输出张量Y

In [1]:

import torch
from torch import nn
from d2l import torch as d2l

In [2]:

def corr2d(X, K):  #@save  # 手撕卷积、底层代码
    """计算二维互相关运算"""  # 卷积
    h, w = K.shape  # 将输入的卷积核K的高h和宽w存下来
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))  # 初始化输出;行数是输入图片的高X.shape[0]
    for i in range(Y.shape[0]):  # shape[0]是最外层层数,在这里指的是行数
        for j in range(Y.shape[1]):  # j是列索引
            Y[i, j] = (X[i:i + h, j:j + w] * K).sum()  # “:”是容器切片;把小方块拿出来与核K内积/点乘;
    return Y  # Y[i, j]设计得很妙, 是二维数组Y索引, 把每次点乘的结果放到输出数组Y中对应的位置[i,j]

通过 :numref:fig_correlation的输入张量X和卷积核张量K,我们来[验证上述二维互相关运算的输出]。

In [3]:

X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
corr2d(X, K)  # 输出元素=4,说明小方块滑动了4次

Out[3]:

tensor([[19., 25.],
        [37., 43.]])

2.2 卷积层 (重点)

卷积层对输入和卷积核权重进行互相关运算,并在添加标量偏置之后产生输出。 所以,卷积层中的两个被训练的参数是卷积核权重和标量偏置。 就像我们之前随机初始化全连接层一样,在训练基于卷积层的模型时,我们也随机初始化卷积核权重。

基于上面定义的corr2d函数[实现二维卷积层]。在__init__构造函数中,将weightbias声明为两个模型参数。前向传播函数调用corr2d函数并添加偏置。

In [4]:

class Conv2D(nn.Module): # 定义卷积层+前向传播

    def __init__(self, kernel_size):
        super().__init__()  # 用于调用父类(在这里是nn.Module)的构造方法,如自动初始化
        self.weight = nn.Parameter(torch.rand(kernel_size))  # 将卷积核权重矩阵(变量)添加到模型的参数列表中
        self.bias = nn.Parameter(torch.zeros(1))  # 初始化偏置,和上一行一样
        #  使用nn.Parameter包装的张量会被自动添加到模型的参数列表中(可以通过model.parameters()方法获取)
        #  在训练过程中,优化器会自动遍历模型的参数列表,计算梯度并更新这些参数
​
    def forward(self, x):  # 输入2D图像x,进行前向运算
        return corr2d(x, self.weight) + self.bias  # 和卷积核K互信息计算(内积)一下,再加上个偏置

高度和宽度分别为ℎ和𝑤的卷积核可以被称为ℎ×𝑤卷积或ℎ×𝑤卷积核。 我们也将带有ℎ×𝑤卷积核的卷积层称为ℎ×𝑤卷积层。

2.3 图像中目标的边缘检测

d3cbe4314aba4e01a79f927b8ae32940.png

  • 不同的卷积核,会有不同的输出效果

如下是[卷积层的一个简单应用:]通过找到像素变化的位置,来(检测图像中不同颜色的边缘)。 首先,我们构造一个6×8像素的黑白图像。中间四列为黑色(0),其余像素为白色(1)。

In [5]:

X = torch.ones((6, 8))

X[:, 2:6] = 0  # 索引X中的列,注意“2”是从0开始数列第三列,包括2但不到6
X

Out[5]:

tensor([[1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.],
        [1., 1., 0., 0., 0., 0., 1., 1.]])

接下来,我们构造一个高度为11、宽度为22的卷积核K。当进行互相关运算时,如果水平相邻的两元素相同,则输出为零,否则输出为非零。

In [6]:

K = torch.tensor([[1.0, -1.0]])

现在,我们对参数X(输入)和K(卷积核)执行互相关运算。 如下所示,[输出Y中的1代表从白色到黑色的边缘,-1代表从黑色到白色的边缘],其他情况的输出为00。

In [7]:

Y = corr2d(X, K)

Y

Out[7]:

tensor([[ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.],
        [ 0.,  1.,  0.,  0.,  0., -1.,  0.]])

现在我们将输入的二维图像转置,再进行如上的互相关运算。 其输出如下,之前检测到的垂直边缘消失了。 不出所料,这个[卷积核K只可以检测垂直边缘],无法检测水平边缘。

In [8]:

corr2d(X.t(), K) # .t()是将Tensor进行转置

Out[8]:

tensor([[0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.]])

2.4 学习卷积核 (更新权重参数)

如果我们只需寻找黑白边缘,那么以上[1, -1]的边缘检测器足以。然而,当有了更复杂数值的卷积核,或者连续的卷积层时,我们不可能手动设计滤波器。那么我们是否可以[学习由X生成Y的卷积核]呢?

现在让我们看看是否可以通过仅查看“输入-输出”对来学习由X生成Y的卷积核。 我们先构造一个卷积层,并将其卷积核初始化为随机张量。接下来,在每次迭代中,我们比较Y与卷积层输出的平方误差,然后计算梯度来更新卷积核。为了简单起见,我们在此使用内置的二维卷积层,并忽略偏置。

In [9]:

# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核

conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)  # 之前咱定义的是输入二阶张量,nn.Conv2d得输入四阶
​
# 这个二维卷积层使用四维输入和输出格式(批量大小、通道数、高度、宽度),
# 其中批量大小和通道数都为1(这里只是简介,先不展开讲)
X = X.reshape((1, 1, 6, 8))  # 批量维:就是样本数;通道维:RGB图是3通道,灰度图是1(单)通道
Y = Y.reshape((1, 1, 6, 7))  # 这里的输出Y少了一列,是因为卷积核列数是2,横向滑动次数比原图列数少1
lr = 3e-2  # 学习率
​
for i in range(10):  # epoch=10,迭代10轮
    Y_hat = conv2d(X)  # 前向计算后的输出,存下计算图
    l = (Y_hat - Y) ** 2  # 用均方误差作为损失,( 输出Y_hat - 输入Y )的平方
    conv2d.zero_grad()  # 清除梯度
    l.sum().backward()  # 计算每个卷积核(权重)的梯度后,求和不能少,求和能化每个权重矩阵为标量,张量
    # 迭代卷积核;对比optimizer.step()来自动更新参数,这里相当于手撕更新卷积核(权重)参数的源代码
    conv2d.weight.data[:] -= lr * conv2d.weight.grad  # 使用[:]才能修改的是原本的核,避免创建新的核对象
    if (i + 1) % 2 == 0:
        print(f'epoch {i+1}, loss {l.sum():.3f}')
epoch 2, loss 20.416
epoch 4, loss 6.979
epoch 6, loss 2.626
epoch 8, loss 1.037
epoch 10, loss 0.418

在10次迭代之后,误差已经降到足够低。现在我们来看看我们[所学的卷积核的权重张量]。

In [10]:

conv2d.weight.data.reshape((1, 2))

Out[10]:

tensor([[ 1.0540, -0.9211]])

细心的读者一定会发现,我们学习到的卷积核权重非常接近我们之前定义的卷积核K

2.5 互相关和卷积 (补充)

回想一下我们在 :numref:sec_why-conv中观察到的互相关和卷积运算之间的对应关系。 为了得到正式的卷积运算输出,我们需要执行 :eqref:eq_2d-conv-discrete中定义的严格卷积运算,而不是互相关运算。 幸运的是,它们差别不大,我们只需水平和垂直翻转二维卷积核张量,然后对输入张量执行互相关运算。

值得注意的是,由于卷积核是从数据中学习到的,因此无论这些层执行严格的卷积运算还是互相关运算,卷积层的输出都不会受到影响。 为了说明这一点,假设卷积层执行互相关运算并学习 :numref:fig_correlation中的卷积核,该卷积核在这里由矩阵𝐊表示。 假设其他条件不变,当这个层执行严格的卷积时,学习的卷积核𝐊′在水平和垂直翻转之后将与𝐊相同。 也就是说,当卷积层对 :numref:fig_correlation中的输入和𝐊′执行严格卷积运算时,将得到与互相关运算 :numref:fig_correlation中相同的输出。

为了与深度学习文献中的标准术语保持一致,我们将继续把“互相关运算”称为卷积运算,尽管严格地说,它们略有不同。 此外,对于卷积核张量上的权重,我们称其为元素

2.6 特征映射和感受野 (补充)

如在 :numref:subsec_why-conv-channels中所述, :numref:fig_correlation中输出的卷积层有时被称为特征映射(feature map),因为它可以被视为一个输入映射到下一层的空间维度的转换器。 在卷积神经网络中,对于某一层的任意元素𝑥,其感受野(receptive field)是指在前向传播期间可能影响𝑥计算的所有元素(来自所有先前层)。

请注意,感受野可能大于输入的实际大小。让我们用 :numref:fig_correlation为例来解释感受野: 给定2×2卷积核,阴影输出元素值19的感受野是输入阴影部分的四个元素。 假设之前输出为𝐘,其大小为2×2,现在我们在其后附加一个卷积层,该卷积层以𝐘为输入,输出单个元素𝑧。 在这种情况下,𝐘上的𝑧的感受野包括𝐘的所有四个元素,而输入的感受野包括最初所有九个输入元素。 因此,当一个特征图中的任意元素需要检测更广区域的输入特征时,我们可以构建一个更深的网络。

2.7 一维和三维 (2D的补充)

e483670bc1d74e96ba0bd48d96d35c0d.png

2.8 小结

  • 二维卷积层的核心计算是二维互相关运算。最简单的形式是,对二维输入数据和卷积核执行互相关操作,然后添加一个偏置。
  • 我们可以设计一个卷积核来检测图像的边缘。
  • 我们可以从数据中学习卷积核的参数。
  • 学习卷积核时,无论用严格卷积运算或互相关运算,卷积层的输出不会受太大影响。
  • 当需要检测输入特征中更广区域时,我们可以构建一个更深的卷积网络。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐