前言:
本篇内容记录笔者学习深度学习的学习过程,如果你有任何想询问的问题,欢迎在以下任何平台提问!
参考书:《动手学深度学习》
Bilibili:space.bilibili.com/57089326
从全连接层到卷积:
声明:知乎落雨乄天珀夜的水印是我本人的。
- 图像的平移不变性使我们以相同的方式处理局部图像,而不在乎它的位置。
- 局部性意味着计算相应的隐藏表示只需一小部分局部图像像素。
- 在图像处理中,卷积层通常比全连接层需要更少的参数,但依旧获得高效用的模型。
- 卷积神经网络(CNN)是一类特殊的神经网络,它可以包含多个卷积层。
- 多个输入和输出通道使模型在每个空间位置可以获取图像的多方面特征。
图像卷积:
互相关运算:
卷积神经网络的设计更多的用于图像数据,
而严格来说,”卷积”这个词用的有点问题,事实上,它所做的运算是互相关运算而非卷积运算。
在卷积层中,输入张量和核张量通过互相关运算产生输出张量。
我们以一个例子来说明,话不多说,上图:
卷积层和卷积核的区别:
- 卷积层是深度神经网络中的一种基本层级结构,其目的是从输入数据中提取有用的特征。
- 卷积层由多个卷积核组成,每个卷积核用于对输入数据进行卷积操作,从而生成输出特征图。
卷积核是卷积层中的一个重要参数,它定义了卷积操作的形式和卷积层的特征提取能力。
卷积核通常是一个小的、固定大小的矩阵,可以视为卷积运算中的滤波器。
卷积核中的每个元素都具有一定的权重,用于控制对输入数据中不同位置的响应。
在具体操作中,卷积层对输入和卷积核权重进行互相关运算,并在添加标量偏置之后产生输出。
图像中目标的边缘检测:
通过找到像素变化的位置,来检测图像中不同颜色的边缘。
举个例子(例子来源于《动手学深度学习》):
X = torch.ones((6, 8))
X[:, 2:6] = 0
X
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.]])
我们构造一个高度为1、宽度为2的卷积核K
。
当进行互相关运算时,如果水平相邻的两元素相同,则输出为零,否则输出为非零。
K = torch.tensor([[1.0, -1.0]])
现在,我们对参数X
(输入)和K
(卷积核)执行互相关运算。 如下所示,输出Y
中的1代表从白色到黑色的边缘,-1代表从黑色到白色的边缘,其他情况的输出为0。
Y = corr2d(X, K)
Y
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
只可以检测垂直边缘,无法检测水平边缘。
corr2d(X.t(), K)
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.]])
学习卷积核:
对于更复杂数值的卷积核或者连续的卷积层来说,我们就不太可能去手动设计滤波器了;
这时候就需要通过”学习”来构造适合的卷积核了。
先构造一个卷积层,并将其卷积核初始化为随机张量。
接下来,在每次迭代中,我们比较Y
与卷积层输出的平方误差,然后计算梯度来更新卷积核。
一个例子:
# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核
conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)
# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
# 其中批量大小和通道数都为1
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2 # 学习率
for i in range(10):
Y_hat = conv2d(X)
l = (Y_hat - Y) ** 2
conv2d.zero_grad()
l.sum().backward()
# 迭代卷积核
conv2d.weight.data[:] -= lr * conv2d.weight.grad
if (i + 1) % 2 == 0:
print(f'epoch {i+1}, loss {l.sum():.3f}')
- 二维卷积层的核心计算是二维互相关运算。最简单的形式是,对二维输入数据和卷积核执行互相关操作,然后添加一个偏置。
- 我们可以设计一个卷积核来检测图像的边缘。
- 我们可以从数据中学习卷积核的参数。
- 学习卷积核时,无论用严格卷积运算或互相关运算,卷积层的输出不会受太大影响。
- 当需要检测输入特征中更广区域时,我们可以构建一个更深的卷积网络。
填充和步幅:
填充:
在应用多层卷积时,我们常常丢失边缘像素。
由于我们通常使用小卷积核,因此对于任何单个卷积,我们可能只会丢失几个像素。
但随着我们应用许多连续卷积层,累积丢失的像素数就多了。
解决这个问题的简单方法即为填充(padding):在输入图像的边界填充元素(通常填充元素是0)。
如下例,我们将3×3输入填充到5×5,那么它的输出就增加为4×4:
步幅:
在计算互相关时,卷积窗口从输入张量的左上角开始,向下、向右滑动。
在前面的例子中,我们默认每次滑动一个元素。
但是,有时候为了高效计算或是缩减采样次数,卷积窗口可以跳过中间位置,每次滑动多个元素。
我们将每次滑动元素的数量称为步幅(stride)。
- 填充可以增加输出的高度和宽度。这常用来使输出与输入具有相同的高和宽。
- 步幅可以减小输出的高和宽,例如输出的高和宽仅为输入的高和宽的1/n1/n(n是一个大于1的整数)。
- 填充和步幅可用于有效地调整数据的维度。
多输入多输出通道:
多输入通道:
当输入包含多个通道时,需要构造一个与输入数据具有相同输入通道数的卷积核,以便与输入数据进行互相关运算。
多输出通道:
在最流行的神经网络架构中,随着神经网络层数的加深,我们常会增加输出通道的维数,通过减少空间分辨率以获得更大的通道深度。
直观地说,我们可以将每个通道看作对不同特征的响应。
而现实可能更为复杂一些,因为每个通道不是独立学习的,而是为了共同使用而优化的。
因此,多输出通道并不仅是学习多个单通道的检测器。
- 多输入多输出通道可以用来扩展卷积层的模型。
- 当以每像素为基础应用时,1×1卷积层相当于全连接层。
- 1×1卷积层通常用于调整网络层的通道数量和控制模型复杂性。
池化层:
最大池化层与平均池化层:
池化层,也称汇聚层。
池化层的两个目的:
- 降低卷积层对位置的敏感性;
- 降低对空间降采样表示的敏感性。
与卷积层类似,池化层运算符由一个固定形状的窗口组成,该窗口根据其步幅大小在输入的所有区域上滑动,为固定形状窗口遍历的每个位置计算一个输出。
然而,不同于卷积层中的输入与卷积核之间的互相关计算,池化层不包含参数。
相反,池运算是确定性的,我们通常计算池化窗口中所有元素的最大值或平均值。
这些操作分别称为最大池化层(maximum pooling)和平均池化层(average pooling)。
填充与步幅:
类似地,与卷积层一样,池化层也可以改变输出形状,通过改变填充和步幅。
多个通道:
在处理多通道输入数据时,汇聚层在每个输入通道上单独运算,而不是像卷积层一样在通道上对输入进行汇总。 这意味着汇聚层的输出通道数与输入通道数相同。
- 对于给定输入元素,最大汇聚层会输出该窗口内的最大值,平均汇聚层会输出该窗口内的平均值。
- 汇聚层的主要优点之一是减轻卷积层对位置的过度敏感。
- 我们可以指定汇聚层的填充和步幅。
- 使用最大汇聚层以及大于1的步幅,可减少空间维度(如高度和宽度)。
- 汇聚层的输出通道数与输入通道数相同。
卷积神经网络之——LeNet:
LeNet是一种卷积神经网络,由Yann LeCun等人在1990年代提出,是卷积神经网络的开山鼻祖之一。
LeNet在当时被广泛应用于手写数字识别等任务,并为后来更复杂的卷积神经网络的设计奠定了基础。
虽然LeNet已经相对简单,但其基本的卷积神经网络结构已经被广泛应用于现代深度学习模型中。
因此,LeNet通常也被用作卷积神经网络的统称。
LeNet:
总体来看,LeNet(LeNet-5)由两个部分组成:
- 卷积编码器:由两个卷积层组成;
- 全连接层密集块:由三个全连接层组成。
简化版如下:
- 卷积神经网络(CNN)是一类使用卷积层的网络。
- 在卷积神经网络中,我们组合使用卷积层、非线性激活函数和汇聚层。
- 为了构造高性能的卷积神经网络,我们通常对卷积层进行排列,逐渐降低其表示的空间分辨率,同时增加通道数。
- 在传统的卷积神经网络中,卷积块编码得到的表征在输出之前需由一个或多个全连接层进行处理。
- LeNet是最早发布的卷积神经网络之一。