caffe中RGB图像三通道卷积过程学习推导

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014381600/article/details/60883856

idea来源于自己的想法,之前在github看过大神贾杨清的推导slider,caffe中如果计算卷积,加上自己最近有个很小的疑惑,输入的image一般是RGB三通道的彩色图片,但是我们在定义卷积层时一般只指定了一个kernel_size参数。像这样:
这里写图片描述
本文首先学习一下贾杨清大神的slider推导过程,然后从caffe源码里面去找从定义caffe的kernel_size参数开始以后干的事,然后分析一下RGB三通道卷积是怎么操作的。

github原文地址https://github.com/Yangqing/caffe/wiki/Convolution-in-Caffe:-a-memo
1:图片:一般我们说一张图片的宽度为width:W,高度为height:H,这张图片的的通道数为D,一般目前都用RGB三通道的D=3,但是为了通用性表示为D
2:卷积核:卷积核大小为K*K,,因为处理的图片是D通道的,因此卷积核其实也就是K*K*D大小的,假设有M个卷积核
–到这里其实就解决了之前的疑问,RGB三通道,指定了kernel_size的前提下,真正的卷积核大小是kernel_size*kernel_size*3。

接下来继续讨论caffe是如何实现通道数为D的卷积的:
最简单的实现方法,循坏:

for w in 1..W
  for h in 1..H
    for x in 1..K
      for y in 1..K
        for m in 1..M
          for d in 1..D
            output(w, h, m) += input(w+x, h+y, d) * filter(m, x, y, d)
          end
        end
      end
    end
  end
end

可以看到最内层的循环是针对通道数D的,

output(w, h, m) += input(w+x, h+y, d) * filter(m, x, y, d)

说明对于D各通道而言,是在每个通道上分别执行二维卷积,然后将D个通道加起来,得到该位置的二维卷积输出,对于RGB三通道而言,就是在R,G,B三个通道上分别使用对应的每个通道上的kernel_size*kernel_size大小的核去卷积每个通道上的W*H的图片,然后将三个通道卷积得到的输出相加,得到M个二维卷积输出结果,在有padding的情况下,能保持输出图片大小和原来的一样,因此是:output(w, h, m) 。
应用作者原文的话:

The trick is to just lay out all the local patches, and organize them to a (W*H, K*K*D) matrix. In Matlab, this is usually known as an im2col operation. After that, consider the filters being a (M, K*K*D) matrix too, the convolution naturally gets reduced to a matrix multiplication (Gemm in BLAS) problem.

我们可以将一张图片考虑为矩阵(W*H, K*K*D),将卷积核考虑为 (M, K*K*D),因此可以用矩阵相乘来实现快速卷积,使用的matlab函数是im2col ,接下来我们仔细的讨论下如何将图片变成矩阵以实现卷积:
这里写图片描述

接下来就要使用img2col函数,将这种方法转换为矩阵乘法,来加速实现卷积方法:
这部分参考了:http://www.cnblogs.com/louyihang-loves-baiyan/p/5154337.html

矩阵相乘基本原理:
这里写图片描述
因此将图片转置为矩阵时,后面的一个卷积核矩阵N的一列就是卷积核参数,前面矩阵M的每一行的大小必须是对应的那个卷积核卷积的原图区域的数据。
因此在img2col函数转换矩阵时需要知道卷积核大小,并按照卷积核大小在原图中取数据,以此类推当多个卷积核时,只需要将矩阵N的列数增加,并在原图中取出不同卷积核对应的数据放在矩阵M的对应行中。
借用一张图可以更清晰的看到是如何在原图中取数据组成矩阵M的:
这里写图片描述
矩阵M的一行分为很多个batch,每一行都是对应原图中同一个位置kernel_size*kernel_size*M,M就是滤波器数目,每一个batch的大小都是对应kernel_size*kernel_size,其实就是按照滤波器数目来从原图中抠出相应的位置数据,以保证对应的滤波器的参数在矩阵相乘时乘的是自己的数据。
当图片也存在多个通道时情况更加复杂,但是都是相同的道理,按照滤波器参数去原图中抠对应的位置数据,放在能够跟滤波器相乘的位置。

猜你喜欢

转载自blog.csdn.net/u014381600/article/details/60883856