vision_layer裡面主要是包括了一些關於一些視覺上的操作,比如卷積、反卷積、池化等等。這裡的類跟data layer一樣好很多種繼承關係。主要包括了這幾個類,其中cudnn分別是cuda版本,這裡先不討論,在這裡先討論convolutionlayer
其繼承自layer,是乙個卷積以及反卷積操作的基類,首先我們來看baseconvolutionlayer的layersetup函式
void baseconvolutionlayer::layersetup(const vector*>& bottom,
const vector*>& top)
//首先這裡主要是在配置卷積kernel 的size,padding,stride以及inputs
convolutionparameter conv_param = this->layer_param_.convolution_param();
force_nd_im2col_ = conv_param.force_nd_im2col();
channel_axis_ = bottom[0]->canonicalaxisindex(conv_param.axis());
const int first_spatial_axis = channel_axis_ + 1;
const int num_axes = bottom[0]->num_axes();
num_spatial_axes_ = num_axes - first_spatial_axis;
check_ge(num_spatial_axes_, 0);
vectorbottom_dim_blob_shape(1, num_spatial_axes_ + 1);
vectorspatial_dim_blob_shape(1, std::max(num_spatial_axes_, 1));
// 設定kernel的dimensions
kernel_shape_.reshape(spatial_dim_blob_shape);
int* kernel_shape_data = kernel_shape_.mutable_cpu_data();
接著是設定相應的stride dimensions,對於2d,設定在h和w方向上的stride,**太長列出簡要的
pad_.reshape(spatial_dim_blob_shape);
int* pad_data = pad_.mutable_cpu_data();
pad_data[0] = conv_param.pad_h();
pad_data[1] = conv_param.pad_w();
......一堆if else判斷
對於kernel的pad也做相應設定
pad_.reshape(spatial_dim_blob_shape);
int* pad_data = pad_.mutable_cpu_data();
pad_data[0] = conv_param.pad_h();
pad_data[1] = conv_param.pad_w();
接下來是對widhts 和bias左設定和填充,其中blob[0]裡面存放的是filter weights,而blob[1]裡面存放的是biases,當然biases是可選的,也可以沒有
//設定相應的shape,並檢查
vectorweight_shape(2);
weight_shape[0] = conv_out_channels_;
weight_shape[1] = conv_in_channels_ / group_;
bias_term_ = this->layer_param_.convolution_param().bias_term();
vectorbias_shape(bias_term_, num_output_);
//填充權重
this->blobs_[0].reset(new blob(weight_shape));
shared_ptr> weight_filler(getfiller(
this->layer_param_.convolution_param().weight_filler()));
weight_filler->fill(this->blobs_[0].get());
//填充偏置項
if (bias_term_)
convolutionlayer
convolutionlayer繼承了baseconvolutionlayer,主要作用就是將一副image做卷積操作,使用學到的filter的引數和biaes。同時在caffe裡面,卷積操作做了優化,變成了乙個矩陣相乘的操作。其中有兩個比較主要的函式是im2col以及col2im。
圖中上半部分是乙個傳統卷積,下圖是乙個矩陣相乘的版本
下圖是在乙個卷積層中將卷積操作展開的具體操作過程,他裡面按照卷積核的大小取資料然後展開,在同一張圖里的不同卷積核選取的逐行擺放,不同n的話,就在同一行後面繼續拼接,不同個可以是多個通道,但是需要注意的是同一行裡面每一段都應該對應的是原圖中中乙個位置的卷積視窗。
對於卷積層中的卷積操作,還有乙個group的概念要說明一下,groups是代表filter 組的個數。引入gruop主要是為了選擇性的連線卷基層的輸入端和輸出端的channels,否則引數會太多。每乙個group 和1/ group的input 通道和 1/group 的output通道進行卷積操作。比如有4個input, 8個output,那麼1-4屬於第一組,5-8屬於第二個gruop
convolutionlayer裡面,主要重寫了forward_cpu和backward_cpu
void convolutionlayer::forward_cpu(const vector*>& bottom,
const vector*>& top) }}}
可以看到其實這裡面他呼叫了forward_cpu_gemm,而這個函式內部又呼叫了math_function裡面的caffe_cpu_gemm的通用矩陣相乘介面,gemm的全稱是general matrix matrix multiply。其基本形式如下:
\[c=alpha*op( a )*op( b ) + beta*c,
\]
template void convolutionlayer::backward_cpu(const vector*>& top,
const vector& propagate_down, const vector*>& bottom)
}//計算weight
if (this->param_propagate_down_[0] || propagate_down[i])
//計算botttom資料的梯度,下後傳遞
if (propagate_down[i]) }}
}}
caffe原始碼解析
目錄目錄 簡單介紹 主要函式readprotofromtextfile 函式 writeprotototextfile 函式 readprotofrombinaryfile 函式 writeprototobinaryfile 函式 readimagetocvmat 函式 matchext 函式 cv...
caffe原始碼解析 一
用si載入 後 首先從caffe layer的實現看起,不同框架下最大的差異就在於層的實現也決定了層的靈活性 layer可以看成是乙個基類,下面存在data layer,activation neuron layers,vision layer,common layers,loss layer,各個...
Caffe原始碼解析6 Neuron Layer
neuronlayer,顧名思義這裡就是神經元,啟用函式的相應層。我們知道在blob進入啟用函式之前和之後他的size是不會變的,而且啟用值也就是輸出 y 只依賴於相應的輸入 x 在caffe裡面所有的layer的實現都放在src資料夾下的layer資料夾中,基本上很多文章裡應用到的layer型別它...