Caffe源码解析1:Blob
from:https://www.cnblogs.com/louyihang-loves-baiyan/p/5149628.html
轉(zhuǎn)載請(qǐng)注明出處,樓燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/
首先看到的是Blob這個(gè)類,Blob是作為Caffe中數(shù)據(jù)流通的一個(gè)基本類,網(wǎng)絡(luò)各層之間的數(shù)據(jù)是通過Blob來傳遞的。這里整個(gè)代碼是非常規(guī)范的,基本上條件編譯,命名空間,模板類,各種不太經(jīng)常看到的關(guān)鍵字如exlicit,inline等等。
首先提一下explicit關(guān)鍵字的作用是禁止單參數(shù)構(gòu)造函數(shù)的隱式轉(zhuǎn)換,具體含義谷歌即可。還有inline的作用,iniline主要是將代碼進(jìn)行復(fù)制,擴(kuò)充,會(huì)使代碼總量上升,好處就是可以節(jié)省調(diào)用的開銷,能提高執(zhí)行效率。
1主要變量
shared_ptr<SyncedMemory> data_; shared_ptr<SyncedMemory> diff_; shared_ptr<SyncedMemory> shape_data_; vector<int> shape_; int count_; int capacity_;BLob只是一個(gè)基本的數(shù)據(jù)結(jié)構(gòu),因此內(nèi)部的變量相對(duì)較少,首先是data_指針,指針類型是shared_ptr,屬于boost庫(kù)的一個(gè)智能指針,這一部分主要用來申請(qǐng)內(nèi)存存儲(chǔ)data,data主要是正向傳播的時(shí)候用的。同理,diff_主要用來存儲(chǔ)偏差,update data,shape_data和shape_都是存儲(chǔ)Blob的形狀,一個(gè)是老版本一個(gè)是新版本。count表示Blob中的元素個(gè)數(shù),也就是個(gè)數(shù)*通道數(shù)*高度*寬度,capacity表示當(dāng)前的元素個(gè)數(shù),因?yàn)锽lob可能會(huì)reshape。
2主要函數(shù)
template <typename Dtype> class Blob {public:Blob(): data_(), diff_(), count_(0), capacity_(0) {}/// @brief Deprecated; use <code>Blob(const vector<int>& shape)</code>.explicit Blob(const int num, const int channels, const int height,const int width);explicit Blob(const vector<int>& shape);/// @brief Deprecated; use <code>Reshape(const vector<int>& shape)</code>.void Reshape(const int num, const int channels, const int height,const int width);其中Blob作為一個(gè)最基礎(chǔ)的類,其中構(gòu)造函數(shù)開辟一個(gè)內(nèi)存空間來存儲(chǔ)數(shù)據(jù),Reshape函數(shù)在Layer中的reshape或者forward操作中來adjust dimension。同時(shí)在改變Blob大小時(shí),內(nèi)存將會(huì)被重新分配如果內(nèi)存大小不夠了,并且額外的內(nèi)存將不會(huì)被釋放。對(duì)input的blob進(jìn)行reshape,如果立馬調(diào)用Net::Backward是會(huì)出錯(cuò)的,因?yàn)閞eshape之后,要么Net::forward或者Net::Reshape就會(huì)被調(diào)用來將新的input shape 傳播到高層
Blob類里面有重載很多個(gè)count()函數(shù),主要還是為了統(tǒng)計(jì)Blob的容量(volume),或者是某一片(slice),從某個(gè)axis到具體某個(gè)axis的shape乘積。
inline int count(int start_axis, int end_axis)并且Blob的Index是可以從負(fù)坐標(biāo)開始讀的,這一點(diǎn)跟Python好像
inline int CanonicalAxisIndex(int axis_index)對(duì)于Blob中的4個(gè)基本變量num,channel,height,width可以直接通過shape(0),shape(1),shape(2),shape(3)來訪問。
計(jì)算offset
inline int offset(const int n, const int c = 0, const int h = 0, const int w = 0) inline int offset(const vector<int>& indices)offset計(jì)算的方式也支持兩種方式,一種直接指定n,c,h,w或者放到一個(gè)vector中進(jìn)行計(jì)算,偏差是根據(jù)對(duì)應(yīng)的n,c,h,w,返回的offset是((n * channels() + c) * height() + h) * width() + w
其實(shí)里面稍加留意可以看到有很多的
CHECK_GE CHECK_LE CHECK_EQ ....等等看意思就知道了,肯定是在做比較Geater or Eqal這樣的意思。這其實(shí)是GLOG,谷歌的一個(gè)日志庫(kù),Caffe里面用用了大量這樣的宏,看起來也比較直觀
void CopyFrom(const Blob<Dtype>& source, bool copy_diff = false,bool reshape = false);從一個(gè)blob中copy數(shù)據(jù) ,通過開關(guān)控制是否copy_diff,如果是False則copy data。reshape控制是否需要reshape。好我們接著往下看
inline Dtype data_at(const int n, const int c, const int h, const int w) inline Dtype diff_at(const int n, const int c, const int h, const int w) inline Dtype data_at(const vector<int>& index) inline Dtype diff_at(const vector<int>& index) inline const shared_ptr<SyncedMemory>& data() inline const shared_ptr<SyncedMemory>& diff()這一部分函數(shù)主要通過給定的位置訪問數(shù)據(jù),根據(jù)位置計(jì)算與數(shù)據(jù)起始的偏差offset,在通過cpu_data*指針獲得地址。下面幾個(gè)函數(shù)都是獲得
const Dtype* cpu_data() const; void set_cpu_data(Dtype* data); const int* gpu_shape() const; const Dtype* gpu_data() const; const Dtype* cpu_diff() const; const Dtype* gpu_diff() const; Dtype* mutable_cpu_data(); Dtype* mutable_gpu_data(); Dtype* mutable_cpu_diff(); Dtype* mutable_gpu_diff();可以看到這里有data和diff兩類數(shù)據(jù),而這個(gè)diff就是我們所熟知的偏差,前者主要存儲(chǔ)前向傳遞的數(shù)據(jù),而后者存儲(chǔ)的是反向傳播中的梯度
void Update();看到update里面面調(diào)用了
caffe_axpy<float>(const int N, const float alpha, const float* X,float* Y) { cblas_saxpy(N, alpha, X, 1, Y, 1); }這個(gè)函數(shù)在caffe的util下面的match-functions.cpp里面,主要是負(fù)責(zé)了線性代數(shù)庫(kù)的調(diào)用,實(shí)現(xiàn)的功能是
?
Y=alpha?X+beta?YY=alpha?X+beta?Y
也就是blob里面的data部分減去diff部分
這兩個(gè)函數(shù)主要是將數(shù)據(jù)序列化,存儲(chǔ)到BlobProto,這里說到Proto是谷歌的一個(gè)數(shù)據(jù)序列化的存儲(chǔ)格式,可以實(shí)現(xiàn)語言、平臺(tái)無關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式。Caffe里面數(shù)據(jù)的存儲(chǔ)都采用這一結(jié)構(gòu),這里就不深入展開,具體可以參照這篇文章,對(duì)于proto的序列化和反序列都講解的非常詳細(xì)http://***/Article/34963
Dtype asum_data() const;//計(jì)算data的L1范數(shù) Dtype asum_diff() const;//計(jì)算diff的L1范數(shù) Dtype sumsq_data() const;//計(jì)算data的L2范數(shù) Dtype sumsq_diff() const;//計(jì)算diff的L2范數(shù) void scale_data(Dtype scale_factor);//將data部分乘以一個(gè)因子 void scale_diff(Dtype scale_factor);//將diff部分乘一個(gè)因子這幾個(gè)函數(shù)是一些零散的功能,一看就懂。
void ShareData(const Blob& other); void ShareData(const Blob& other);這兩個(gè)函數(shù)看名字就知道了一個(gè)是共享data,一個(gè)是共享diff,具體就是將別的blob的data和響應(yīng)的diff指針給這個(gè)Blob,實(shí)現(xiàn)數(shù)據(jù)的共享。同時(shí)需要注意的是這個(gè)操作會(huì)引起這個(gè)Blob里面的SyncedMemory被釋放,因?yàn)閟hared_ptr指針被用=重置的時(shí)候回調(diào)用響應(yīng)的析構(gòu)器。
bool ShapeEquals(const BlobProto& other);這函數(shù)就不用說了,比較兩個(gè)Blob形狀是否相同
好了,基本上Blob的主要參數(shù)功能基本就涵蓋在里面了,以上只是我的拙見,如有紕漏,還望指出,萬分感謝。
總結(jié)
以上是生活随笔為你收集整理的Caffe源码解析1:Blob的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vim命令下显示行号
- 下一篇: 步进电机参数计算