深度学习:Neural Network Layers Understanding
我想做又應該做的事,都會做到;我想做卻不應做的事,都會戒掉。
Inner Product Layer
Inner Product Layer即全連接層,對于IP層的理解,可以簡單的將其視為矩陣1*N和矩陣N*M相乘后得到1*M的維度向量。
舉個簡單的例子,比如輸入全連接層的是一個3*56*56維度的數據,假設未知的權重維度為N*M,假設全連接層的輸出為num_ouput = 4096,為了計算全連接層的輸出,全連接層會將輸入的數據3*56*56?reshape 成為1*N的形式,即1x(56x56x3) = 1x9408,所以:
N = 9408 M = num_ouput = 4096由此,我們做了一個(1x9408)矩陣和(9408x4096)矩陣的乘法。如果num_output的值改變成為100,則做的是一個(1x9408)矩陣和(9408x100)矩陣的乘法。Inner Product layer(常被稱為全連接層)將輸入視為一個vector,輸出也是一個vector(height和width被設為1)。下面是IP層的示意圖
圖片摘自Why GEMM is at the heart of deep learning
增大num_output會使得模型需要學習的權重參數增加。IP層一個典型的例子:
layer {name: "ip1"type: "InnerProduct"bottom: "pool2"top: "ip1"# learning rate and decay multipliers for the weightsparam {lr_mult: 1}# learning rate and decay multipliers for the biasesparam {lr_mult: 2}inner_product_param {num_output: 500weight_filler {type: "xavier"}bias_filler {type: "constant"}} }有了上面對IP層的理解,對caffe inner_product_layer.cpp中Forward的理解就比較自然了。下面是Caffe的IP層在CPU上的實現:
template <typename Dtype> void InnerProductLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) {const Dtype* bottom_data = bottom[0]->cpu_data();Dtype* top_data = top[0]->mutable_cpu_data();const Dtype* weight = this->blobs_[0]->cpu_data();caffe_cpu_gemm<Dtype>(CblasNoTrans, transpose_ ? CblasNoTrans : CblasTrans,M_, N_, K_, (Dtype)1.,bottom_data, weight, (Dtype)0., top_data);if (bias_term_) {caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, M_, N_, 1, (Dtype)1.,bias_multiplier_.cpu_data(),this->blobs_[1]->cpu_data(), (Dtype)1., top_data);} }上面完成矩陣與矩陣相乘的函數是caffe_cpu_gemm<Dtype>(見math_functions.cpp),caffe_cpu_gemm函數矩陣相乘的具體數學表示形式為:
C=alpha?TransA(A)?TransB(B)+beta?CC=alpha?TransA(A)?TransB(B)+beta?C
上式中TransX是對X做的一種矩陣變換,比如轉置、共軛等,具體是cblas.h中定義的為枚舉類型。在math_functions.cpp中,除了定義矩陣與矩陣相乘的caffe_cpu_gemm外,還定義了矩陣與向量的相乘,具體的函數為caffe_cpu_gemv,其數學表示形式為:
C=alpha?TransA(A)?y+beta?yC=alpha?TransA(A)?y+beta?y
上面表達式中,y是向量,不是標量。
參考
GEMM
在上面的IP層中,我們已經涉及到了GEMM的知識,在這一小節里面,不妨對該知識點做一個延伸。
GEMM是BLAS (Basic Linear Algebra Subprograms)庫的一部分,該庫在1979年首次創建。為什么GEMM在深度學習中如此重要呢?我們可以先來看一個圖:
圖片摘自Yangqing Jia的thesis
上圖是采用AlexNet對CNN網絡中不同layer GPU和CPU的時間消耗,從更底層的實現可以看到CNN網絡的主要時間消耗用在了FC (for fully-connected)和Conv (for convolution),而FC和Conv在實現上都將其轉為了矩陣相乘的形式。舉個例子:
圖片摘自cuDNN: Efficient Primitives for Deep Learning
上面Conv在Caffe中具體實現的時候,會將每一個小的patch拉成一個向量,很多patch構成的向量會構成一個大的矩陣,同樣的對于多個卷積核展成一個矩陣形式,從而將圖像的卷積轉成了矩陣與矩陣的相乘(更形象化的解釋參閱在 Caffe 中如何計算卷積?)。上面可以看到在FC和Conv上消耗的時間GPU占95%,CPU上占89%。因而GEMM的實現高效與否對于整個網絡的效率有很大的影響。
那么什么是GEMM呢?GEMM的全稱是GEneral Matrix to Matrix Multiplication,正如其字面意思所表達的,GEMM即表示兩個輸入矩陣進行相乘,得到一個輸出的矩陣。兩個矩陣在進行相乘的時候,通常會進行百萬次的浮點運算。對于一個典型網絡中的某一層,比如一個256 row1152 column的矩陣和一個1152 row192 column的矩陣,二者相乘57 million (256 x 1152 x 192)的浮點運算。因而,通常我們看到的情形是,一個網絡在處理一幀的時候,需要幾十億的FLOPs(Floating-point operations per second,每秒浮點計算)。
既然知道了GEMM是限制整個網絡時間消耗的主要部分,那么我們是不是可以對GEMM做優化調整呢?答案是否定的,GEMM采用Fortran編程語言實現,經過了科學計算編程人員幾十年的優化,性能已經極致,所以很難再去進一步的優化,在Nvidia的論文cuDNN: Efficient Primitives for Deep Learning中指出了還存在著其他的一些方法,但是他們最后采用的還是改進的GEMM版本實現。GEMM可匹敵的對手是傅里葉變換,將卷積轉為頻域的相乘,但是由于在圖像的卷積中存在strides,使得傅里葉變換方式很難保持高效。
from:?http://yongyuan.name/blog/neural-network-layers-understanding.html?
總結
以上是生活随笔為你收集整理的深度学习:Neural Network Layers Understanding的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像检索:图像拷贝检索PHash改进方案
- 下一篇: 图像检索:layer选择与fine-tu