最近,在看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. JIRA Plugin Development——Configurable Custom Field Plugin

    关于JIRA Plugin开发的中文资料相当少,这可能还是由于JIRA Plugin开发在国内比较小众的原因吧,下面介绍下自己的一个JIRA Plugin开发的详细过程. 业务需求 创建JIRA IS ...

  2. 为Visual Studio 2012添加MSDN离线帮助

    之前有网络的情况下,一直使用的都是在线的,最近又有笔记本上面有时使用时没有网络,所以就想使用下离线的MSDN包.可是找了半天,发现都是需要再次进行下载的.VS2012使用的帮助程序是HelpViewe ...

  3. hdu-3572 Task Schedule---最大流判断满流+dinic算法

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3572 题目大意: 给N个任务,M台机器.每个任务有最早才能开始做的时间S,deadline E,和持 ...

  4. Android(java)学习笔记102:Dalivk虚拟机的初始化过程

    1. 初始化下面系统函数(调用dvmStartup函数初始化所有相关的函数) 开始学习虚拟机的初始化过程,先从dvmStartup函数开始,这个函数实现所有开始虚拟机的准备工作:    dvmAllo ...

  5. BSGS算法初探

    前言 \(BSGS\)算法,全称\(Baby\ Step\ Giant\ Step\),即大小步算法.某些奆佬也称其为拔(Ba)山(Shan)盖(Gai)世(Shi)算法. 它的主要作用是求解形式如\ ...

  6. 深入理解计算机系统_3e 第十一章家庭作业 CS:APP3e chapter 11 homework

    注:tiny.c csapp.c csapp.h等示例代码均可在Code Examples获取 11.6 A. 书上写的示例代码已经完成了大部分工作:doit函数中的printf("%s&q ...

  7. 更改yum网易、阿里云的yum源

    更改yum源为网易的. 首先备份/etc/yum.repos.d/CentOS-Base.repomv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos ...

  8. (79)zabbix key总是not supported的解决方法

    zabbix定义好key之后,总是会出现Not supported,看到这个问题,大家不用着急,问题其实很容易解决,首先鼠标点击当前key的大红叉上,会显示出报错内容. 常见的有: 1. zabbix ...

  9. js获取整型数组最大值、最小值、平均值

    ---恢复内容开始--- let values = [];//数组(整型数字) //获取数组最大值function arrMaxNum(arr){ var maxNum = null; for (va ...

  10. pycharm配置Git托管

    利用Pycharm和github管理代码转载https://www.cnblogs.com/feixuelove1009/p/5955332.html git教程--廖雪峰git教程  转载https ...