说明:

Caffe自带的图像转LMDB接口只支持单label,对于多label的任务,可以使用HDF5的格式,也可以通过修改caffe代码来实现.本篇文章介绍怎么通过修改DataLayer来实现带Multilabel的lmdb格式数据输入的分类任务.

--- 本文参考自 :


1. 总体介绍

共修改5个文件:

  1. $CAFFE_ROOT/src/caffe/proto/caffe.proto
  2. $CAFFE_ROOT/src/caffe/layers/data_layer.cpp
  3. $CAFFE_ROOT/src/caffe/util/io.cpp
  4. $CAFFE_ROOT/include/caffe/util/io.hpp
  5. $CAFFE_ROOT/tools/convert_imageset.cpp

其中$CAFFE_ROOT为caffe根目录,即git clone 目录, 如图:

修改完成后,执行:

make clean
make all –j8

-------______

具体的文件修改内容如下:

2.1 caffe.proto

vim /src/caffe/proto/caffe.proto

在message Datum { }里中添加一行代码,即添加一个labels,是repeated类型的,以便接受多标签数据集。

 repeated float labels = 8;

message Datum {
optional int32 channels = 1;
optional int32 height = 2;
optional int32 width = 3;
// the actual image data, in bytes
optional bytes data = 4;
optional int32 label = 5;
// Optionally, the datum could also hold float data.
repeated float float_data = 6;
// If true data contains an encoded image that need to be decoded
optional bool encoded = 7 [default = false];
//////////////////////////////////
repeated float labels = 8;
//////////////////////////////////
}

2.2 data_layer.cpp (两处)

// label
/*
if (this->output_labels_) {
vector<int> label_shape(1, batch_size);
top[1]->Reshape(label_shape);
for (int i = 0; i < this->prefetch_.size(); ++i) {
this->prefetch_[i]->label_.Reshape(label_shape);
}
}
*/
/////////////////////////////////////////////////
if (this->output_labels_){
top[1]->Reshape(batch_size, 4, 1, 1);
for (int i = 0; i < this->prefetch_.size(); ++i) {
this->prefetch_[i]->label_.Reshape(batch_size, 4, 1, 1);
}
}
//////////////////////////////////////////////////
// Copy label.
/*
if (this->output_labels_) {
Dtype* top_label = batch->label_.mutable_cpu_data();
top_label[item_id] = datum.label();
}
*/
///////////////////////////////////////////////
if (this->output_labels_) {
Dtype* top_label = batch->label_.mutable_cpu_data();
for (int i = 0; i < 4; i++)
top_label[item_id * 4 + i] = datum.labels(i);
}
///////////////////////////////////////////////

2.3 io.cpp(两处)

修改两个函数,替换成下面修改后的代码即可,

vim /src/caffe/util/io.cpp

ReadImageToDatum()

bool ReadImageToDatum(const string& filename, const vector<float> label,
const int height, const int width, const bool is_color,
const std::string & encoding, Datum* datum) {
cv::Mat cv_img = ReadImageToCVMat(filename, height, width, is_color);
if (cv_img.data) {
if (encoding.size()) {
if ( (cv_img.channels() == 3) == is_color && !height && !width &&
matchExt(filename, encoding) )
return ReadFileToDatum(filename, label, datum);
std::vector<uchar> buf;
cv::imencode("."+encoding, cv_img, buf);
datum->set_data(std::string(reinterpret_cast<char*>(&buf[0]),
buf.size())); datum->clear_labels();
for (int i = 0; i < label.size(); i++){
datum->add_labels(label[i]);
}
datum->set_encoded(true);
return true;
}
CVMatToDatum(cv_img, datum); datum->clear_labels();
for (int i = 0; i < label.size(); i++){
datum->add_labels(label[i]);
}
return true;
} else {
return false;
}
}

ReadFileToDatum()

//////////////////////////////////////////////////////////////////////
bool ReadFileToDatum(const string& filename, const vector<float> label,
Datum* datum) {
std::streampos size; fstream file(filename.c_str(), ios::in|ios::binary|ios::ate);
if (file.is_open()) {
size = file.tellg();
std::string buffer(size, ' ');
file.seekg(0, ios::beg);
file.read(&buffer[0], size);
file.close();
datum->set_data(buffer); datum->clear_labels();
for (int i = 0; i < label.size(); i++){
datum->add_labels(label[i]);
}
datum->set_encoded(true);
return true;
} else {
return false;
}
}

2.4 io.hpp

在其中新加入/////// ..... ///////内的两个成员函数声明,不删除原来的任何代码,下面的前两个函数声明是原来文件中就有的,可以看到,原来代码中的label参数是int类型,只能处理单标签字符;新增的两个成员函数就是参考上面两个函数,将const int label参数改成了std::vector labels,以接受多标签字符。

bool ReadImageToDatum(const string& filename, const int label,
const int height, const int width, const bool is_color,
const std::string & encoding, Datum* datum);
bool ReadFileToDatum(const string& filename, const int label, Datum* datum);
//////////////////////////////////////////
bool ReadImageToDatum(const string& filename, std::vector<float> labels,
const int height, const int width, const bool is_color,
const std::string & encoding, Datum* datum);
bool ReadFileLabelsToDatum(const string& filename, std::vector<float> labels,
Datum* datum);
///////////////////////////////////

