日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Caffe源码解析1:Blob

發(fā)布時(shí)間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Caffe源码解析1:Blob 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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庫的一個(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è)日志庫,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ù)庫的調(diào)用,實(shí)現(xiàn)的功能是

?

Y=alpha?X+beta?YY=alpha?X+beta?Y


也就是blob里面的data部分減去diff部分

void FromProto(const BlobProto& proto, bool reshape = true); void ToProto(BlobProto* proto, bool write_diff = false) const;

這兩個(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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。