最近,在看caffe源码时,偶然在网上看到一个问题?觉得挺有意思,于是,仔细的查了相关资料,并将总结写在这里,供大家迷惑时,起到一点启示作用吧。

问题的题目是CNN中的一个卷积层输入64个通道的特征子图,输出256个通道的特征子图,那么,该层一共包含多少个卷积核?

对于上面这个问题,目前有两种答案,每一种答案的区别是所基于的卷积核的维度不同而导致的。下面是两种答案的解析过程:

第一种答案:卷积核是二维的(caffe源码中以卷积核二维转化成相应矩阵),那么就需要64*256个卷积核来对输入特征子图进行卷积,其中,输入的每个通道对应64种不同的卷积核进行卷积,再将64种卷积核得到的卷积结果合并成一张输出特征子图;这样,就会得到256个通道的特征子图。

第二种答案:卷积核是三维的(caffe大神贾杨清老师的回答中就是这么认为的),那么一个卷积核的表示为C*H*W(C:通道数,H:卷积核的高,W:卷积核宽)。那么对于输入的特征子图,就需要一个大小为64*h*w的卷积核进行卷积,得到一张特征子图。这样,就需要256个不同卷积核,每个卷积核的通道数为64,从而得到256个通道的特征子图。

  显然,这两种答案都有一定的依据,不管如何认为,其最终的目的都是要将卷积层复杂的卷积问题转化为矩阵的相乘问题,从而大大的提高计算速度。

  那么,肯定有很多朋友,尤其是像我这种深度学习的菜鸟,一开始还是比较迷糊的,对于上面的解释还是不知所云。那么,下面,我就来对这两种观点进行具体分析,不足之处,希望大家能指出来,共同学习。

一,卷积核是二维的

  我们知道,在caffe中卷积层的运算是首先通过img2col()将各个卷积核和输入特征子图转化为向量,然后多个卷积核或输入特征子图的向量组合成为矩阵;接下来,通过矩阵相乘运算得到卷积的结果,再通过col2img()将向量转化为特征子图。M个卷积核卷积一张输入图像的矩阵计算如下图所示:

图来自http://www.cnblogs.com/laiqun/p/6055498.html

其中,M表示二维卷积核的个数,K=k*k表示二维卷积核的大小;这样,每个k*k大小的二维卷积核转化为一个行向量,M个二维卷积核对应M个行向量就得到了M*K的卷积矩阵A。

再说矩阵B:假设输入的每张特征子图大小为r*r,二维卷积核的大小为k*k,扩展大小pad,步长为stride,那么对于每张特征子图,按卷积核每次卷积图像的大小k*k,将该块卷积的图像转化为行向量,长度也为k*k=K,这样,依据卷积核与输入图像卷积的过程,将每一次卷积核卷积的区域转化为一个行向量,各个行向量按照卷积先后顺序以列进行排列,从而得到了矩阵B。此外,对于卷积后得到的二维特征子图的大小,在caffe中的计算公式如下(这里假设,输入图像和卷积和大小都是q*q的,即长与宽相等):

  输出特征子图大小:n*n=[(r+2*pad-k)/strde+1]*[(r+2*pad-k)/strde+1]

如果我们令pad=0,stride=1,那么就会变成我们熟悉的形式,即n*n=[(r-k)+1]*[(r-k)/+1]。比如,输入特征图大小为32*32,卷积核大小为3*3,那么输出的特征子图大小为(32-3+1)*(32-3+1)=28*28。

  好了,现在我们知道了矩阵B的列N=n*n,然后通过矩阵相乘运行,即A*BT=(M*K)*(N*K)T=(M*K)*(K*N)=(M*N)=C,即得到了最终的矩阵C。当然,在caffe中可能会存在偏置项,那么这个矩阵C还要加上偏置矩阵P,然后得到最终的输出矩阵D,再通过col2img()将D中的每一行转化为一张特征图,就得到了输出的各个特征子图,从而完成了该卷积层的卷积运算。

二,卷积核是三维的

  对于卷积核是三维的情况,主要参考的是贾杨清老师在知乎上的一个解答。即认为每个输入图像和每个卷积核的大小表示为C*H*W,即:

  由上图知道,一个输入特征图的表示是C*H*W(通道数*长*宽),一个卷积核的大小表示为C*K*K(注意:这里,如果认为卷积核是三维的,就必须保证卷积核的通道数跟输入特征图的通道数相同,否则卷积失败),那么根据卷积核一次卷积的图像区域,将该区域图像转化为行向量,即得到一个C*k*k的行向量。

  按此方式,将一张图像按照卷积的顺序得到的行向量按列排列,就得到了最终的特征矩阵如下:

上图知道,对于一个C*H*W的图像,按照卷积核大小进行卷积,转化为的特征矩阵大小为:(H*W)*(C*K*K)。

那么,对于多个卷积核而言,将多个卷积核转化为卷积矩阵过程如下:

这里,卷积核的个数为Cout,每个卷积核的大小为C*K*K,同理,将每个卷积核转化为一个行向量C*K*K,按照卷积核个数按列排列,就得到卷积矩阵Cout*(C*K*K)。

  最后,将卷积矩阵与输入特征矩阵的转置进行相乘,就得到了最终的输出特征矩阵[Cout*(C*K*K)]*[(H*W)*(C*K*K)]T=[Cout*(C*K*K)]*[(C*K*K)*(H*W)]=Cout*(H*W)。这样,再将输出矩阵的每一行转化为一张特征图,就得到了Cout张输出特征子图。而这,也就印证了:卷积层输出的特征图个数等于卷积核的个数。

  以上,就是对两种对于卷积核的维度不同看法的具体分析,不管怎么定义,都有其充分的理由和实践证明。并且,最重要的是,不管卷积核定义为二维还是三维,都是为了数据转化为矩阵的形式,从而将卷积层的复杂的卷积过程,转化为矩阵的相乘的简单运算,大大的提高了计算的速度。

  最后,通过一个具体的例子,来看一下将卷积转化为矩阵运算的过程:

