caffe的lmdb

来源:互联网 发布:删除筛选出来的数据 编辑:程序博客网 时间:2024/05/18 03:08

要求系统已经安装了caffe,相关的安装可以参考 链接

一,LMDB的概况

全称是Lightning Memory-Mapped Database, 是一种闪电型的内存映射数据库,它的文件结构比较简单,就是一个文件夹,里面有一个数据文件和一个锁文件,数据随意复制,随意传输,访问简单,不需要运行单独的数据库管理进程,只要在访问数据的代码里引用LMDB库,访问时给文件路径就可以了;

说了那么多,直接上一个例子吧

在文件目录中,write.py是用于向lmdb写入zhengfan文件夹图片数据的代码,而read.py是用于向lmdb里面读取数据的代码;lmdb就是我们用write.py运行后得到的文件夹,里面有两个文件,一个data.lmdb,一个clock.lmdb 

二,LMDB与Caffe

Caffe中DataLayer默认的数据格式是LMDB。许多example中提供的输入数据是LMDB格式。使用extract_features.bin提取特征时支持的输出格式之一也是LMDB。LMDB在Caffe的IO功能中有相当重要的地位

那么使用LMDB有何优点呢? 1)caffe主要使用LMDB来存放训练和测试用的数据库,还有使用网络提取出的feature,因为数据集的结构很简单,就是矩阵,向量数据,数据之间也没有什么关联,数据内没有复杂的对象结构;所以数据并不复杂,就选用LMDB这个简单的数据库来存放数据;2)为什么不直接读取图片数据呢?因为这样可以减少IO开销,直接从硬盘上读取大量小文件的开销是很大的,而LMDB使用内存映射的方式访问文件,使得文件内寻址的开销非常小;数据库单文件还能减少数据集复制和传输过程的开销

在caffe中,Caffe并不是把数据集中的向量和矩阵直接放进数据库中的,而是將数据通过caffe.proto(文件路径为 `caffe/src/caffe/proto/caffe.proto`)进行结构的转换操作,代码如下

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];}
针对如上代码做如下的说明

  • 关于protobuf的知识,请 参考
  • __channels__:表示通道数量,比如RGB图像就是三通道的,灰色图片就是单通道的;在ubuntu下面查看图片的信息可以使用  identify 命令
  • __heigth__:表示图片的高
  • __width__:表示图片的宽
  • __data__:表示要存放的整数型数据,一般是存放图像数据
  •  __float_data__:表示要存放的浮点型数据,一般是提取到的特征向量
  • __label__:表示数据的标签类型,是整数型
  • __encoded__:表示是否需要被解码(里面可能放的是JEPG之类经过编码的数据)
  • Datum这个数据结构将数据和标签封装在一起,兼容整形和浮点型数据。经过Protobuf编译后,可以在Python和C++中都提供高效的访问。同时Protubuf还为它提供了序列化与反序列化的功能。存放进LMDB的就是Datum序列化生成的字符串
在Caffe下成功运行mnist样例代码如下
cd caffesh data/mnist/get_mnist.shsh examples/mnist/create_mnist.shvi examples/mnist/lenet_solver.prototxt # 修改 solver_mode 为 CPU; 也就是 # uncomment CPU_ONLY := 1./examples/mnist/train_lenet.sh 

那么如何caffe里面mnist集数据的LMDB存储?在caffe目录下执行如下的命令
./data/mnist/get_mnish.sh #在线获取mnist数据包./example/mnist/create_mnist.sh #将下载到的二进制mnist数据转换成lmdb数据
对上面的代码进行如下的说明
  • 在第二个执行命令后,我们可以看到在example/mnist目录下多了两个目录,就是我们生成的lmdb文件夹,一个是`mnist_test_lmdb`,一个是`mnist_train_lmdb`
  • 我们查看create_mnist.sh文件,可以知道这个shell脚本的过程主要有删除之前之前生成的两个lmdb文件,然后调用caffe/build/examples/mnist目录下的conver_minst_data.bin这个可执行文件,并给其传入3个参数;
  • 这个二进制文件是怎么生成的,它的源文件在caffe/example/mnist/conver_mnist_data.cpp,我们着重看这个文件;看函数入口main函数,main函数主要是针对传入的参数进行判断,也就是我们在shell文件里面调用bin文件后后面所带的参数,如果argc不等于四个的(argc的值是函数名加上参数的个数),就输出函数的使用方式,关于shell文件里面的`--backend=${BACKEND}`,我们可以在cpp代码里面看到`DEFINE_string(backend, "lmdb", "The backend for storing the result");`其作用是 使用GFLAGS 工具定义命令行选项 backend, 默认值为 lmdb, 即: --backend=lmdb,这样我们就可以在全局使用一个变量也就是`FLAGS_backend`它的默认值是lmdb,可能被命令行的`--backend=`重新赋值;如果argc等于四的话,就将argv[1](第一个参数),argc[2],argc[3],还有FLAGS_backend作为参数,调用convert_dataset()函数;
  • 关于convert_dataset()函数,可以参考 参考2  要注意的是,关于里面read这个函数需要读取的大小,需要参考mnist数据集的格式
三,最后加上一个Python版的lmdb读取与写入
代码来源于 http://blog.mythsman.com/?p=2591;
代码地址可以看 github

参考链接
[1]: https://rayz0620.github.io/2015/05/25/lmdb_in_caffe/
[2]: http://blog.csdn.net/u010167269/article/details/51915512
[3]: [总结得很详细](http://blog.inet198.cn/?u010167269/article/details/51915512)

0 0
原创粉丝点击