1. 程式人生 > >8、編寫自己的CNN框架(初級)

8、編寫自己的CNN框架(初級)

一、矩陣運算

(1)庫:cblas

void cblas_gemm (
const enum CBLAS_ORDER Order,  // Specifies row-major (C) or column-major (Fortran) data ordering.
#eg:
#Matrix A =
#[1 2 3]
#[4 5 6]
#Row-major stores values as {1,2,3,4,5,6}
#Col-major stores values as {1, 4, 2, 5, 3, 6}
#設定矩陣讀取方式,預設Row-major。
const enum CBLAS_TRANSPOSE TransA,//Specifies whether to transpose matrix A.
const enum CBLAS_TRANSPOSE TransB,
#是否轉置矩陣A,B
const int M,   //Number of rows in matrices A and C.
const int N,//Number of rows in matrices A and C.
#矩陣運算的行數
const int K,  //Number of columns in matrix A; number of rows in matrix B
const float alpha, //Scaling factor for the product of matrices A and B
const float *A, 
const int lda,  //The size of the first dimention of matrix A; if you are passing a matrix A[m][n], the value should be m.  stride
const float *B,  
const int ldb,  //The size of the first dimention of matrix B; if you are passing a matrix B[m][n], the value should be m.
const float beta,  //Scaling factor for matrix C.
float *C,
const int ldc    //The size of the first dimention of matrix C; if you are passing a matrix C[m][n], the value should be m.
);

(2)Caffe 中使用了cblas_gemm的使用例子:      

  •          caffe_cpu_gemm()
  •          forward_cpu_gemm()
  •          forward_cpu_bias()

caffe/src/caffe/layers/cudnn_conv_layer.cpp 

template <typename Dtype>

void ConvolutionLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) 

    { const Dtype* weight = this->blobs_[0]->cpu_data();
      for (int i = 0; i < bottom.size(); ++i)
      {
	const Dtype* bottom_data = bottom[i]->cpu_data();
	Dtype* top_data = top[i]->mutable_cpu_data();
        for (int n = 0; n < this->num_; ++n) 
         {
	   this->forward_cpu_gemm(bottom_data + n * this->bottom_dim_, weight,
	   top_data + n * this->top_dim_);//把現在的矩陣和權重矩陣相乘,輸出到top_dim,
	   if (this->bias_term_) 
             {
	        const Dtype* bias = this->blobs_[1]->cpu_data();
        	this->forward_cpu_bias(top_data + n * this->top_dim_, bias);
	     }
	  }
       }
     }
template <typename Dtype>
	void BaseConvolutionLayer<Dtype>::forward_cpu_gemm(const Dtype* input,
	const Dtype* weights, Dtype* output, bool skip_im2col)
        {
	  const Dtype* col_buff = input;
	  if (!is_1x1_) {
	  if (!skip_im2col) 
          {
	  conv_im2col_cpu(input, col_buffer_.mutable_cpu_data());
	  }
	  col_buff = col_buffer_.cpu_data();
	}
	for (int g = 0; g < group_; ++g) 
        {
	  caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, conv_out_channels_ /
	  group_, conv_out_spatial_dim_, kernel_dim_,
	  (Dtype)1., weights + weight_offset_ * g, col_buff + col_offset_ * g,
	  (Dtype)0., output + output_offset_ * g);
	}
	}

caffe/src/caffe/util/math_functions.cpp 

template<>
	void caffe_cpu_gemm<float>(const CBLAS_TRANSPOSE TransA,
	const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K,
	const float alpha, const float* A, const float* B, const float beta,
	float* C) 
       {
	int lda = (TransA == CblasNoTrans) ? K : M;
	int ldb = (TransB == CblasNoTrans) ? N : K;
	cblas_sgemm(CblasRowMajor, TransA, TransB, M, N, K, alpha, A, lda, B,
	ldb, beta, C, N);//封裝模組。
        }

 二、Caffe 的最小版本:四個變數+兩個函式

資料結構Blob:

Struct Blob{
vector<int>shape_;//Blob的形狀[num,channel,width,height]
float *data_;//資料,向前傳播使用
float *diff_;//梯度,先後傳播使用
};

層Layer:

class Layer{
public:
void forward(vector<Blob>*bottom,vector<Blob>*top);
Void backward(vector<Blob>*bottom,vector<Blob>*top);
protected:
vector<Blob>blob_;//存放學習引數,如weight,bias,一般呼叫0或1,全卷積中用到
}

使用課件定義的簡化版的Blob、Layer和CBLAS庫,嘗試自己編寫一個CNN框架,以LeNet的網路結構為例。

#安裝json

$ sudo apt-get install libjsoncpp-dev

#安裝先行運算庫

#armadillo-7.500.2目錄下

#cmake .

#make all

$ sudo make install

#編譯MinNet

#在MiniNet/cpp目錄下

$ make all