標籤:
寒小陽 && 龍心塵
時間:2016年3月。
出處:http://blog.csdn.net/han_xiaoyang/article/details/50856583
http://blog.csdn.net/longxinchen_ml/article/details/50903658
聲明:著作權,轉載請聯絡作者並註明出處
1.
重點內容引言
本系統是基於CVPR2015的論文《Deep Learning of Binary Hash Codes for Fast Image Retrieval》實現的海量資料下的基於內容圖片檢索系統,250w圖片下,對於給定圖片,檢索top 1000相似時間約為1s,其基本背景和原理會在下文提到。
2.基本問題與技術
大家都知道,基於內容的映像檢索系統是根據映像的內容,在已有映像集中找到最『相近』的圖片。而這類系統的效果(精準度和速度)和兩個東西直接相關:
根據我們這個簡單系統裡的情況粗淺地談談這兩個點。
首先說映像特徵的表達能力,這一直是基於內容的映像檢索最核心卻又困難的點之一,電腦所『看到』的圖片像素層面表達的低層次資訊與人所理解的映像多維度高層次資訊內容之間有很大的差距,因此我們需要一個儘可能豐富地表達映像層次資訊的特徵。我們前面的部落格也提到了,deep learning是一個對於映像這種層次資訊非常豐富的資料,有更好表達能力的架構,其中每一層的中間資料都能表達映像某些維度資訊,相對於傳統的Hist,Sift和Gist,表達的資訊可能會豐富一下,因此這裡我們用deep learning產出的特徵來替代傳統映像特徵,希望能對映像有更精準的描繪程度。
再說『近似最近鄰』,ANN(Approximate Nearest Neighbor)/近似最近鄰一直是一個很熱的研究領域。因為在海量樣本的情況下,遍曆所有樣本,計算距離,精確地找出最接近的Top K個樣本是一個非常耗時的過程,尤其有時候樣本向量的維度也相當高,因此有時候我們會犧牲掉一小部分精度,來完成在很短的時間內找到近似的top K個最近鄰,也就是ANN,最常見的ANN演算法包括局部敏感度雜湊/locality-sensitive hashing,最優節點優先/best bin first和Balanced box-decomposition tree等,我們系統中將採用LSH/局部敏感度雜湊來完成這個過程。有一些非常專業的ANN庫,比如FLANN,有興趣的同學可以瞭解一下。
3. 本檢索系統原理
映像檢索系統和關鍵環節如所示:
映像檢索過程簡單說來就是對圖片資料庫的每張圖片抽取特徵(一般形式為特徵向量),儲存於資料庫中,對於待檢索圖片,抽取同樣的特徵向量,然後並對該向量和資料庫中向量的距離,找出最接近的一些特徵向量,其對應的圖片即為檢索結果。
基於內容的映像檢索系統最大的痛點在上節已經說過了,其一為大部分神經網路產出的中介層特徵維度非常高,比如Krizhevsky等的在2012的ImageNet比賽中用到的AlexNet神經網,第7層的輸出包含豐富的映像資訊,但是維度高達4096維。4096維的浮點數向量與4096維的浮點數向量之間求相似性,運算量較大,因此Babenko等人在論文Neural codes for image retrieval中提出用PCA對4096維的特徵進行PCA降維壓縮,然後用於基於內容的映像檢索,此情境中效果優於大部分傳統映像特徵。同時因為高維度特徵之間相似性運算會消耗一定的時間,因此線性地逐個比對資料庫中特徵向量是顯然不可取的。大部分的ANN技術都是將高維特徵向量壓縮到低維度空間,並且以01二值的方式表達,因為在低維空間中計算兩個二值向量的漢明距離速度非常快,因此可以在一定程度上緩解時效問題。ANN的這部分hash映射是在拿到特徵之外做的,本系統架構試圖讓卷積神經網在訓練過程中學習出對應的『二值檢索向量』,或者我們可以理解成對全部圖先做了一個分桶操作,每次檢索的時候只取本桶和臨近桶的圖片作比對,而不是在全域做比對,以提高檢索速度。
論文是這樣實現『二值檢索向量』的:在Krizhevsky等2012年用於ImageNet中的卷積神經網路結構基礎上,在第7層(4096個神經元)和output層之間多加了一個隱層(全串連層)。隱層的神經元激勵函數,可以選用sigmoid,這樣輸出值在0-1之間值,可以設定閾值(比如說0.5)之後,將這一層輸出變換為01二值向量作為『二值檢索向量』,這樣在使用卷積神經網做映像分類訓練的過程中,會『學到』和結果類別最接近的01二值串,也可以理解成,我們把第7層4096維的輸出特徵向量,通過神經元關聯壓縮成一個低維度01向量,但不同於其他的降維和二值操作,這是在一個神經網路裡完成的,每對圖片做一次完整的前向運算拿到類別,就產出了表徵映像豐富資訊的第7層output(4096維)和代表圖片分桶的第8層output(神經元個數自己指定,一般都不會很多,因此維度不會很高)。引用論文中的圖例解釋就是如下的結構:
上方圖為ImageNet比賽中使用的卷積神經網路;中間圖為調整後,在第7層和output層之間添加隱層(假設為128個神經元)後的卷積神經網路,我們將複用ImageNet中得到最終模型的前7層權重做fine-tuning,得到第7層、8層和output層之間的權重。下方圖為實際檢索過程,對於所有的圖片做卷積神經網路前向運算得到第7層4096維特徵向量和第8層128維輸出(設定閾值0.5之後可以轉成01二值檢索向量),對於待檢索的圖片,同樣得到4096維特徵向量和128維01二值檢索向量,在資料庫中尋找二值檢索向量對應『桶』內圖片,比對4096維特徵向量之間距離,做重拍即得到最終結果。圖上的檢索例子比較直觀,對於待檢索的”鷹”映像,算得二值檢索向量為101010,取出桶內圖片(可以看到基本也都為鷹),比對4096維特徵向量之間距離,重新排序拿得到最後的檢索結果。
4. 預訓練好的模型
一般說來,在自己的圖片訓練集上,針對特定的情境進行映像類別訓練,得到的神經網路,中介層特徵的表達能力會更有針對性一些。具體訓練的過程可以第3節中的說明。對於不想自己重新費時訓練,或者想快速搭建一個基於內容的圖片檢索系統的同學,這裡也提供了100w圖片上訓練得到的卷積神經網路模型供大家使用。
這裡提供了2個預先訓練好的模型,供大家提取『映像特徵』和『二值檢索串』用。2個模型訓練的資料集一致,卷積神經網路搭建略有不同。對於幾萬到十幾萬層級的小量級圖片建立檢索系統,請使用模型Image_Retrieval_20_hash_code.caffemodel,對於百萬以上的圖片建立檢索系統,請使用模型Image_Retrieval_128_hash_code.caffemodel。
對於同一張圖片,兩者產出的特徵均為4096維度,但用作分桶的『二值檢索向量』長度,前者為20,後者為128。
模型為雲端硬碟地址。
傻瓜式環境配置手冊1.關於系統
這個說明是關於linux系統的,最好是centOS 7.0以上,或者ubuntu 14.04 以上。低版本的系統可能會出現boost,opencv等庫版本不相容問題。
2. centOS配置方法2.1 配置yum源
配置合適的yum源是一種『偷懶』的辦法,可以簡化很多後續操作。不進行這一步的話很多依賴庫都需要自己手動編譯和指定caffe編譯路徑,耗時且經常編譯不成功。
在國內的話用sohu或者163的源
rpm -Uvh http://mirrors.sohu.com/fedora-epel/7/x86_64/e/epel-release-7-2.noarch.rpm
如果身處國外的話,可以查一下fedora mirror list,找到合適的yum源添加。
接著我們讓新的源生效:
yum repolist
2.2 安裝依賴的庫
該映像檢索系統依賴於caffe深度學習架構,因此需要安裝caffe依賴的部分庫:比如protobuf是caffe中定義layers的設定檔解析時需要的,leveldb是訓練時儲存圖片資料的資料庫,opencv是影像處理庫,boost是通用C++庫,等等…
我們用yum install一鍵安裝:
sudo yum install protobuf-devel leveldb-devel snappy-devel opencv-devel boost-devel hdf5-devel
2.3 安裝科學計算庫
這個部分大家都懂的,因為要訓練和識別過程,涉及到大量的科學計算,因此必要的科學計算庫也需要安裝。同時python版本caffe中會依賴一些python科學計算庫,pip和easy_install有時候安裝起來會有一些問題,因此部分庫這裡也用yum install直接安裝了。
yum install openblas-devel.x86_64 gcc-c++.x86_64 numpy.x86_64 scipy.x86_64 python-matplotlib.x86_64 lapack-devel.x86_64 python-pillow.x86_64 libjpeg-turbo-devel.x86_64 freetype-devel.x86_64 libpng-devel.x86_64 openblas-devel.x86_64
2.4 其餘依賴
包括lmdb等:
sudo yum install gflags-devel glog-devel lmdb-devel
若此處yum源中找不到這些拓展package,可是手動編譯(要有root許可權):
# glogwget https://google-glog.googlecode.com/files/glog-0.3.3.tar.gztar zxvf glog-0.3.3.tar.gzcd glog-0.3.3./configuremake && make install# gflagswget https://github.com/schuhschuh/gflags/archive/master.zipunzip master.zipcd gflags-mastermkdir build && cd buildexport CXXFLAGS="-fPIC" && cmake .. && make VERBOSE=1make && make install# lmdbgit clone https://github.com/LMDB/lmdbcd lmdb/libraries/liblmdbmake && make install
2.5 python版本依賴
編譯pycaffe的時候,我們需要更多的一些python的依賴庫。這時候我們可以用pip或者easy_install完成。
pip和easy_install的配置方法為:
wget --no-check-certificate https://bootstrap.pypa.io/ez_setup.pypython ez_setup.py --insecurewget https://bootstrap.pypa.io/get-pip.pypython get-pip.py
在caffe/python/requirements.txt中有pycaffe的python依賴包,如下:
Cython>=0.19.2numpy>=1.7.1scipy>=0.13.2scikit-image>=0.9.3matplotlib>=1.3.1ipython>=3.0.0h5py>=2.2.0leveldb>=0.191networkx>=1.8.1nose>=1.3.0pandas>=0.12.0python-dateutil>=1.4,<2protobuf>=2.5.0python-gflags>=2.0pyyaml>=3.10Pillow>=2.3.0
通過以下shell命令可以全部安裝:
for req in $(cat requirements.txt); do pip install $req; done
3. ubuntu配置方法
基本與centOS一致,這裡簡單列出需要執行的shell命令:
sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compilersudo apt-get install --no-install-recommends libboost-all-devsudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev
python部分的依賴包安裝方式同上。
4. caffe的編譯與準備
保證caffe所需依賴都安裝完成後,在caffe目錄下執行:
cp Makefile.config.example Makefile.config
根據自己的實際情況,修改Makefile.config的內容,主要修改的幾個如下:
- 如果沒有GPU,只打算用CPU進行實驗,將
# CPU_ONLY := 1
前的#號去掉。
- 如果使用GPU,且有cuDNN加速,將
# USE_CUDNN := 1
前的#號去掉。
- 如果使用openBLAS,將
BLAS := atlas
改成BLAS := open
,並添加BLAS_INCLUDE := /usr/include/openblas
(Caffe中預設的矩陣運算庫為ATLAS,但是OpenBLAS有一些效能最佳化,因此建議換做OpenBLAS)
未完待續…
深度學習與電腦視覺(11)_基於deep learning的快速映像檢索系統