Ann, Approximate Nearest Neighbor的縮寫,就是近似最近鄰搜索。
在機器學習領域,語義檢索,圖像識別,推薦系統等方向常涉及到的一個問題是:給定一個向量X=[x1,x2,x3...xn],需要從海量的向量庫中找到最相似的前K個向量。通常這些向量的維度很高,對於在線服務,用傳統的方法查找是非常耗時的,容易使得時延上成爲瓶頸,因此業界通用的方式就是將最相似的查找轉換成Ann問題。
這樣查找返回的前K個向量並不一定是最相似的K個向量,衡量Ann算法好不好的一個依據是召回,每次Ann請求返回的K個結果與使用暴力查找的K個結果去比較,如果完全一致,說明是最好的。因爲省了搜索時間卻沒有影響效果。
目前的Ann算法有基於圖(hnswlib )的,基於樹(pysparnn)的,基於哈希(NearPy這個庫)等,並且有很多關於Ann算法的實現,開源的很多,如annoy, faiss,nmslib, falconn,FLANN等。
更詳細的一些測試在這個網站有數據 http://ann-benchmarks.com。作者比較了不同的距離度量方式及在不同數據集的效果。
基於圖的算法(hnsw)其實在評測上看起來是最好的, 但是其耗費比較多內存,樹的方法在維度大時會變成暴力搜索,其它方法也有不同的特點。
我測試過的,一分爲兩類:稀疏向量和非稀疏向量
首先:稀疏向量是指維度比較多,而且向量的很多元素是0,啁密向量指零元素較少,向量的維度也就幾十到幾百。
如果上萬維的一般是稀疏向量(一萬個詞語詞庫句子搜索),這樣的PySpann最好。
其次是周密向量,那麼faiss應該內存和速度比較均衡 。
pysparnn安裝比較簡單,下載源碼python setup.py install
faiss的安裝如下:
1 sudo apt-get install libopenblas-dev liblapack3 python-numpy python-dev
2 apt-get install libblas-dev libatlas-dev liblapack-dev
swig install
git clone https://github.com/swig/swig.git
cd swig
sudo apt-get install automake
./autogen.sh
./configure
sudo apt-get install bison flex
make
sudo make install
這樣的算法成千上百,對此進行評測https://github.com/erikbern/ann-benchmarks
評測數據集如下
Dataset | Dimensions | Train size | Test size | Neighbors | Distance | Download |
---|---|---|---|---|---|---|
DEEP1B | 96 | 9,990,000 | 10,000 | 100 | Angular | HDF5 (3.6GB) |
Fashion-MNIST | 784 | 60,000 | 10,000 | 100 | Euclidean | HDF5 (217MB) |
GIST | 960 | 1,000,000 | 1,000 | 100 | Euclidean | HDF5 (3.6GB) |
GloVe | 25 | 1,183,514 | 10,000 | 100 | Angular | HDF5 (121MB) |
GloVe | 50 | 1,183,514 | 10,000 | 100 | Angular | HDF5 (235MB) |
GloVe | 100 | 1,183,514 | 10,000 | 100 | Angular | HDF5 (463MB) |
GloVe | 200 | 1,183,514 | 10,000 | 100 | Angular | HDF5 (918MB) |
Kosarak | 27983 | 74,962 | 500 | 100 | Jaccard | HDF5 (2.0GB) |
MNIST | 784 | 60,000 | 10,000 | 100 | Euclidean | HDF5 (217MB) |
NYTimes | 256 | 290,000 | 10,000 | 100 | Angular | HDF5 (301MB) |
SIFT | 128 | 1,000,000 | 10,000 | 100 | Euclidean | HDF5 (501MB) |
評估的實現
- Annoy Spotify自家的C++庫(提供Python綁定)。Annoy最突出的特性是支持使用靜態索引文件,這意味着不同進程可以共享索引。
- FLANN 加拿大英屬哥倫比亞大學出品的C++庫,提供C、MATLAB、Python、Ruby綁定。
- scikit-learn 知名的Python機器學習庫scikit-learn提供了
LSHForest
、KDTree
、BallTree
實現。 - PANNS 純Python實現。已“退休”,作者建議使用MRPT。
- NearPy 純Python實現。基於局部敏感哈希(Locality-sensitive hashing,簡稱LSH,一種降維方法)。
- KGraph C++庫,提供Python綁定。基於圖(graph)算法。
- NMSLIB (Non-Metric Space Library) C++庫,提供Python綁定,並且支持通過Java或其他任何支持Apache Thrift協議的語言查詢。提供了SWGraph、HNSW、BallTree、MPLSH實現。
- hnswlib(NMSLIB項目的一部分) 相比當前NMSLIB版本,hnswlib內存佔用更少。
- RPForest 純Python實現。主要特性是不需要在模型中儲存所有索引的向量。
- FAISS Facebook出品的C++庫,提供可選的GPU支持(基於CUDA)和Python綁定。包含支持搜尋任意大小向量的算法(甚至包括可能無法在RAM中容納的向量)。
- DolphinnPy 純Python實現。基於超平面局部敏感哈希算法。
- Datasketch 純Python實現。基於MinHash局部敏感哈希算法。
- PyNNDescent 純Python實現。基於k-近鄰圖構造(k-neighbor-graph construction)。
- MRPT C++庫,提供Python綁定。基於稀疏隨機投影(sparse random projection)和投票(voting)。
- NGT: C++庫,提供了Python、Go綁定。提供了PANNG實現。