作為cnn中最重要的卷積榜揖,最簡單的理解就為:
其中迅矛,卷積主要的參數(shù)有:
stride 步長 ? ? ? ? ? ? ?stride_w,stride_h
kernel_size ? ? ? ? ? ? kernel_w,kernel_w
dilation ? ? ? ? ? ? ? ? ? ?膨脹系數(shù)
padding? ? ? ? ? ? ? ? ? pad_w,pad_h
卷積層:conv_layer.cpp
里面主要有
compute_output_shape() ? ?計算輸出blob的大小
Forward_cpu
Backward_cpu
其中Forword_cpu主要用到了forward_cpu_gemm,這個位于base_conv_layer,
forward_cpu_gemm里面使用到了conv_im2col_cpu壶硅,caffe_cpu_gemm销斟。
conv_im2col_cpu ? 是把輸入圖像變?yōu)橐粋€矩陣,這樣子做能直接和卷積核組成的矩陣做點乘约谈,得到的矩陣就為 卷積后每一個特征圖就為為這矩陣中一個行向量犁钟。
查看cov_im2col_cpu;
我們先以im2col_cpu為入手:
主要參數(shù)為:
1.data ?
?2.conv_channels 卷積的通道數(shù)
3.conv_input_shape.cpu_data()[1] ? ? ? ? 即image_h 輸入圖像的height醋粟,主要下標
4conv_input_shape.cpu_data()[1] ? ? ? ? ?image_w
5.padding_h,padding_w
6.stride_h,stride_w
7.dilation ? ?膨脹系數(shù)
推導過程太復雜了米愿,這里有一個單通道的完整的推導過程:lib.csdn.net/article/aiframework/62849
總之,im2col泳唠,就是把一個圖片上的對應每一個卷積核大小的窗函數(shù)里面的元素宙搬,變?yōu)榱邢蛄浚S著步長的移動脖母,得到不同的列向量闲孤,合并起來得到一個矩陣,也就是col_buff
那caffe中是怎么樣計算卷積的:
我們先從單通道入手肥照,用一個單通道卷積核去卷積一個單通道圖像:
在不考慮膨脹系數(shù)的情況下勤众,N=((image_h+2*pad_h-kenrel_h)/stride_h+1)*((image_w+2*pad_w-kenrel_w)/stride_w+1),其實就是計算經(jīng)卷積后輸出的圖像的長與寬们颜,再相乘吕朵,得到feature map的大小努溃。
那當是多通道圖片(比如說最開始的三通道阻问,以及經(jīng)過一層卷積后的擁有很多通道的特征圖)的情況是什么樣的?
下面以一個實際的例子:
這就是caffe卷積的原理贡蓖。
caffe_gpu_gemm(CblasNoTrans,CblasTrans,M,N,K(Dtype)1,top_diff,bottom_data,(Dtype)1,weights_diff)
voidcaffe_gpu_gemm(constCBLAS_TRANSPOSETransA,constCBLAS_TRANSPOSETransB,const intM,const intN,const intK,constDtypealpha,constDtype* A,constDtype*B,constDtypebeta,
Dtype* C);
caffe_gpu_gemm(CblasTrans,CblasNoTrans,kernel_dim_,
conv_out_spatial_dim_,conv_out_channels_/group_,
(Dtype)1.,weights +weight_offset_* g,output +output_offset_* g,
(Dtype)0.,col_buff +col_offset_* g);