🐡
type
status
date
slug
summary
tags
category
icon
password
Property
深度学习框架会在后端自动构建计算图。利用计算图,系统可以了解所有依赖关系,并且可以选择性地并行执行多个不相互依赖的任务以提高速度。
通常情况下单个操作符将使用所有CPU或单个GPU上的所有计算资源。例如,即使在一台机器上有多个CPU处理器,
dot
操作符也将使用所有CPU上的所有核心(和线程)。这样的行为同样适用于单个GPU。因此,并行化对于单设备计算机来说并不是很有用,而并行化对于多个设备就很重要了。虽然并行化通常应用在多个GPU之间,但增加本地CPU以后还将提高少许性能。例如,Hadjis.Zhang.Mitliagkas.ea.2016
则把结合GPU和CPU的训练应用到计算机视觉模型中。借助自动并行化框架的便利性,可以依靠几行Python代码实现相同的目标。更广泛地考虑,这里对自动并行计算的讨论主要集中在使用CPU和GPU的并行计算上,以及计算和通信的并行化内容。基于GPU的并行计算
从定义一个具有参考性的用于测试的工作负载开始:下面的
run
函数将执行次“矩阵-矩阵”乘法时需要使用的数据分配到两个变量(x_gpu1
和x_gpu2
)中,这两个变量分别位于不同设备上。通过在测量之前预热设备(对设备执行一次传递)来确保缓存的作用不影响最终的结果。
torch.cuda.synchronize()
函数将会等待一个CUDA设备上的所有流中的所有核心的计算完成。函数接受一个device
参数,代表是哪个设备需要同步。如果device参数是None
(默认值),它将使用current_device()
找出的当前设备。如果删除两个任务之间的
synchronize
语句,系统就可以在两个设备上自动实现并行计算。🐡
type
status
date
slug
summary
tags
category
icon
password
Property
很好地理解算法和模型才可以捕获统计方面的问题,构建出具有出色性能的系统。同时,至少对底层硬件有一定的了解也是必不可少的。一个好的设计可以很容易地在性能上造就数量级的差异,这也是后续产生的能够训练网络(例如,训练时间为 周)和无法训练网络(训练时间为 个月,导致错过截止期)之间的差异。
计算机
大多数深度学习研究者和实践者都可以使用一台具有相当数量的内存、计算资源、某种形式的加速器(如一个或者多个GPU)的计算机,计算机由以下关键部件组成:
- 一个处理器(CPU),它除了能够运行操作系统和许多其他功能之外,还能够执行给它的程序,通常由个或更多个核心组成。
- 内存(随机访问存储,RAM)用于存储和检索计算结果,如权重向量和激活参数,以及训练数据。
🐳
type
status
date
slug
summary
tags
category
icon
password
Property
DNN局限性
DNN十分适合处理表格数据,其中行对应样本,列对应特征。 对于表格数据,我们寻找的模式可能涉及特征之间的交互,但是不能预先假设任何与特征交互相关的先验结构。 此时,DNN可能是最好的选择,然而对于高维感知数据,这种缺少结构的网络可能会变得不实用。
假设有一个足够充分的照片数据集,数据集中是拥有标注的照片,每张照片具有百万级像素,这意味着网络的每次输入都有一百万个维度。 即使将隐藏层维度降低到1000,这个全连接层也将有 个参数。 想要训练这个模型将不可实现,因为需要有大量的GPU、分布式优化训练的经验和超乎常人的耐心。此外,拟合如此多的参数还需要收集大量的数据。 然而,如今人类和机器都能很好地区分猫和狗:这是因为图像中本就拥有丰富的结构,而这些结构可以被人类和机器学习模型使用。 卷积神经网络是机器学习利用自然图像中一些已知结构的创造性方法。
空间不变性
想象一下,假设你想从一张图片中找到某个物体。 合理的假设是:无论哪种方法找到这个物体,都应该和物体的位置无关。 理想情况下,系统应该能够利用常识:猪通常不在天上飞,飞机通常不在水里游泳。 但是,如果一只猪出现在图片顶部,我们还是应该认出它。
可以从儿童游戏”沃尔多在哪里”中得到灵感: 在这个游戏中包含了许多充斥着活动的混乱场景,而沃尔多通常潜伏在一些不太可能的位置,我们的目标就是找出他。 尽管沃尔多的装扮很有特点,但是在眼花缭乱的场景中找到他也如大海捞针。 然而沃尔多的样子并不取决于他潜藏的地方,因此可以使用一个“沃尔多检测器”扫描图像。 该检测器将图像分割成多个区域,并为每个区域包含沃尔多的可能性打分。 卷积神经网络正是将空间不变性(spatial invariance)的这一概念系统化,从而基于这个模型使用较少的参数来学习有用的表示。
将上述想法总结一下,从而帮助我们设计适合于计算机视觉的神经网络架构:
🐳
type
status
date
slug
summary
tags
category
icon
password
Property
有时,在应用了连续的卷积之后,最终得到的输出远小于输入大小。这是由于卷积核的宽度和高度通常大于所导致的。比如,一个 像素的图像,经过层 的卷积后,将减少到像素。如此一来,原始图像的边界丢失了许多有用信息。而填充是解决此问题最有效的方法。 有时,我们可能希望大幅降低图像的宽度和高度,例如原始的输入分辨率十分冗余,步幅则可以在这类情况下提供帮助。
填充
由于通常使用小卷积核,对于任何单个卷积可能只会丢失几个像素。 但随着应用许多连续卷积层,累积丢失的像素数就多了。 解决这个问题的简单方法即为填充(padding):在输入图像的边界填充元素(通常填0)。
例如,在图中将 输入填充到,那么输出就增加为
如果添加行填充(大约一半在顶部,一半在底部)和列填充(左侧大约一半,右侧一半),则输出形状将为:
输出的高度和宽度将分别增加 和
在许多情况下,我们需要设置 和 ,使输入和输出具有相同的高度和宽度,这样可以在构建网络时更容易地预测每个图层的输出形状。
🐳
type
status
date
slug
summary
tags
category
icon
password
Property
一般来说,一维卷积用于文本数据,二维卷积用于图像数据,对宽度和高度都进行卷积,三维卷积用于视频及3D图像处理领域(检测动作及人物行为),对立方体的三个面进行卷积 。
一维卷积Conv1d
一维卷积实质是对一个词向量做卷积,如下所示:
- 图中的输入的数据维度为8,过滤器的维度为5。卷积后输出的数据维度为8−5+1=4
- 如果过滤器数量仍为1,输入数据的channel数量变为16,则输入数据维度为8×16
- 一维卷积常用于序列模型,自然语言处理领域。
torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
Pytorch中
nn.Conv1d
卷积运算要求输入源是3维,输入源的三个维度分别是:第一个维度代表每个序列的个数即样本数,第二个维度代表每一个序列的通道数,第三个维度代表这个词向量序列,如下所示:🐳
type
status
date
slug
summary
tags
category
icon
password
Property
我们一般可以通过卷积操作来实现高维特征到低维特征的转换.比如在一维卷积中,一个5 维的输入特征,经过一个大小为3 的卷积核,其输出为3 维特征。如果设置步长大于1,可以进一步降低输出特征的维数。但在一些任务中,我们需要将低维特征映射到高维特征,并且依然希望通过卷积操作来实现。
我们将低维特征映射到高维特征的卷积操作称为转置卷积,也称为反卷积。在卷积网络中,卷积层的前向计算和反向传播也是一种转置关系。
基本操作
从基本的转置卷积开始,设步幅为1且没有填充。 假设有一个的卷积核。 以步幅为1滑动卷积核窗口,每行 次,每列次,共产生个中间结果。 每个中间结果都是一个 的张量,初始化为0。 为了计算每个中间张量,输入张量中的每个元素都要乘以卷积核,从而使所得的张量替换中间张量的一部分。 请注意,每个中间张量被替换部分的位置与输入张量中元素的位置相对应。 最后,所有中间结果相加以获得最终结果。
可以对输入矩阵
X
和卷积核矩阵K
实现基本的转置卷积运算trans_conv
🐳
type
status
date
slug
summary
tags
category
icon
password
Property
对于一个卷积层,如果希望增加输出单元的感受野,一般可以通过三种方式实现:
- 增加卷积核的大小
- 增加层数,比如两层3 × 3 的卷积可以近似一层5 × 5 卷积的效果
- 在卷积之前进行汇聚操作.前两种方式会增加参数数量,而第三种方式会丢失一些信息
空洞卷积(Atrous Convolution)是一种不增加参数数量,同时增加输出单元感受野的一种方法,也称为膨胀卷积(Dilated Convolution)。空洞卷积通过给卷积核插入“空洞”来变相地增加其大小。如果在卷积核的每两个元素之间插入𝐷 − 1 个空洞,卷积核的有效大小为
其中𝐷称为膨胀率(Dilation Rate),当𝐷 = 1 时卷积核为普通的卷积核
🐳
type
status
date
slug
summary
tags
category
icon
password
Property
处理图像时,我们希望逐渐降低隐藏表示的空间分辨率、聚集信息,这样随着在神经网络中层叠的上升,每个神经元对其敏感的感受野(输入)就越大。而机器学习任务通常会跟全局图像的问题有关(例如,“图像是否包含一只猫呢?”),所以最后一层的神经元应该对整个输入的全局敏感。通过逐渐聚合信息,生成越来越粗糙的映射,最终实现学习全局表示的目标,同时将卷积图层的所有优势保留在中间层。
此外,当检测较底层的特征时(例如边缘),我们通常希望这些特征保持某种程度上的平移不变性。例如,如果我们拍摄黑白之间轮廓清晰的图像
X
,并将整个图像向右移动一个像素,即Z[i, j] = X[i, j + 1]
,则新图像Z
的输出可能大不相同。而在现实中,随着拍摄角度的移动,任何物体几乎不可能发生在同一像素上。即使用三脚架拍摄一个静止的物体,由于快门的移动而引起的相机振动,可能会使所有物体左右移动一个像素(除了高端相机配备了特殊功能来解决这个问题)。池化(pooling)层,它具有双重目的:
最大池化层和平均池化层
与卷积层类似,池化层运算符由一个固定形状的窗口组成,该窗口根据其步幅大小在输入的所有区域上滑动,为固定形状窗口(有时称为池化窗口)遍历的每个位置计算一个输出。 然而,不同于卷积层中的输入与卷积核之间的互相关计算,池化层不包含参数。 相反,池运算是确定性的,我们通常计算池化窗口中所有元素的最大值或平均值。这些操作分别称为最大池化层(maximum pooling)和平均池化层(average pooling)
在这两种情况下,与互相关运算符一样,池化窗口从输入张量的左上角开始,从左往右、从上往下的在输入张量内滑动。在池化窗口到达的每个位置,它计算该窗口中输入子张量的最大值或平均值。计算最大值或平均值是取决于使用了最大池化层还是平均池化层
下面这个例子采用取最大值的池化方法。同时采用的是2x2的池化。步幅为2。
首先对红色2x2区域进行池化,由于此2x2区域的最大值为6,那么对应的池化输出位置的值为6,由于步幅为2,此时移动到绿色的位置去进行池化,输出的最大值为8。同样的方法,可以得到黄色区域和蓝色区域的输出值。最终输入4x4的矩阵在池化后变成了2x2的矩阵,进行了压缩。
🐳
type
status
date
slug
summary
tags
category
icon
password
Property
CNN的基本结构
一个常见的CNN例子如下图:
图中是一个图形识别的CNN模型。可以看出最左边的船的图像就是我们的输入层,计算机理解为输入若干个矩阵,这点和DNN基本相同。
接着是卷积层(Convolution Layer),这个是CNN特有的,卷积层的激活函数使用的是ReLU。在卷积层后面是池化层(Pooling layer),这个也是CNN特有的。需要注意的是,池化层没有激活函数。
卷积层+池化层的组合可以在隐藏层出现很多次,上图中出现两次。而实际上这个次数是根据模型的需要而来的。当然也可以灵活使用使用卷积层+卷积层,或者卷积层+卷积层+池化层的组合,这些在构建模型的时候没有限制。但是最常见的CNN都是若干卷积层+池化层的组合,如上图中的CNN结构。
在若干卷积层+池化层后面是全连接层(Fully Connected Layer, 简称FC),全连接层其实就是DNN结构,只是输出层使用了Softmax激活函数来做图像识别的分类。
从上面CNN的模型描述可以看出,CNN相对于DNN,比较特殊的也就是是卷积层和池化层。
用一个彩色的汽车样本的图像识别直观的看下CNN的结构。图中的CONV即为卷积层,POOL即为池化层,而FC即为DNN全连接层,包括了最后的用Softmax激活函数的输出层。