2.5 convert_imageset.cpp

/*
std::ifstream infile(argv[2]);
std::vector<std::pair<std::string, int> > lines;
std::string line;
size_t pos;
int label;
while (std::getline(infile, line)) {
pos = line.find_last_of(' ');
label = atoi(line.substr(pos + 1).c_str());
lines.push_back(std::make_pair(line.substr(0, pos), label));
}
*/
////////////////////////////
std::ifstream infile(argv[2]);
std::vector<std::pair<std::string, vector<float> > > lines;
std::string filename;
vector<float> labels(4);
while (infile >> filename >> labels[0] >> labels[1] >> labels[2] >> labels[3]){
lines.push_back(std::make_pair(filename, labels));
}
///////////////////////////

多标签caffe重新编译的更多相关文章

  1. 深度学习框架Caffe的编译安装

    深度学习框架caffe特点,富有表达性.快速.模块化.下面介绍caffe如何在Ubuntu上编译安装. 1. 前提条件 安装依赖的软件包: CUDA 用来使用GPU模式计算. 建议使用 7.0 以上最 ...

  2. 64位win10+cuda8.0+vs2013+cuDNN V5下Caffe的编译安装教程并配置matlab2014a 接口

    一.需要安装的软件 1)vs2013,我是在http://www.52pojie.cn/thread-492326-1-1.html这个网址安装的.我之前用的是vs2012,按照网上的配置教程会爆各种 ...

  3. caffe windows编译

    MicroSoft维护的caffe已经作为官方的caffe分支了,编译方式也改了,刚好最近重装了一次caffe windows, 记录一下里面的坑 https://github.com/BVLC/ca ...

  4. caffe make 编译

    其实嘛,出现这个的原因在于,已经编译过啦,没有任何改动,那还烦劳编译啥呢. 那Linux又是如何知道已经编译过了呢? 那就要看makefile的规则啦.makefile的规则是所想产生的文件需要依赖很 ...

  5. Caffe: gflag编译出现问题汇总

    1. 使用Unicode字符集: 出现问题 E:\CodeBase\ML\Caffe\ThirdPartySrc\gflags-master\src\gflags.cc(1340): error C2 ...

  6. caffe安装编译问题-ImportError: No module named google.protobuf.internal

    问题描述 ~/Downloads/caffe$ python Python (default, Dec , ::) [GCC ] on linux2 Type "help", &q ...

  7. caffe安装编译问题-ImportError: No module named skimage.io

    问题描述 >>> import caffe Traceback (most recent call last): File , in <module> File , in ...

  8. caffe安装编译问题-ImportError: libopencv_core.so.3.4: cannot open shared object file: No such file or directory

    问题描述 >>> import caffe Traceback (most recent call last): File , in <module> File , in ...

  9. caffe安装编译问题-ImportError: No module named caffe

    问题描述 ~/Downloads/caffe$ python Python (default, Dec , ::) [GCC ] on linux2 Type "help", &q ...

随机推荐

  1. 06--STL序列容器(priority_queue)

    一:优先队列priority_queue简介 同队列,不支持迭代 (一)和队列相比 同: 优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素. 异: 但是它有一个特性,就是队列中最大的元素总是 ...

  2. 0. Java虚拟机系列备忘预览图

    打算把Java虚拟机这块单独弄一个主题出来,做做备忘,结构如图所示: 后面还有一部分待更新...

  3. Promise库

    标准 https://promisesaplus.com/ An open standard for sound, interoperable JavaScript promises—by imple ...

  4. JavaScript在div后添加删除div

    var idd = 'str'; $('.task-done-detail-content-p7').click(function () { var id = this.id; if(idd !== ...

  5. vue-router.esm.js:1905 TypeError: Cannot convert undefined or null to object

    环境:vue+vuex+element 报错原因 ...mapState('isDialNumber') mapState如果传递一个参数,参数必须是数组 ...mapState(['isDialNu ...

  6. 基于范围的for循环(C++11)

    C++11新增了一种循环:基于范围的for循环.这简化了一种常见的循环任务:对数组(或容器类,如vector和array)的每个元素执行相同的操作,如下例所示 for语句允许简单的范围迭代:(只遍历, ...

  7. python matplotlib 简单生成图

    import numpy as np import pandas as pd from matplotlib import pyplot as plt data = pd.DataFrame([[1, ...

  8. Unsafe 的简单使用

    Unsafe 简介 Unsafe 是sun.misc包中的一个类,可以通过内存偏移量操作类变量/成员变量 Unsafe 用途 AQS(AbstractQueuedSynchronizer) 常用作实现 ...

  9. 【转】监听器(Listener)学习

    一.监听器介绍 1.1.监听器的概念 监听器是一个专门用于对其它对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监听的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通 ...

  10. Marshal.PtrToStringAnsi中文乱码

    出错代码: string dec = Marshal.PtrToStringAnsi(audioOutput.psz_description);//输出 鎵0鍣?(Realtek High Defi ...