参考链接:http://www.cnblogs.com/laiqun/p/6055498.html

     https://www.zhihu.com/question/28385679

     Convolution in Caffe: a memo · Yangqing/caffe Wiki · GitHub 

              High Performance Convolutional Neural Networks for Document Processing
              https://hal.archives-ouvertes.fr/file/index/docid/112631/filename/p1038112283956.pdf

关于caffe 是如何卷积的一点总结的更多相关文章

  1. caffe源码 卷积层

    通俗易懂理解卷积 图示理解神经网络的卷积 input: 3 * 5 * 5 (c * h * w) pading: 1 步长: 2 卷积核: 2 * 3 * 3 * 3 ( n * c * k * k ...

  2. caffe中全卷积层和全连接层训练参数如何确定

    今天来仔细讲一下卷基层和全连接层训练参数个数如何确定的问题.我们以Mnist为例,首先贴出网络配置文件: name: "LeNet" layer { name: "mni ...

  3. caffe中LetNet-5卷积神经网络模型文件lenet.prototxt理解

    caffe在 .\examples\mnist文件夹下有一个 lenet.prototxt文件,这个文件定义了一个广义的LetNet-5模型,对这个模型文件逐段分解一下. name: "Le ...

  4. caffe中的卷积

    https://www.zhihu.com/question/28385679 如上,将三维的操作转换到二维上面去做,然后调用GEMM库进行矩阵间的运算得到最后结果. 两个矩阵相乘,需要中间的那个维度 ...

  5. caffe卷积输入通道如何到输出通道

    今天一个同学问 卷积过程好像是对 一个通道的图像进行卷积, 比如10个卷积核,得到10个feature map, 那么输入图像为RGB三个通道呢,输出就为 30个feature map 吗, 答案肯定 ...

  6. caffe源码阅读(1)_整体框架和简介(摘录)

    原文链接:https://www.zhihu.com/question/27982282 1.Caffe代码层次.回答里面有人说熟悉Blob,Layer,Net,Solver这样的几大类,我比较赞同. ...

  7. caffe学习(1):多平台下安装配置caffe

    如何在 centos 7.3 上安装 caffe 深度学习工具   有好多朋友在安装 caffe 时遇到不少问题.(看文章的朋友希望关心一下我的创业项目趣智思成) 今天测试并整理一下安装过程.我是在阿 ...

  8. Caffe源码解析5:Conv_Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ Vision_layer里面主要是包括了一些关于一些视觉上的操 ...

  9. 【转】Caffe初试(五)视觉层及参数

    本文只讲解视觉层(Vision Layers)的参数,视觉层包括Convolution, Pooling, Local Response Normalization (LRN), im2col等层. ...

随机推荐

  1. 微信小程序 尺寸单位px与rpx之间的转换(入门篇)

    1.rpx:微信小程序中的尺寸单位rpx(responsive pixel):可以根据屏幕宽度进行自适应.规定屏幕宽度为750rpx. 微信官方建议视觉稿以iphone6为标准. 2.个人示例测试: ...

  2. Android(java)学习笔记93:为什么局部内部类只能访问外部类中的 final型的常量

    为什么匿名内部类参数必须为final类型: 1)  从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形式参数定义处或者方法体处),因而访问方法中的局部变 ...

  3. 【BZOJ3668】[NOI2014] 起床困难综合症(位运算思想)

    点此看题面 大致题意: 给定一些位运算操作,让你在\(0\sim m\)范围内选一个初始值,使其在经过这些运算后得到的结果最大. 前置技能:关于位运算 作为一道位运算的题,如果你不知道什么是位运算,那 ...

  4. C#继承机制 继承与访问修饰符

    继承与访问修饰符 访问修饰符是一些关键字,用于指定声明的成员或类型的可访问性.类的继承中有四个访问修饰符: public protected internal private.使用这些访问修饰符可指定 ...

  5. java实现微信扫一扫详解

    java实现微信扫一扫详解 一.微信JS-SDK参数配置及查找 JS安全域名配置(查找:微信公众号里-公众号设置-功能设置页) 注:1.安全域名外网必须可以访问的到  2.域名不能有下划线  3.要将 ...

  6. java基础面试题:如何把一段逗号分割的字符串转换成一个数组? String s = "a" +"b" + "c" + "d";生成几个对象?

    package com.swift; public class Douhao_String_Test { public static void main(String[] args) { /* * 如 ...

  7. Uva 组装电脑 12124 - Assemble

    主要运用二分法查找最优解 #include<iostream> #include<string> #include<vector> #include<map& ...

  8. nginx Keepalived高可用集群

    一.Keepalived高可用 1.简介 Keepalived软件起初是专为LvS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能.因此, ...

  9. LeetCode949-给定数字能组成的最大时间

    问题: 给定一个由 4 位数字组成的数组,返回可以设置的符合 24 小时制的最大时间. 最小的 24 小时制时间是 00:00,而最大的是 23:59.从 00:00 (午夜)开始算起,过得越久,时间 ...

  10. Python虚拟机类机制之自定义class(四)

    用户自定义class 在本章中,我们将研究对用户自定义class的剖析,在demo1.py中,我们将研究单个class的实现,所以在这里并没有关于继承及多态的讨论.然而在demo1.py中,我们看到了 ...