【问题标题】:How to get features from several layers using c++ in caffe如何在 caffe 中使用 c++ 从多个层获取特征
【发布时间】:2017-04-17 17:28:25
【问题描述】:

如何在使用 C++ 进行一次前向传递后在 caffe 中同时获得 4096 dim 特征层和 1000 dim 类层?

我试图在 extract_features.cpp 中查找它,但它使用了一些奇怪的 datum 对象,所以我无法真正理解它是如何工作的。

到目前为止,我只是将我的 prototxt 文件裁剪到我想要提取和使用的层

[...]
net->ForwardPrefilled();
Blob<float> *output_layer = net->output_blobs()[0];
const float *begin = output_layer->cpu_data();
const float *end = begin + output_layer->channels();
return vector<float>(begin, end);

但如果我想同时提取两个特定层(例如“prob”和“fc7”),这将不起作用。

【问题讨论】:

  • 你绝对需要使用 C++。在 python 中,从不同层提取特征要简单得多。
  • 不幸的是,是的。 (在 python 上它已经在工作了。)

标签: machine-learning deep-learning caffe conv-neural-network


【解决方案1】:

更新

extract_feature.cpp的简单工作流程(假设你在c++中有一个shared_ptr&lt;Net&lt;float&gt; &gt; net对象):

  1. 执行网络转发以处理输入:net-&gt;Forward()。 在这一步中,net 中有一个Data 层来读取输入图像。因此,如果在您自己的应用程序/代码中,您想将图像读取到cv::Mat image 并将其输入到net,您可以编写如下代码:

    // for data preprocess
    shared_ptr<caffe::DataTransformer<float> > data_transformer;
    caffe::TransformationParameter trans_para;
    // set mean
    trans_para.set_mean_file("/path/to/image_mean.binaryproto");
    // set crop size, e.g.here is cropping 227x227
    trans_para.set_crop_size(227);
    // instantiate a DataTransformer using trans_para for image preprocess
    data_transformer.reset(new caffe::DataTransformer<float>(trans_para, caffe::TEST));
    const std::vector<caffe::Blob<float> *> net_input = net->input_blobs();
    // maybe you need to resize image before this step
    data_transformer->Transform(image, *net_input[0]);
    net->Forward();
    

    net.prototxt 应该有一个Input 层作为第一层,例如这个deploy.prototxt

  2. 根据名字获取特征块:const boost::shared_ptr&lt;Blob&lt;Dtype&gt; &gt; feature_blob = net-&gt;blob_by_name(blob_names[i])
  3. 从你想要的结构中提取特征数据,例如一个数组,一个简单的示例代码可以是:

    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;        
    

请注意,从feature_blob_data 存储的数据在row-major order 中。


extract_feature.cpp 对您的任务的用法应该是这样的:

path/to/extract_features your_pretrained_model.caffemodel \
    net.prototxt 4096_dim_feature_blob_name,1000_dim_class_feature_blob_name \
    saved_4096_dim_feature_database,saved_1000_dim_class_feature_database \
    num_mini_batches(times for forward pass) lmdb(or leveldb) GPU(or CPU)

net.prototxt 应该包含一个可以读取输入图像数据的数据层。

并且在运行时,它会首先从net.prototxt内的数据层读取图像数据,并执行num_mini_batches次前向传递,将4096_dim_feature_blob_name1000_dim_class_feature_blob_name的2个特征blob的数据提取到一个Datum 类型的结构,然后将它们序列化以保存在数据库中 saved_4096_dim_feature_databasesaved_1000_dim_class_feature_database 类型为 lmdbleveldb

完成后,您可以分别使用net.prototxt 中的数据层从saved_4096_dim_feature_databasesaved_1000_dim_class_feature_database 读取保存的特征数据。

顺便说一句,datum是一个最多可以存储4D数据以及数据的形状和标签信息等的结构体。它定义在caffe.proto中,使用google protobuf生成,方便caffe之间的数据交换和LMDBLEVELDB 等数据库。

【讨论】:

  • 问题是我需要提取extract_features.cpp 的代码并将其插入到我的c++ 代码中。由于我还无法理解extract_features.cpp 的代码,我想我会问是否有人有一个最小的工作示例(没有批处理,没有 lmdb 输出 -> 只是输入图像并将输出特征向量存储在数组中或 cv::mat 文件。
  • @mcExchange 我已经更新了我的答案。请看。
  • @mcExchange 这个帖子stackoverflow.com/a/39766758/6281477 也可以帮助您了解如何将图像读取到 cv::Mat 并将其输入到 caffe Net 对象中。
  • extract_features.cpp 现在存在吗?我再也找不到它了(Caffe 1.0)。
猜你喜欢
  • 2018-08-18
  • 2016-12-13
  • 2018-04-08
  • 2015-03-26
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
相关资源
最近更新 更多