使用C++在Caffe中从多个层获取特征

如何在Caffe中使用C++进行一次前向传递后同时获取4096维特征层和1000维类别层的数据?

我尝试在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”),这种方法就不适用了。


回答:

更新

extract_feature.cpp的简单工作流程(假设你在C++中有一个shared_ptr<Net<float> > net对象):

  1. 执行网络前向传递处理输入:net->Forward()。在这一步中,网络中的Data层用于读取输入图像。因此,如果在你自己的应用程序/代码中想要读取图像到cv::Mat image并将其输入到net中,你可以编写如下代码:

    // 数据预处理shared_ptr<caffe::DataTransformer<float> > data_transformer;caffe::TransformationParameter trans_para;// 设置均值trans_para.set_mean_file("/path/to/image_mean.binaryproto");// 设置裁剪大小,例如这里裁剪为227x227trans_para.set_crop_size(227);// 使用trans_para为图像预处理实例化一个DataTransformerdata_transformer.reset(new caffe::DataTransformer<float>(trans_para, caffe::TEST));const std::vector<caffe::Blob<float> *> net_input = net->input_blobs();// 可能需要在此步骤之前调整图像大小data_transformer->Transform(image, *net_input[0]);net->Forward();

    并且net.prototxt应包含一个作为第一层的Input层,例如这个deploy.prototxt

  2. 根据它们的名称获取特征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); // 从批次中的第n个输入图像生成的特征数据 memcpy(feature_array, feature_blob_data, count * sizeof(float)); ...// 其他操作delete [] feature_array;        

请注意,从feature_blob_data存储的数据是以行优先顺序排列的。


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次前向传递,提取两个特征blob 4096_dim_feature_blob_name1000_dim_class_feature_blob_name的数据到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等数据库之间进行数据交换。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注