使用caffe也有一段時間了,但更多是使用python的介面,使用現有的imagenet訓練好的模型進行分類。為了更好的了解caffe這個框架,也為了提高自己的水平,在對卷積神經網路有了一些研究之後,終於開始研讀caffe的原始碼了,今天看了blob類的一些內容,做個總結。
看過caffe官方文件的話,應該會知道,它可以分為三層:blob、layer、net。blob是乙個四維的陣列,用於儲存資料,包括輸入資料、輸出資料、權值等等;layer層則是神經網路中具體的各層結構,主要是計算的作用,在根據配置檔案初始化結構後,前向計算結果,反向更新引數,都是它要做的,而它的輸入和輸出都是blob資料;net的話,就是多個layer組合而成的有向無環圖結構,也就是具體的網路了。layer和net的**有待深入,尤其是layer的**,caffe實現了差不多40種不同的layer層,裡面有不同的啟用函式,這個要好好研究下。
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/syncedmem.hpp"
#include "caffe/util/math_functions.hpp"
從blob.hpp
包含的四個標頭檔案入手,其中caffe.pb.h
是google protocol buffer根據caffe.proto
自動生成的,可以到src/caffe/proto/caffe.proto
裡看下caffe裡面用到的各個資料的定義,比如blobproto
,datum
,netparameter
等。使用這個protocol buffer看起來確實方便,一方面可以用文字檔案定義結構化的資料型別,另一方面可以生成查詢效率更高、佔空間更小的二進位制檔案,具體的教程可以看看這裡。
在caffe/common.hpp
,主要singleton化caffe類,並封裝了boost和cuda隨機數生成的函式,提供了統一的介面。而在caffe/syncedmem.hpp
中,定義了以下的介面:
inline void caffemallochost(void** ptr, size_t size)
inline void caffefreehost(void* ptr)
主要是分配記憶體和釋放記憶體的。而class syncedmemory
定義了記憶體分配管理和cpu與gpu之間同步的函式,也沒啥特別的。
比較重要的是caffe/util/math_functions.hpp
,這裡面封裝了很多cblas矩陣運算,真是密密麻麻,看的我眼花繚亂、如痴如醉。比如:
void caffe_cpu_gemm(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)
void caffe_cpu_gemv(const cblas_transpose transa, const int m, const int n, const float alpha, const float* a, const float* x, const float beta, float* y)
是對cblas_sgemv
的封裝,實現的矩陣與向量的乘積,結果為y=alphaax+beta*y。
void caffe_axpy(const int n, const float alpha, const float* x, float* y)
封裝了cblas_saxpy
,實現的是y=alpha*x+y
裡面都是諸如此類的函式,基本是些矩陣和向量的一些處理函式。
回到blob
類,裡面定義了data_()
,diff_()
指標,用於存放資料,而num_
,channel_
,height_
,width_
則主要用來做定位offset
和reshape
處理。對於輸入(n, c, h, w)
位置的資料位置為((n*channels_+c)*height_+h)*width_+w
,可以依據位置取data_()
或diff_()
中的資料。
對blob的理解還要結合caffe.proto
裡面blobproto
的定義:
message blobproto
對於blobproto
,可以看到定義了四個optional
的int32
型別的名字(name)num
、channels
、height
和width
,optional
意味著blob
可以有乙個或者沒有這個引數,每個名字(name)後面都有乙個數字,這個數字是其名字的乙個標籤。這個數字就是用來在生成的二進位制檔案中搜尋查詢的標籤(怪不得會快呢^_^)。關於這個數字,1到15會花費1byte的編碼空間,16到2047花費2byte。所以一般建議把那些頻繁使用的名字的標籤設為1到15之間的值~而後面的repeated
意味著float
型別的data
和diff
可以重複任意次,而加上[packed = true]
是為了更高效的編碼。
到這裡基本上blob
就很清楚了,主要資料有兩個data
和diff
,用num
、channels
、height
和width
這四個維度來確定資料的具體位置,做一些資料查詢和blobreshape
的操作。
關於blob就這麼多內容,畢竟就是乙個統一的資料訪問介面,後續會重點讀一下layer的原始碼,畢竟各層的輸入輸出和計算更新過程都在裡面,還需要補充一些相關的知識~~
目前的感受,是學到了一些封裝的手法,可以看看封裝cblas函式的那個檔案,以及cpu和gpu一些介面的封裝上;另一方面是對於protocol buffer
有了一些了解,目前看起來確實方便,以後如果遇到類似的場景可以試著用一下~~
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型別它...