受益于深度学习,计算机视觉是目前快速发展的领域之一。 深度学习计算机视觉可以帮助自动驾驶汽车判断其周围的其他汽车和行人的位置以躲避他们,帮助面部识别解锁手机,甚至打开门等。 下面列出几个深度学习的计算机视觉问题的例子:
计算机视觉的一个挑战是输入可以任意大。 如果你使用较大的图像 也许这是一个 10001000 像素的图像,输入特征的维度将会是10001000*3,也就是 3 ∗ 1 0 6 3*10^6 3∗106 维。如果用一个标准的或者全连接的网络,假设第一个隐藏层只有 1000 个隐藏的单元,那么权重矩阵 W1 将会是一个 1000 ∗ 3000000 1000*3000000 1000∗3000000 维的矩阵。也就是说 W1 包含 3 ∗ 1 0 9 3*10^9 3∗109 个参数,这个参数数量是非常大的。
这么多的参数会带来两方面的弊端:
但对于计算机视觉应用,你不会想要被限制于使用一个小图像,你想要用清晰的图像获取足够的信息。为了做到这点你需要运用卷积运算,它是卷积神经网络的基础之一 。
在计算机视觉中,神经网络的前几层会检测一些低级特征,例如边缘; 接下来的几层可能会检测对象的某些部分;而更靠后的几层会检测到某些整个对象,比如在此例中的人脸。
如果给你一张这样的图片(下图左),让电脑预测在这张图片中的物体是什么。你做的第一件事可能是检测图片中的垂直边缘,例如图像中垂直的线是栅栏、还有比较垂直的线是这些行人的轮廓 。除此之外,你也许也想要检测水平边缘,比如非常明显的栅栏的横杆。
所以你怎样才能在像这样的图像中检测垂直边缘呢?这里以一个 6x6 的灰度图像为例(下图左)。为了检测这个图像中的垂直边缘,你能做的是建立一个 3x3 的矩阵(下图右),在池化(pooling)过程中,用卷积神经网络中的专业术语它被称为一个过滤器(filter),有时候在科研论文中也会将它称为核(kernel)。
下面我们开始用这个 filter 在原图上做卷积运算:
第一步:将 filter 覆盖在原图左上角的位置,将 filter 中的数值与原图相同位置的像素值相乘,再将得到的 9 个乘积结果相加,最后将最终结果记录在另一个矩阵中。
第二步:将 filter 往右移动一格,将 filter 中的数值与原图相同位置的像素值相乘,再将得到的 9 个乘积结果相加,最后将最终结果记录下来。
以此类推,直到完成对整张图的卷积操作
所以用 3x3 的 filter 对一个 6x6 灰度图像完成一次卷积操作,将得到一个4x4的矩阵,可以把这个卷积的结果理解为另一个图像,这就是一个垂直边缘检测器。
大部分的编程语言都会有自己的方法来完成卷积操作。python中可以用 conv_forward( ),在 TensorFlow 中是 tf.nn.conv2d( ) 函数,而在 Keras 中则是 Conv2D( ) 来实现卷积运算。
在计算机视觉的文献中,对过滤器用哪些数字组合是最好的仍然存在相当大的争议。这里你也可以选择使用别的数字:
Sobel过滤器,这个过滤器的优点在于它给中间行赋予了更大的权重,从而可能使得它更加稳定。
Scharr过滤器。
随着深度学习的发展,我们发现,如果你想要检测一些复杂图片的边界,可能并不需要计算机视觉的研究人员挑选出这9个矩阵元素。你可以把矩阵里的这9个元素当做参数,通过反向传播来学习得到他们的数值。目标是要获得这9个参数,使得对图片用这个过滤器进行卷积能得到一个优良的边界检测器。我们发现神经网络可以学习底层特征得很好,比如边界,甚至比计算机视觉研究人员精心选择的更加稳定。
如果你有一个 n x n 的图片并且想使用一个 f x f 的过滤器 这样输出的维度将会是 (n-f+1) x (n-f+1) 这其实有两个缺陷:
第一个是 如果每一次你使用一个卷积操作,你的图像都会缩小。例如你从 6x6 降维到 4x4 你做不了几次卷积,你的图片就会变得非常小 也许它会缩小到只有1x1或者别的什么 所以也许你并不希望 每次你想检测边界或者其他的特征时,都缩小你的图片 这就是一个缺陷
第二个缺陷是 角落或者边界上的像素被使用的次数少很多 你丢失了许多图片上靠近边界的信息
所以为了同时解决上述的两个问题,你可以填充(pad)图片的边缘。如果 p 是填充的数量,这样输出变成了 (n+2p-f+1) x (n+2p-f+1)
那么这个 p 应该取什么值呢?我们有两个常见的选择,即 valid卷积和 same 卷积
valid卷积 基本上意思是没有填充 因此在这种情况下 当你用一个 fxf 过滤器去卷积一个 nxn 的图片 你会得到一个 (n-f+1) x (n-f+1) 维度的输出 。
same卷积,意思是你选择的填充将使得 输出大小等于输入大小。 当你用p=(f-1)/2个像素填充且f是奇数时,可以保证输出和输入的大小相同。
通常在计算机视觉(computer vision)领域,f 基本上是使用奇数。有两个原因导致这个现象,一是如果f是偶数,会需产生些不对称的填充,其次当你有一个奇数大小的过滤器,比如 3x3 或者 5x5 这样,则可以得到有一个中心位置。有时候在计算机视觉领域 有一个特殊点是很好的,你可以称之为中心像素,这样你就可以描述你过滤器的位置。但是只是约定俗成。
除了一次移动一格(stride = 1),我们还可以一次移动多格(stride = s),下面以步长为 2 举例,7x7 的矩阵在用 3x3 的过滤器完成卷积操作后,得到了一个 3x3 的矩阵。
总结一下经卷积操作后,输出矩阵的维度计算。如果你有一个 n x n 的图像或矩阵,将其填充 p 层元素后,用 f x f 大小的过滤器,以步长为 s 的方式进行卷积,那么输出的矩阵大小为 (n + 2p - f) / s + 1,最后还需用向下取整可以保持结果为整数。
假设你想在这张RGB(红绿蓝)图片中检测特征,则相应的需要使用三通道过滤器。因此,过滤器本身将有对应的三层分别是 红、绿、蓝三个通道。并且,过滤器的通道数目必须和图像中的通道数目相等。这个三通道的过滤器有27个参数,接下来,你要做的是用这个过滤器中的每个数字分别与图像的红,绿,蓝三通道的对应数字相乘,再把所有这些数字相加就能得到你输出结果矩阵中的一个元素。
假如你想检测这种RGB图像里的垂直边缘, 那你可以按照以下的数值设置过滤器:
也可以只对一个通道的图像检测特征,比如想要检测图片里红色通道的垂直边缘, 那你可以按照以下的数值设置过滤器:
如果我们想同时检测垂直边缘和水平边缘, 又或者是45度边缘或者70度边缘, 换句话来说,如果你想要同时应用多个过滤器呢?
这里需要注意两点,第一是不管有几个过滤器,每个过滤器的通道数应该与被卷积图像的通道数相等,第二是有多少个过滤器,卷积结果就有多少个通道。
在卷积神经网络中,一个卷积层需要做哪些工作呢?这里以一个带两个 3x3x3 的过滤器的卷积网络为例。
应用第一个卷积过滤器,我们得到了第一个4x4的输出,最终我们需要把这些输出变成单层卷积神经网络 还需要对这 16个元素添加同样的偏差(bias),这里偏差是一个实数 这里使用的是广播机制,然后我们可以继续进行一些非线性转换ReLU。最终,我们得到一个4x4矩阵输出 。同理第二个卷积层也是一样。
总而言之,在一个卷积层中会经过线性操作计算(卷积操作)、添加偏差、然后通过ReLU操作。
假定你的单层神经网络中有 10 个而不是 2 个 3x3x3 的过滤器, 这层网络中有多少参数?
每个过滤器是一个 3x3x3 的矩阵 因此每个过滤器有27个参数 也就是,此外,每个过滤器还对应一个参数 b,也就是总共28个参数。现在这里我们有10个过滤器,加起来是 28x10,也就是280个参数 。所以卷积层有一个很好的特性是:不管输入的图像有多大 比方1000 x 1000 或者5000 x 5000,只要过滤器的大小与个数不变,这里的参数个数就不会变.,依然是280个。 这个特性使得卷积神经网络不太容易过拟合。
假设我们有一张图像 并且你想做图像分类,或图像识别 输入为一个图像, x , 然后判断这是不是一只猫,0或1 所以这是一个分类问题。 让我们构建一个可用于此任务的ConvNet范例。 假设这个图像是 39 x 39 x 3。
通过三个卷积层后得到结果为一个 7 x 7 x 40 的特征向量。 最后通常会做的是, 如果你把这个 7 x 7 x 40 的特征向量展开为 1960 个单元,然后将其输入到一个逻辑回归 或 softmax 单元。
随着你建的神经网络越来越深, 通常你开始的时候, 图像都是比较大的,例如39乘39 高度和宽度在保持不变一阵子后 随着你在神经网络中的深入, 逐渐变小 在我们的这个例子里,它从39到37到17到7。而通道的数目一般会增加,它已经从3到10到20到40。这在卷积神经网络中是一种常见的趋势。
卷积神经网络设计中的许多工作是选择 像这样的超参数(hyperparameter): 总单元数是多少? 步长是什么? padding是多少和使用了多少过滤器?
事实证明, 在一个典型的 ConvNet, 通常有三种类型的层。 第一种是卷积层, 通常我们会将其表示为一个Conv层 ;第二种称为 “Pooling” 层, 通常我会直接称为 Pool。 最后一种是全连接层,称为 FC。
除卷积层之外 ConvNets通常还使用池化层来减少展示量,以此来提高计算速度,并使一些特征的检测功能更强大。以最大池化(Max pooling)为例:
最大池化就是将原矩阵划分为大小相等的小区域,然后找到每个小区域最大的元素,并按顺序保存在一个新的矩阵种。假设你有一个 4x4 的输入并且按照 2x2 的大小来划分小区域,那么 max pooling 后的输出将会是一个 2x2 的矩阵。这如同你使用了一个大小为2的过滤器,因为你选取一个 2x2 的区域,并且使用的步长为 2,这些实际上就是max pooling 的超参数。
max pooling背后的机制:
如果你把这个4x4的区域看作某个特征的集合,那么一个大的数字意味着它或许检测到了一个特定的特征,它或许是一个垂直的边沿,或者其他。所以左侧上方的四分之一区域的最大值为 9,说明这个区域有这样的特征。但是,右侧上方的四分之一区域的最大值很小,可能说明这个区域没有这个特征。所以 max pooling作所做的其实是如果在滤波器中任何地方检测到了这些特征就保留最大的数值。
max pooling 的一个有趣的特性是它有一套超参,但是它没有任何参数需要学习。实际上,没有任何需要梯度相加算法学习的东西,一旦确定了 f 和 s 就确定了计算,而且梯度下降算法不会对其有任何改变。让我们来看一个有某些不同超参的例子:
除了最大池化,还有一类不是很常使用的池化:平均池化。 它所做的不是求在每个小区域中取最大值,而是取其平均值。 目前,最大值采样的使用通常比均值采样多得多,唯一的例外是有时候在深度非常大的神经网络 你也许可以使用均值采样来合并表示。
总结一下,池化的超参数有滤波器的大小 f 以及步长 s,最常见的是 f = 2,s = 2,这个相当常用并且其效果是近似得把高度和宽度缩小了两倍,而其它的超参就像一个二进制位来指示你是使用最大值采样还是均值采样。通常情况下,是不进行任何的补位,所以,p 最为常用的取值是 p = 0。
此外,对于单个过滤器,输入通道的数量等于输出通道的数量,因为池化是独立地应用于每一个通道。另外需要注意的是,池化是一个确定的函数,它没有需要学习的参数。 反而这些超参需要你设定一次,或许是人工设定或者使用交叉检验。
现在我们用卷积层,池化层,全连接层创建一个完整的卷积神经网络。 假设我们试着做手写数字识别,输入图像大小为 32x32x3的一个RGB图像,要尝试识别图像是0-9中十个数字中的哪一个是 7。
将上图通过表格的形式展示出来。可以发现,随着神经网络的深入,激活输入大小也逐渐变小。不过如果减少的太快,通常也不利于网络性能。许多卷积神经网络有着与此相似的特性和模式。
这其中似乎有许多超参数,关于如何选择这类超参数 ,一个常用的法则实际上是 不要试着创造你自己的超参数组,而是查看文献,看看其他人使用的超参数,从中选一组很可能它也适用于自己的应用。
到这里你已经了解了神经网络的基本构件 卷积神经网络,卷积层,池化层和全连接层。如何利用这些基本构件来构造一个有效的神经网络,已经有许多计算机领域专家在深入研究了,把这些构件组合到一起实际上需要相当的洞察力。最好的方法之一 就是去学习一定数量的实例,看看人家是如何做的,并从中来获得灵感如何把这些构件组合在一起。
卷积层和只用完全连接的神经层比起来有两个优势:参数共享和连接的稀疏性 。
参数共享:过滤器对于图像的一部分是有用的,那么对于另一部分可能也是有用的。
稀疏连接:在每一层中,每个输出值只依赖于少量的输入而不是全部的输入。
通过这两个优势,卷积层所需的参数比起相同输入输出下的全连接层参数少了很多很多。
此外,卷积神经网络会被用来捕捉平移不变。比如说当一张猫的图片的像素格向任意方向移动了几格,还是一个非常清晰的猫的图片。经卷积层后产生的特征还是与没有移动时的特征相似。
综上所述,如何来训练这样一个卷积神经网络?我们需要定义一个代价函数 J, 然后使用梯度下降或一些类似的算法,比如梯度下降动量 或者 RMSProp,Adam 等算法,来优化所有的神经网络参数 W 和 b,从而降低成本函数 J。
1、利用到了图像的空间信息。
2、参数的多少取决于过滤器的大小和数量,和输入的图像没有关系。即使输入的图片很大很大,只需少量的参数就能处理这张图片,而且少量的参数不会造成过拟合。
3、学习到的过滤器既可以用到大图片中,也可以用到小图片中,也就是对输入没有了限制。