caffe為什麼要使用lmdb資料庫?

我查了一些資料,知道lmdb資料庫是一個非關係型資料庫,原以為caffe可以將訓練數據的label作為key,數據本身作為value,但是看一些存入lmdb的程序發現好像不是這樣,還是會把數據和label都作為value,然後連續增加一個整數作為key,這樣為什麼caffe不選用關係型資料庫作為支持的資料庫呢?說的不對請各位知友請指正,謝謝大家啦!


1. caffe先支持leveldb,後支持lmdb的,lmdb讀取的效率更高,而且支持不同程序同時讀取,而leveldb只允許一個程序讀取。這一點在使用同樣的數據跑不同的配置程序時很重要。

2. 關於key的問題,圖像數據label(默認支持的label是一個整數,表示類別)就那麼多,用label作為key肯定要重複了,故不能用label作為key。

3. 關係資料庫不是很了解。不過訓練過程是不斷的按序讀取一個一個batch的數據,不需要複雜的數據存儲格式吧,這樣線性存儲讀取的效率也高吧。


如果你用caffe自帶的圖片轉存LMDB程序 ( distribute/bin/compute_imageset.bin ) 的話,默認的key是

序數_文件名

value是序列化的caffe:Datum數據。

所以並不是將label和value分別存儲的。 這裡的序數是文件名在train.txt之類的文件中的行號。使用序數做前綴是為了防止重複。使用行號+文件名做序數,這樣在對已經存在的database錄入新數據時,先前的錄入過的同名文件如果出現在train.txt中的行沒有變的話,這次的錄入會複寫先前的數據,而不是再錄入一遍。關於LMDB的優勢,可以自行google。

具體可以看 tools/convert_imageset.cpp 的源碼:
第136行

string key_str = caffe::format_int(line_id, 8) + "_" + lines[line_id].first;

第139,140 和141行

string out;
CHECK(datum.SerializeToString(out));
txn-&>Put(key_str, out);

這裡的Put操作本身只是將key_str和out分別放入兩個vector中,而不是直接進行資料庫寫入,看 src/util/db_lmdb.cpp 第51行至54行

void LMDBTransaction::Put(const string key, const string value) {
keys.push_back(key);
values.push_back(value);
}

寫入操作是在 tools/convert_imageset.cpp 的第145和152行執行的

txn-&>Commit();

轉到 src/util/db_lmdb.cpp 第65至72行

for (int i = 0; i &< keys.size(); i++) { mdb_key.mv_size = keys[i].size(); mdb_key.mv_data = const_cast&(keys[i].data());
mdb_data.mv_size = values[i].size();
mdb_data.mv_data = const_cast&(values[i].data());

// Add data to the transaction
int put_rc = mdb_put(mdb_txn, mdb_dbi, mdb_key, mdb_data, 0);
...
}


我也很想知道,大概說一下我認為的原因。

1. 為了數據更一致。原始數據可能是圖像數據,文本數據,語音數據,但是使用lmdb之後都成了lmdb數據。

2.大量小文件的IO太花時間,使用lmdb能夠一次取一個batch。

3.貌似現在不用lmdb,只用imagedata也行。因為新的caffe加入了prefetch,在數據處理的階段可以不斷從硬碟讀取數據(這個我真的不確定)


1.lmdb有利於提高磁碟IO利用率

2.數據類型太多(文本,JPEG,PNG,二進位等等)不可能用一套代碼實現所有類型的輸入數據讀取,轉換成一致的數據格式有利於讀取。


推薦閱讀:

怎麼使用caffe實現人臉的識別?
caffe官方將會支持TX1的fp16的特性嗎?
caffe下用FCN做圖像分割,如何製作訓練集?
怎樣在windows下輸出訓練caffemodel的log日誌並畫出accuracy和loss曲線?
caffe 每個樣本對應多個label?

TAG:資料庫 | 深度學習DeepLearning | Caffe深度學習框架 |