logo资料库

Deep Learning:CNN卷积神经网络推导和实现.docx

第1页 / 共11页
第2页 / 共11页
第3页 / 共11页
第4页 / 共11页
第5页 / 共11页
第6页 / 共11页
第7页 / 共11页
第8页 / 共11页
资料共11页,剩余部分请下载后查看
http://blog.csdn.net/zouxy09/article/details/9993371 自己平时看了一些论文,但老感觉看完过后就会慢慢的淡忘,某一天重新拾起来的时候又好像没有看 过一样。所以想习惯地把一些感觉有用的论文中的知识点总结整理一下,一方面在整理过程中,自己 的理解也会更深,另一方面也方便未来自己的勘察。更好的还可以放到博客上面与大家交流。因为基 础有限,所以对论文的一些理解可能不太正确,还望大家不吝指正交流,谢谢。 本文的论文来自: Notes on Convolutional Neural Networks, Jake Bouvrie。 这个主要是 CNN 的推导和实现的一些笔记,再看懂这个笔记之前,最好具有 CNN 的一些基础。 这里也先列出一个资料供参考: [1] Deep Learning(深度学习)学习笔记整理系列之(七) [2] LeNet-5, convolutional neural networks [3]卷积神经网络 [4] Neural Network for Recognition of Handwritten Digits [5] Deep learning:三十八(Stacked CNN 简单介绍) [6] Gradient-based learning applied to document recognition. [7]Imagenet classification with deep convolutional neural networks. [8] UFLDL 中的“卷积特征提取”和“池化”。 另外,这里有个 matlab 的 Deep Learning 的 toolbox,里面包含了 CNN 的代码,在下一个博文中, 我将会详细注释这个代码。这个笔记对这个代码的理解非常重要。 下面是自己对其中的一些知识点的理解: 《Notes on Convolutional Neural Networks》 一、介绍
这个文档讨论的是 CNNs 的推导和实现。CNN 架构的连接比权值要多很多,这实际上就隐含着实 现了某种形式的规则化。这种特别的网络假定了我们希望通过数据驱动的方式学习到一些滤波器,作 为提取输入的特征的一种方法。 本文中,我们先对训练全连接网络的经典 BP 算法做一个描述,然后推导 2D CNN 网络的卷积层 和子采样层的 BP 权值更新方法。在推导过程中,我们更强调实现的效率,所以会给出一些 Matlab 代 码。最后,我们转向讨论如何自动地学习组合前一层的特征 maps,特别地,我们还学习特征 maps 的稀疏组合。 二、全连接的反向传播算法 典型的 CNN 中,开始几层都是卷积和下采样的交替,然后在最后一些层(靠近输出层的),都 是全连接的一维网络。这时候我们已经将所有两维 2D 的特征 maps 转化为全连接的一维网络的输入。 这样,当你准备好将最终的 2D 特征 maps 输入到 1D 网络中时,一个非常方便的方法就是把所有输出 的特征 maps 连接成一个长的输入向量。然后我们回到 BP 算法的讨论。(更详细的基础推导可以参 考 UFLDL 中“反向传导算法”)。 2.1、Feedforward Pass 前向传播 在下面的推导中,我们采用平方误差代价函数。我们讨论的是多类问题,共 c 类,共 N 个训练样 本。 这里 表示第 n 个样本对应的标签的第 k 维。 表示第 n 个样本对应的网络输出的第 k 个 输出。对于多类问题,输出一般组织为“one-of-c”的形式,也就是只有该输入对应的类的输出节点 输出为正,其他类的位或者节点为 0 或者负数,这个取决于你输出层的激活函数。sigmoid 就是 0,tanh 就是-1.
因为在全部训练集上的误差只是每个训练样本的误差的总和,所以这里我们先考虑对于一个样本 的 BP。对于第 n 个样本的误差,表示为: 传统的全连接神经网络中,我们需要根据 BP 规则计算代价函数 E 关于网络每一个权值的偏导数。 我们用 l 来表示当前层,那么当前层的输出可以表示为: 输出激活函数 f(.)可以有很多种,一般是 sigmoid 函数或者双曲线正切函数。sigmoid 将输出压缩 到[0, 1],所以最后的输出平均值一般趋于 0 。所以如果将我们的训练数据归一化为零均值和方差为 1, 可以在梯度下降的过程中增加收敛性。对于归一化的数据集来说,双曲线正切函数也是不错的选择。 2.2、Backpropagation Pass 反向传播 反向传播回来的误差可以看做是每个神经元的基的灵敏度 sensitivities(灵敏度的意思就是我们的 基 b 变化多少,误差会变化多少,也就是误差对基的变化率,也就是导数了),定义如下:(第二个 等号是根据求导的链式法则得到的) 因为∂u/∂b=1,所以∂E/∂b=∂E/∂u=δ,也就是说 bias 基的灵敏度∂E/∂b=δ和误差 E 对一个节点全部 输入 u 的导数∂E/∂u 是相等的。这个导数就是让高层误差反向传播到底层的神来之笔。反向传播就是 用下面这条关系式:(下面这条式子表达的就是第 l 层的灵敏度,就是) 这里的“◦”表示每个元素相乘。输出层的神经元的灵敏度是不一样的: 公式(1)
最后,对每个神经元运用 delta(即δ)规则进行权值更新。具体来说就是,对一个给定的神经元, 得到它的输入,然后用这个神经元的 delta(即δ)来进行缩放。用向量的形式表述就是,对于第 l 层, 误差对于该层每一个权值(组合为矩阵)的导数是该层的输入(等于上一层的输出)与该层的灵敏度 (该层每个神经元的δ组合成一个向量的形式)的叉乘。然后得到的偏导数乘以一个负学习率就是该 层的神经元的权值的更新了: 对于 bias 基的更新表达式差不多。实际上,对于每一个权值(W)ij 都有一个特定的学习率ηIj。 公式(2) 三、Convolutional Neural Networks 卷积神经网络 3.1、Convolution Layers 卷积层 我们现在关注网络中卷积层的 BP 更新。在一个卷积层,上一层的特征 maps 被一个可学习的卷 积核进行卷积,然后通过一个激活函数,就可以得到输出特征 map。每一个输出 map 可能是组合卷 积多个输入 maps 的值: 这里 Mj表示选择的输入 maps 的集合,那么到底选择哪些输入 maps 呢?有选择一对的或者三个 的。但下面我们会讨论如何去自动选择需要组合的特征 maps。每一个输出 map 会给一个额外的偏置 b,但是对于一个特定的输出 map,卷积每个输入 maps 的卷积核是不一样的。也就是说,如果输出 特征 map j 和输出特征 map k 都是从输入 map i 中卷积求和得到,那么对应的卷积核是不一样的。
3.1.1、Computing the Gradients 梯度计算 我们假定每个卷积层 l 都会接一个下采样层 l+1 。对于 BP 来说,根据上文我们知道,要想求得层 l 的每个神经元对应的权值的权值更新,就需要先求层 l 的每一个神经节点的灵敏度δ(也就是权值更 新的公式(2))。为了求这个灵敏度我们就需要先对下一层的节点(连接到当前层 l 的感兴趣节点 的第 l+1 层的节点)的灵敏度求和(得到δl+1),然后乘以这些连接对应的权值(连接第 l 层感兴趣节 点和第 l+1 层节点的权值)W。再乘以当前层 l 的该神经元节点的输入 u 的激活函数 f 的导数值(也就 是那个灵敏度反向传播的公式(1)的δl 的求解),这样就可以得到当前层 l 每个神经节点对应的灵敏 度δl 了。 然而,因为下采样的存在,采样层的一个像素(神经元节点)对应的灵敏度δ对应于卷积层(上 一层)的输出 map 的一块像素(采样窗口大小)。因此,层 l 中的一个 map 的每个节点只与 l+1 层中 相应 map 的一个节点连接。 为了有效计算层 l 的灵敏度,我们需要上采样 upsample 这个下采样 downsample 层对应的灵敏度 map(特征 map 中每个像素对应一个灵敏度,所以也组成一个 map),这样才使得这个灵敏度 map 大小与卷积层的 map 大小一致,然后再将层 l 的 map 的激活值的偏导数与从第 l+1 层的上采样得到的 灵敏度 map 逐元素相乘(也就是公式(1))。 在下采样层 map 的权值都取一个相同值β,而且是一个常数。所以我们只需要将上一个步骤得 到的结果乘以一个β就可以完成第 l 层灵敏度δ的计算。 我们可以对卷积层中每一个特征 map j 重复相同的计算过程。但很明显需要匹配相应的子采样层 的 map(参考公式(1)): up(.)表示一个上采样操作。如果下采样的采样因子是 n 的话,它简单的将每个像素水平和垂直方 向上拷贝 n 次。这样就可以恢复原来的大小了。实际上,这个函数可以用 Kronecker 乘积来实现:
好,到这里,对于一个给定的 map,我们就可以计算得到其灵敏度 map 了。然后我们就可以通 过简单的对层 l 中的灵敏度 map 中所有节点进行求和快速的计算 bias 基的梯度了: 公式(3) 最后,对卷积核的权值的梯度就可以用 BP 算法来计算了(公式(2))。另外,很多连接的权 值是共享的,因此,对于一个给定的权值,我们需要对所有与该权值有联系(权值共享的连接)的连 接对该点求梯度,然后对这些梯度进行求和,就像上面对 bias 基的梯度计算一样: 这里, 是 中的在卷积的时候与 逐元素相乘的 patch,输出卷 积 map 的(u, v)位置的值是由上一层的(u, v)位置的 patch 与卷积核 k_ij 逐元素相乘的结果。 咋一看,好像我们需要煞费苦心地记住输出 map(和对应的灵敏度 map)每个像素对应于输入 map 的哪个 patch。但实际上,在 Matlab 中,可以通过一个代码就实现。对于上面的公式,可以用 Matlab 的卷积函数来实现: 我们先对 delta 灵敏度 map 进行旋转,这样就可以进行互相关计算,而不是卷积(在卷积的数学 定义中,特征矩阵(卷积核)在传递给 conv2 时需要先翻转(flipped)一下。也就是颠倒下特征矩阵 的行和列)。然后把输出反旋转回来,这样我们在前向传播进行卷积的时候,卷积核才是我们想要的 方向。
3.2、Sub-sampling Layers 子采样层 对于子采样层来说,有 N 个输入 maps,就有 N 个输出 maps,只是每个输出 map 都变小了。 down(.)表示一个下采样函数。典型的操作一般是对输入图像的不同 nxn 的块的所有像素进行求和。 这样输出图像在两个维度上都缩小了 n 倍。每个输出 map 都对应一个属于自己的乘性偏置β和一个加 性偏置 b。 3.2.1、Computing the Gradients 梯度计算 这里最困难的是计算灵敏度 map。一旦我们得到这个了,那我们唯一需要更新的偏置参数β和 b 就可以轻而易举了(公式(3))。如果下一个卷积层与这个子采样层是全连接的,那么就可以通过 BP 来计算子采样层的灵敏度 maps。 我们需要计算卷积核的梯度,所以我们必须找到输入 map 中哪个 patch 对应输出 map 的哪个像 素。这里,就是必须找到当前层的灵敏度 map 中哪个 patch 对应与下一层的灵敏度 map 的给定像素, 这样才可以利用公式(1)那样的δ递推,也就是灵敏度反向传播回来。另外,需要乘以输入 patch 与 输出像素之间连接的权值,这个权值实际上就是卷积核的权值(已旋转的)。 在这之前,我们需要先将核旋转一下,让卷积函数可以实施互相关计算。另外,我们需要对卷积 边界进行处理,但在 Matlab 里面,就比较容易处理。Matlab 中全卷积会对缺少的输入像素补 0 。 到这里,我们就可以对 b 和β计算梯度了。首先,加性基 b 的计算和上面卷积层的一样,对灵敏 度 map 中所有元素加起来就可以了:
而对于乘性偏置β,因为涉及到了在前向传播过程中下采样 map 的计算,所以我们最好在前向的 过程中保存好这些 maps,这样在反向的计算中就不用重新计算了。我们定义: 这样,对β的梯度就可以用下面的方式计算: 3.3、Learning Combinations of Feature Maps 学习特征 map 的组合 大部分时候,通过卷积多个输入 maps,然后再对这些卷积值求和得到一个输出 map,这样的效 果往往是比较好的。在一些文献中,一般是人工选择哪些输入 maps 去组合得到一个输出 map。但我 们这里尝试去让 CNN 在训练的过程中学习这些组合,也就是让网络自己学习挑选哪些输入 maps 来计 算得到输出 map 才是最好的。我们用αij 表示在得到第 j 个输出 map 的其中第 i 个输入 map 的权值或 者贡献。这样,第 j 个输出 map 可以表示为: 需要满足约束: 这些对变量αij 的约束可以通过将变量αij 表示为一个组无约束的隐含权值 cij 的 softmax 函数来加 强。(因为 softmax 的因变量是自变量的指数函数,他们的变化率会不同)。
分享到:
收藏