caffe-----使用C++ 提取网络中间层特征数据
最近实验,想要在c++下知道网络中间某一层的特征数据情况,查找了相关资料,记录一下。
其实在caffe框架里面是包含这种操作的,可以模仿tools/extract_features.cpp中的操作来得到网络中间的特征数据。
首先看下extract_features.cpp是如何写的。
template<typename Dtype>
int feature_extraction_pipeline(int argc, char** argv) {
::google::InitGoogleLogging(argv[]);
const int num_required_args = ;
if (argc < num_required_args) {
LOG(ERROR)<<
"This program takes in a trained network and an input data layer, and then"
" extract features of the input data produced by the net.\n"
"Usage: extract_features pretrained_net_param"
" feature_extraction_proto_file extract_feature_blob_name1[,name2,...]"
" save_feature_dataset_name1[,name2,...] num_mini_batches db_type"
" [CPU/GPU] [DEVICE_ID=0]\n"
"Note: you can extract multiple features in one pass by specifying"
" multiple feature blob names and dataset names separated by ','."
" The names cannot contain white space characters and the number of blobs"
" and datasets must be equal.";
return ;
}
int arg_pos = num_required_args; arg_pos = num_required_args;
if (argc > arg_pos && strcmp(argv[arg_pos], "GPU") == ) {
LOG(ERROR)<< "Using GPU";
int device_id = ;
if (argc > arg_pos + ) {
device_id = atoi(argv[arg_pos + ]);
CHECK_GE(device_id, );
}
LOG(ERROR) << "Using Device_id=" << device_id;
Caffe::SetDevice(device_id);
Caffe::set_mode(Caffe::GPU);
} else {
LOG(ERROR) << "Using CPU";
Caffe::set_mode(Caffe::CPU);
} arg_pos = ; // the name of the executable
std::string pretrained_binary_proto(argv[++arg_pos]); // Expected prototxt contains at least one data layer such as
// the layer data_layer_name and one feature blob such as the
// fc7 top blob to extract features.
/*
layers {
name: "data_layer_name"
type: DATA
data_param {
source: "/path/to/your/images/to/extract/feature/images_leveldb"
mean_file: "/path/to/your/image_mean.binaryproto"
batch_size: 128
crop_size: 227
mirror: false
}
top: "data_blob_name"
top: "label_blob_name"
}
layers {
name: "drop7"
type: DROPOUT
dropout_param {
dropout_ratio: 0.5
}
bottom: "fc7"
top: "fc7"
}
*/
std::string feature_extraction_proto(argv[++arg_pos]);
boost::shared_ptr<Net<Dtype> > feature_extraction_net(
new Net<Dtype>(feature_extraction_proto, caffe::TEST));
feature_extraction_net->CopyTrainedLayersFrom(pretrained_binary_proto);//初始化网络 std::string extract_feature_blob_names(argv[++arg_pos]);
std::vector<std::string> blob_names;
boost::split(blob_names, extract_feature_blob_names, boost::is_any_of(",")); std::string save_feature_dataset_names(argv[++arg_pos]);
std::vector<std::string> dataset_names;
boost::split(dataset_names, save_feature_dataset_names,
boost::is_any_of(","));
CHECK_EQ(blob_names.size(), dataset_names.size()) <<
" the number of blob names and dataset names must be equal";
size_t num_features = blob_names.size(); for (size_t i = ; i < num_features; i++) {
CHECK(feature_extraction_net->has_blob(blob_names[i]))
<< "Unknown feature blob name " << blob_names[i]
<< " in the network " << feature_extraction_proto;
} int num_mini_batches = atoi(argv[++arg_pos]); std::vector<boost::shared_ptr<db::DB> > feature_dbs;
std::vector<boost::shared_ptr<db::Transaction> > txns;
const char* db_type = argv[++arg_pos];
for (size_t i = ; i < num_features; ++i) {
LOG(INFO)<< "Opening dataset " << dataset_names[i];
boost::shared_ptr<db::DB> db(db::GetDB(db_type));
db->Open(dataset_names.at(i), db::NEW);
feature_dbs.push_back(db);
boost::shared_ptr<db::Transaction> txn(db->NewTransaction());
txns.push_back(txn);
} LOG(ERROR)<< "Extracting Features"; Datum datum;
std::vector<int> image_indices(num_features, );
for (int batch_index = ; batch_index < num_mini_batches; ++batch_index) {
feature_extraction_net->Forward();//首先进行前传 这样才能有中间数据
for (int i = ; i < num_features; ++i) {
const boost::shared_ptr<Blob<Dtype> > feature_blob =
feature_extraction_net->blob_by_name(blob_names[i]);//通过名字查找blob
int batch_size = feature_blob->num();
int dim_features = feature_blob->count() / batch_size;
const Dtype* feature_blob_data;
for (int n = ; n < batch_size; ++n) {
datum.set_height(feature_blob->height());
datum.set_width(feature_blob->width());
datum.set_channels(feature_blob->channels());
datum.clear_data();
datum.clear_float_data();
feature_blob_data = feature_blob->cpu_data() +
feature_blob->offset(n);
for (int d = ; d < dim_features; ++d) {
datum.add_float_data(feature_blob_data[d]);//将feature_blob的数据都保存到datum里
}
string key_str = caffe::format_int(image_indices[i], ); string out;
CHECK(datum.SerializeToString(&out));//将datum保存到本地
txns.at(i)->Put(key_str, out);
++image_indices[i];
if (image_indices[i] % == ) {
txns.at(i)->Commit();
txns.at(i).reset(feature_dbs.at(i)->NewTransaction());
LOG(ERROR)<< "Extracted features of " << image_indices[i] <<
" query images for feature blob " << blob_names[i];
}
} // for (int n = 0; n < batch_size; ++n)
} // for (int i = 0; i < num_features; ++i)
} // for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index)
// write the last batch
for (int i = ; i < num_features; ++i) {
if (image_indices[i] % != ) {
txns.at(i)->Commit();
}
LOG(ERROR)<< "Extracted features of " << image_indices[i] <<
" query images for feature blob " << blob_names[i];
feature_dbs.at(i)->Close();
} LOG(ERROR)<< "Successfully extracted the features!";
return ;
}
主要三个核心步骤:
1.初始化网络,并前传,
net->Forward()
2.通过blob的名字(prototxt中的name)来得到blob数据,
const boost::shared_ptr<Blob<Dtype> > feature_blob = net->blob_by_name(blob_names[i])
3.blob里面已经保存了所有的特征数据,按照需求取出来就好了。
count = feature_blob->channels() * feature_blob->height() * feature_blob->width();
float* feature_array = new float[count];
const float* feature_blob_data = feature_blob->cpu_data() + feature_blob->offset(n); // feature data generated from
// the nth input image within a batch
memcpy(feature_array, feature_blob_data, count * sizeof(float));
...// other operations
delete [] feature_array;
如下是做实验时候的一个例子,提取出了blstm_input中的数据,并保存到了txt里。
Blob<float>* input_layer = m_net->input_blobs()[];
input_layer->Reshape(, m_channelNum, m_inputGeometry.height, m_inputGeometry.width);
m_net->Reshape();
std::vector<cv::Mat> input_channels;
wrapInputLayer(&input_channels);
preprocess(img, &input_channels);
m_net->Forward();
Blob<float>* output_layer = m_net->output_blobs()[];
int alphabet_size=output_layer->shape();
int time_step=output_layer->shape(); vector<int> shape; const boost::shared_ptr<Blob<float> > blstm_input = m_net->blob_by_name("blstm_input");
shape = blstm_input->shape();
for(int i = ; i < shape.size(); i++)
{
cout<<" blstm_input shape:"<<i<<" :"<<shape[i]<<endl;
} const boost::shared_ptr<Blob<float> > lstm1 = m_net->blob_by_name("lstm1");
shape = lstm1->shape();
for(int i = ; i < shape.size(); i++)
{
cout<<" lstm1 shape:"<<i<<" :"<<shape[i]<<endl;
} cout<<"==============blob info======="<<endl;
ofstream of("blstm.txt");
for(int h = ; h < ; h++)
{
int count = blstm_input->channels() * blstm_input->height() * blstm_input->width();
// cout<<"blstm_input->channels():"<<blstm_input->channels()<<" blstm_input->height():"<<blstm_input->height()
// <<" blstm_input->width():"<<blstm_input->width()<<endl;
float* feature_array = new float[count];
const float* feature_blob_data = blstm_input->cpu_data() +
blstm_input->offset(h); // feature data generated from the nth input image within a batch
memcpy(feature_array, feature_blob_data, count * sizeof(float)); for(int i = ; i < count; i++ )
{
if(i && i % == )
{
of<<endl;
}
of<<" ["<< h<< ","<<i % << "]:"<<feature_blob_data[i];
}
of<<endl;
delete [] feature_array;
}
of.close();
参考:
caffe-----使用C++ 提取网络中间层特征数据的更多相关文章
- Paper | 深度网络中特征的可迁移性
目录 1. 核心贡献 2. 实验设置 2.1. 任务设置 2.2. 网络设置 3. 实验结果 4. 启发 论文:How transferable are features in deep neural ...
- KDD Cup 99网络入侵检测数据的分析
看论文 该数据集是从一个模拟的美国空军局域网上采集来的 9 个星期的网络连接数据, 分成具有标识的训练数据和未加标识的测试数据.测试数据和训练数据有着不同的概率分布, 测试数据包含了一些未出现在训练数 ...
- python数据可视化-matplotlib入门(7)-从网络加载数据及数据可视化的小总结
除了从文件加载数据,另一个数据源是互联网,互联网每天产生各种不同的数据,可以用各种各样的方式从互联网加载数据. 一.了解 Web API Web 应用编程接口(API)自动请求网站的特定信息,再对这些 ...
- Android之三种网络请求解析数据(最佳案例)
AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法. ...
- ASP.NET提取多层嵌套json数据的方法
本文实例讲述了ASP.NET利用第三方类库Newtonsoft.Json提取多层嵌套json数据的方法,具体例子如下. 假设需要提取的json字符串如下: {"name":&quo ...
- NLP用CNN分类Mnist,提取出来的特征训练SVM及Keras的使用(demo)
用CNN分类Mnist http://www.bubuko.com/infodetail-777299.html /DeepLearning Tutorials/keras_usage 提取出来的特征 ...
- 教你50招提升ASP.NET性能(十):减少通过网络发送的数据
(16)Reduce the data sent across the network 招数16: 减少通过网络发送的数据 Reducing the amount of data sent acros ...
- iOS开发网络篇—JSON数据的解析
iOS开发网络篇—JSON数据的解析 iOS开发网络篇—JSON介绍 一.什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互 服务器返回给客户端的数据,一般都是JSON格式或者XML格式 ...
- 分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要)
原文:分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要) Java InputStream读取数据问题 ======== ...
随机推荐
- dedecms织梦网站本地迁移到服务器后,后台更新栏目文档提示模板文件不存在,无法解析文档!的解决办法
解决办法: 1.系统设置-系统基本参数-站点设置-网页主页链接,替换为空 2.系统设置-系统基本参数-核心设置-DedeCMS安装目录,替换为空
- 【2019.3.20】NOI模拟赛
题目 这里必须标记一下那个傻逼问题,再不解决我人就没了! 先放一个 $T3$ $20$ 分暴力 #include<bits/stdc++.h> #define rep(i,x,y) for ...
- switch的参数类型
switch(expr1)中,expr1是一个整数表达式,整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型 ...
- pthread_cond_wait
while(1) 33 { 34 mm* p = NULL; 35 pthread_mutex_lock(&mutex); 36 while(head == NULL) 37 pthread_ ...
- 关于nmap扫描端口
nmap查看一个服务器的端口,是通过扫描来实现的.所以在本机执行nmap扫描的端口有可能被防火墙阻止,在外部是访问不了的. 如:开启ORACLE监听后,在本机使用nmap 127.0.0.1是可以扫描 ...
- repo 回退当前分支下所有仓库到指定日期前的最新代码版本
回退命令: repo forall -c 'commitID=git log --before "2019-11-24 23:59" -1 --pretty=format:&quo ...
- Linux内核编译完整过程
Linux内核编译完整过程 通过网上的资料我自己的实际内核编译,我把对Linux内核编译的过程写在这里,也许对其他的Linux爱好者的编译学习有些帮助,其中很大部分是网上的资料,另外就是我在实际编译过 ...
- H5实现手写功能
html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf- ...
- ZOJ - 3780-Paint the Grid Again-(拓扑排序)
Description Leo has a grid with N × N cells. He wants to paint each cell with a specific color (eith ...
- Unity3D_(API)射线检测Raycast()
Unity射线检测官方文档: 传送门 一.检测前方是否有游戏物体(射线无限长度) 二.检测前方是否有游戏物体(射线长度为1m) 三.检测前方游戏物体碰撞信息(射线无限长度): 四.指定检测碰撞Tag层 ...