學(xué)習(xí)Caffe(二)使用Caffe

如何使用Caffe

Caffe教程(http://robots.princeton.edu/courses/COS598/2015sp/slides/Caffe/caffe_tutorial.pdf

預(yù)備知識

Google Protocol Buffer

https://developers.google.com/protocol-buffers/docs/cpptutorial
Caffe數(shù)據(jù)的讀取庐冯、運算孽亲、存儲都是采用Google Protocol Buffer來進(jìn)行的。PB是一種輕便肄扎、高效的結(jié)構(gòu)化數(shù)據(jù)存儲格式墨林,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化,很適合做數(shù)據(jù)存儲或 RPC 數(shù)據(jù)交換格式犯祠。它可用于通訊協(xié)議旭等、數(shù)據(jù)存儲等領(lǐng)域的語言無關(guān)、平臺無關(guān)衡载、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式搔耕。是一種效率和兼容性都很優(yōu)秀的二進(jìn)制數(shù)據(jù)傳輸格式,目前提供了 C++痰娱、Java弃榨、Python 三種語言的 API。Caffe采用的是C++和Python的API梨睁。

轉(zhuǎn)載自https://github.com/shicai/Caffe_Manual/blob/master/ReadMe.md

初始化網(wǎng)絡(luò)

#include "caffe/caffe.hpp"
#include <string>
#include <vector>
using namespace caffe;

char *proto = "H:\\Models\\Caffe\\deploy.prototxt"; /* 加載CaffeNet的配置 */
Phase phase = TEST; /* or TRAIN */
Caffe::set_mode(Caffe::CPU);
// Caffe::set_mode(Caffe::GPU);
// Caffe::SetDevice(0);

//! Note: 后文所有提到的net鲸睛,都是這個net
boost::shared_ptr< Net<float> > net(new caffe::Net<float>(proto, phase));

加載已訓(xùn)練好的模型

char *model = "H:\\Models\\Caffe\\bvlc_reference_caffenet.caffemodel";    
net->CopyTrainedLayersFrom(model);

讀取模型中的每層的結(jié)構(gòu)配置參數(shù)

char *model = "H:\\Models\\Caffe\\bvlc_reference_caffenet.caffemodel";
NetParameter param;
ReadNetParamsFromBinaryFileOrDie(model, &param);
int num_layers = param.layer_size();
for (int i = 0; i < num_layers; ++i)
{
    // 結(jié)構(gòu)配置參數(shù):name,type坡贺,kernel size官辈,pad箱舞,stride等
    LOG(ERROR) << "Layer " << i << ":" << param.layer(i).name() << "\t" << param.layer(i).type();
    if (param.layer(i).type() == "Convolution")
    {
        ConvolutionParameter conv_param = param.layer(i).convolution_param();
        LOG(ERROR) << "\t\tkernel size: " << conv_param.kernel_size()
            << ", pad: " << conv_param.pad()
            << ", stride: " << conv_param.stride();
    }
}

讀取圖像均值

char *mean_file = "H:\\Models\\Caffe\\imagenet_mean.binaryproto";
Blob<float> image_mean;
BlobProto blob_proto;
const float *mean_ptr;
unsigned int num_pixel;

bool succeed = ReadProtoFromBinaryFile(mean_file, &blob_proto);
if (succeed)
{
    image_mean.FromProto(blob_proto);
    num_pixel = image_mean.count(); /* NCHW=1x3x256x256=196608 */
    mean_ptr = (const float *) image_mean.cpu_data();
}

根據(jù)指定數(shù)據(jù),前向傳播網(wǎng)絡(luò)

//! Note: data_ptr指向已經(jīng)處理好(去均值的拳亿,符合網(wǎng)絡(luò)輸入圖像的長寬和Batch Size)的數(shù)據(jù)
void caffe_forward(boost::shared_ptr< Net<float> > & net, float *data_ptr)
{
    Blob<float>* input_blobs = net->input_blobs()[0];
    switch (Caffe::mode())
    {
    case Caffe::CPU:
        memcpy(input_blobs->mutable_cpu_data(), data_ptr,
            sizeof(float) * input_blobs->count());
        break;
    case Caffe::GPU:
        cudaMemcpy(input_blobs->mutable_gpu_data(), data_ptr,
            sizeof(float) * input_blobs->count(), cudaMemcpyHostToDevice);
        break;
    default:
        LOG(FATAL) << "Unknown Caffe mode.";
    } 
    net->ForwardPrefilled();
}

根據(jù)Feature層的名字獲取其在網(wǎng)絡(luò)中的Index

//! Note: Net的Blob是指晴股,每個層的輸出數(shù)據(jù),即Feature Maps
// char *query_blob_name = "conv1";
unsigned int get_blob_index(boost::shared_ptr< Net<float> > & net, char *query_blob_name)
{
    std::string str_query(query_blob_name);    
    vector< string > const & blob_names = net->blob_names();
    for( unsigned int i = 0; i != blob_names.size(); ++i ) 
    { 
        if( str_query == blob_names[i] ) 
        { 
            return i;
        } 
    }
    LOG(FATAL) << "Unknown blob name: " << str_query;
}

讀取網(wǎng)絡(luò)指定Feature層數(shù)據(jù)

//! Note: 根據(jù)CaffeNet的deploy.prototxt文件肺魁,該Net共有15個Blob电湘,從data一直到prob    
char *query_blob_name = "conv1"; /* data, conv1, pool1, norm1, fc6, prob, etc */
unsigned int blob_id = get_blob_index(net, query_blob_name);

boost::shared_ptr<Blob<float> > blob = net->blobs()[blob_id];
unsigned int num_data = blob->count(); /* NCHW=10x96x55x55 */
const float *blob_ptr = (const float *) blob->cpu_data();

根據(jù)文件列表,獲取特征鹅经,并存為二進(jìn)制文件

詳見get_features.cpp文件:

主要包括三個步驟

  • 生成文件列表寂呛,格式與訓(xùn)練用的類似,每行一個圖像
    包括文件全路徑瞬雹、空格昧谊、標(biāo)簽(沒有的話,可以置0)
  • 根據(jù)train_val或者deploy的prototxt酗捌,改寫生成feat.prototxt
    主要是將輸入層改為image_data層呢诬,最后加上prob和argmax(為了輸出概率和Top1/5預(yù)測標(biāo)簽)
  • 根據(jù)指定參數(shù),運行程序后會生成若干個二進(jìn)制文件胖缤,可以用MATLAB讀取數(shù)據(jù)尚镰,進(jìn)行分析

根據(jù)Layer的名字獲取其在網(wǎng)絡(luò)中的Index

//! Note: Layer包括神經(jīng)網(wǎng)絡(luò)所有層,比如哪廓,CaffeNet共有23層
// char *query_layer_name = "conv1";
unsigned int get_layer_index(boost::shared_ptr< Net<float> > & net, char *query_layer_name)
{
    std::string str_query(query_layer_name);    
    vector< string > const & layer_names = net->layer_names();
    for( unsigned int i = 0; i != layer_names.size(); ++i ) 
    { 
        if( str_query == layer_names[i] ) 
        { 
            return i;
        } 
    }
    LOG(FATAL) << "Unknown layer name: " << str_query;
}

讀取指定Layer的權(quán)重數(shù)據(jù)

//! Note: 不同于Net的Blob是Feature Maps狗唉,Layer的Blob是指Conv和FC等層的Weight和Bias
char *query_layer_name = "conv1";
const float *weight_ptr, *bias_ptr;
unsigned int layer_id = get_layer_index(net, query_layer_name);
boost::shared_ptr<Layer<float> > layer = net->layers()[layer_id];
std::vector<boost::shared_ptr<Blob<float>  >> blobs = layer->blobs();
if (blobs.size() > 0)
{
    weight_ptr = (const float *) blobs[0]->cpu_data();
    bias_ptr = (const float *) blobs[1]->cpu_data();
}

//! Note: 訓(xùn)練模式下,讀取指定Layer的梯度數(shù)據(jù)涡真,與此相似分俯,唯一的區(qū)別是將cpu_data改為cpu_diff

修改某層的Weight數(shù)據(jù)

const float* data_ptr;          /* 指向待寫入數(shù)據(jù)的指針, 源數(shù)據(jù)指針*/
float* weight_ptr = NULL;       /* 指向網(wǎng)絡(luò)中某層權(quán)重的指針哆料,目標(biāo)數(shù)據(jù)指針*/
unsigned int data_size;         /* 待寫入的數(shù)據(jù)量 */
char *layer_name = "conv1";     /* 需要修改的Layer名字 */

unsigned int layer_id = get_layer_index(net, query_layer_name);    
boost::shared_ptr<Blob<float> > blob = net->layers()[layer_id]->blobs()[0];

CHECK(data_size == blob->count());
switch (Caffe::mode())
{
case Caffe::CPU:
    weight_ptr = blob->mutable_cpu_data();
    break;
case Caffe::GPU:
    weight_ptr = blob->mutable_gpu_data();
    break;
default:
    LOG(FATAL) << "Unknown Caffe mode";
}
caffe_copy(blob->count(), data_ptr, weight_ptr);

//! Note: 訓(xùn)練模式下缸剪,手動修改指定Layer的梯度數(shù)據(jù),與此相似
// mutable_cpu_data改為mutable_cpu_diff东亦,mutable_gpu_data改為mutable_gpu_diff

保存新的模型

char* weights_file = "bvlc_reference_caffenet_new.caffemodel";
NetParameter net_param;
net->ToProto(&net_param, false);
WriteProtoToBinaryFile(net_param, weights_file);

Caffe中添加新的層

https://github.com/BVLC/caffe/wiki/Development

這里寫圖片描述

用預(yù)訓(xùn)練網(wǎng)絡(luò)參數(shù)初始化

caffe的參數(shù)初始化是根據(jù)名字從caffemodel讀取的杏节,只要修改名字,自己想要修改的層就能隨機(jī)初始化典阵。

  • 修改名字奋渔,保留前面幾層的參數(shù),同時后面的參數(shù)設(shè)置較高的學(xué)習(xí)率壮啊,基礎(chǔ)學(xué)習(xí)率大概0.00001左右嫉鲸。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市歹啼,隨后出現(xiàn)的幾起案子充坑,更是在濱河造成了極大的恐慌减江,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捻爷,死亡現(xiàn)場離奇詭異,居然都是意外死亡份企,警方通過查閱死者的電腦和手機(jī)也榄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來司志,“玉大人甜紫,你說我怎么就攤上這事÷钤叮” “怎么了囚霸?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長激才。 經(jīng)常有香客問我拓型,道長,這世上最難降的妖魔是什么瘸恼? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任劣挫,我火速辦了婚禮,結(jié)果婚禮上东帅,老公的妹妹穿的比我還像新娘压固。我一直安慰自己,他們只是感情好靠闭,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布帐我。 她就那樣靜靜地躺著,像睡著了一般愧膀。 火紅的嫁衣襯著肌膚如雪拦键。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天扇调,我揣著相機(jī)與錄音矿咕,去河邊找鬼。 笑死狼钮,一個胖子當(dāng)著我的面吹牛碳柱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播熬芜,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼莲镣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涎拉?” 一聲冷哼從身側(cè)響起瑞侮,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤的圆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后半火,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體越妈,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年钮糖,在試婚紗的時候發(fā)現(xiàn)自己被綠了梅掠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡店归,死狀恐怖阎抒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情消痛,我是刑警寧澤且叁,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站秩伞,受9級特大地震影響逞带,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜稠歉,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一掰担、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧怒炸,春花似錦带饱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捏鱼,卻和暖如春执庐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背导梆。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工轨淌, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人看尼。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓递鹉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親藏斩。 傳聞我的和親對象是個殘疾皇子躏结,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,957評論 6 13
  • Caffe GitHub頁面 1. Caffe目錄結(jié)構(gòu) data/用于存放下載的訓(xùn)練數(shù)據(jù)docs/ 幫助文檔exa...
    sixfold_yuan閱讀 1,671評論 3 14
  • 簡介 用簡單的話來定義tcpdump,就是:dump the traffic on a network狰域,根據(jù)使用者...
    保川閱讀 5,956評論 1 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理媳拴,服務(wù)發(fā)現(xiàn)黄橘,斷路器,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 今天周六屈溉,每周放松的日子塞关。挑選了幾個青花瓷的水仙盆,天氣暖起來之后子巾,書房的銅錢草長的很快描孟,已經(jīng)長成郁郁蔥蔥的一滿盆...
    Rene_Yu閱讀 476評論 0 0