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实现。