欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 人工智能 > caffe >内容正文

caffe

学习caffe(二)使用caffe:caffe加载模型 caffe添加新层 caffe finetune -凯发k8官方网

发布时间:2024/9/21 caffe 18 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 学习caffe(二)使用caffe:caffe加载模型 caffe添加新层 caffe finetune 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

凯发k8官方网的版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014230646/article/details/51934150

caffe教程(http://robots.princeton.edu/courses/cos598/2015sp/slides/caffe/caffe_tutorial.pdf)

google protocol buffer

https://developers.google.com/protocol-buffers/docs/cpptutorial 
caffe数据的读取、运算、存储都是采用google protocol buffer来进行的。pb是一种轻便、高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 rpc 数据交换格式。它可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。是一种效率和兼容性都很优秀的二进制数据传输格式,目前提供了 c 、java、python 三种语言的 api。caffe采用的是c 和python的api。

转载自https://github.com/shicai/caffe_manual/blob/master/readme.md

初始化网络

#include "caffe/caffe.hpp" #include #include 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 > net(new caffe::net(proto, phase));

加载已训练好的模型

char *model = "h:\\models\\caffe\\bvlc_reference_caffenet.caffemodel"; net->copytrainedlayersfrom(model);

读取模型中的每层的结构配置参数

char *model = "h:\\models\\caffe\\bvlc_reference_caffenet.caffemodel"; netparameter param; readnetparamsfrombinaryfileordie(model, ¶m); int num_layers = param.layer_size(); for (int i = 0; i < num_layers; i) {// 结构配置参数: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 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(); }

根据指定数据,前向传播网络

//! note: data_ptr指向已经处理好(去均值的,符合网络输入图像的长宽和batch size)的数据 void caffe_forward(boost::shared_ptr< net > & net, float *data_ptr) {blob* 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(); }

根据feature层的名字获取其在网络中的index

//! note: net的blob是指,每个层的输出数据,即feature maps // char *query_blob_name = "conv1"; unsigned int get_blob_index(boost::shared_ptr< net > & 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; }

读取网络指定feature层数据

//! note: 根据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 = net->blobs()[blob_id]; unsigned int num_data = blob->count(); /* nchw=10x96x55x55 */ const float *blob_ptr = (const float *) blob->cpu_data();

根据文件列表,获取特征,并存为二进制文件

详见get_features.cpp文件:

主要包括三个步骤 
- 生成文件列表,格式与训练用的类似,每行一个图像 
包括文件全路径、空格、标签(没有的话,可以置0) 
- 根据train_val或者deploy的prototxt,改写生成feat.prototxt 
主要是将输入层改为image_data层,最后加上prob和argmax(为了输出概率和top1/5预测标签) 
- 根据指定参数,运行程序后会生成若干个二进制文件,可以用matlab读取数据,进行分析

根据layer的名字获取其在网络中的index

//! note: layer包括神经网络所有层,比如,caffenet共有23层 // char *query_layer_name = "conv1"; unsigned int get_layer_index(boost::shared_ptr< net > & 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的权重数据

//! 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 = net->layers()[layer_id]; std::vector >> blobs = layer->blobs(); if (blobs.size() > 0) {weight_ptr = (const float *) blobs[0]->cpu_data();bias_ptr = (const float *) blobs[1]->cpu_data(); }//! note: 训练模式下,读取指定layer的梯度数据,与此相似,唯一的区别是将cpu_data改为cpu_diff

修改某层的weight数据

const float* data_ptr; /* 指向待写入数据的指针, 源数据指针*/ float* weight_ptr = null; /* 指向网络中某层权重的指针,目标数据指针*/ unsigned int data_size; /* 待写入的数据量 */ char *layer_name = "conv1"; /* 需要修改的layer名字 */unsigned int layer_id = get_layer_index(net, query_layer_name); boost::shared_ptr > 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: 训练模式下,手动修改指定layer的梯度数据,与此相似 // 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);

https://github.com/bvlc/caffe/wiki/development 

caffe的参数初始化是根据名字从caffemodel读取的,只要修改名字,自己想要修改的层就能随机初始化。

  • 修改名字,保留前面几层的参数,同时后面的参数设置较高的学习率,基础学习率大概0.00001左右。

总结

以上是凯发k8官方网为你收集整理的学习caffe(二)使用caffe:caffe加载模型 caffe添加新层 caffe finetune的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

  • 上一篇:
  • 下一篇:
网站地图