深度學習與計算機視覺(11)_基於deep learning的快速圖像檢索系統


作者:寒小陽
時間:2016年3月。
出處:http://blog.csdn.net/han_xiaoyang/article/details/50856583
聲明:版權所有,轉載請聯系作者並注明出處

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 firstBalanced 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權限):

# glog
wget https://google-glog.googlecode.com/files/glog-0.3.3.tar.gz
tar zxvf glog-0.3.3.tar.gz
cd glog-0.3.3
./configure
make && make install
# gflags
wget https://github.com/schuhschuh/gflags/archive/master.zip
unzip master.zip
cd gflags-master
mkdir build && cd build
export CXXFLAGS="-fPIC" && cmake .. && make VERBOSE=1
make && make install
# lmdb
git clone https://github.com/LMDB/lmdb
cd lmdb/libraries/liblmdb
make && make install

2.5 python版本依賴

編譯pycaffe的時候,我們需要更多的一些python的依賴庫。這時候我們可以用pip或者easy_install完成。

pip和easy_install的配置方法為:

wget --no-check-certificate https://bootstrap.pypa.io/ez_setup.py
python ez_setup.py --insecure
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

在caffe/python/requirements.txt中有pycaffe的python依賴包,如下:

Cython>=0.19.2
numpy>=1.7.1
scipy>=0.13.2
scikit-image>=0.9.3
matplotlib>=1.3.1
ipython>=3.0.0
h5py>=2.2.0
leveldb>=0.191
networkx>=1.8.1
nose>=1.3.0
pandas>=0.12.0
python-dateutil>=1.4,<2
protobuf>=2.5.0
python-gflags>=2.0
pyyaml>=3.10
Pillow>=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-compiler
sudo apt-get install --no-install-recommends libboost-all-dev

sudo 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)

未完待續…


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com