精华内容
下载资源
问答
  • 基于邻域图的大规模最近邻搜索
  • Ann, Approximate Nearest Neighbor的缩写,就是近似最近邻搜索。 在机器学习领域,语义检索,图像识别,推荐系统等方向常涉及到的一个问题是:给定一个向量X=[x1,x2,x3...xn],需要从海量的向量库中找到最相似的前...

    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提供了LSHForestKDTreeBallTree实现。
    • 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实现。
    展开全文
  • 最近邻搜索用于分类问题的一种改进
  • 用于最近邻搜索的 Dijkstra 算法。
  • 基于顺序NPsim矩阵的高维数据最近邻搜索算法
  • 最近邻搜索广泛应用于分类问题,其最显著的优点是分类准确率高、泛化性能好。但现有最近邻分类算法都存在着一个弱点――样本集增大分类计算量也显著增大。为了克服这一不足,本文基于一个新的思路,提出了最近邻分类...
  • 高维空间中基于聚类的最近邻搜索的有效优化
  • k-最近邻搜索(KNNS) 在高维空间中应用非常广泛,但目前很多KNNS算法是基于欧氏距离对数据进行索引和搜索,不适合采用角相似性的应用。提出一种基于角相似性的k-最近邻搜索算法(BA-KNNS)。该算法先提出基于角相似性的...
  • flann快速最近邻搜索库的手册,快速入门用法,主要类和方法的介绍等等
  • 了解NearPy,进行快速最近邻搜索

    千次阅读 2018-12-03 12:37:52
    NearPy是一个Python框架,用于使用不同的局部敏感散列方法在高维向量空间中进行快速(近似)最近邻搜索。 你可以使用NearPy去进行试验和评估新的(研究)方法,但也可以直接用于实际应用。NearPy配有一个redis存储...

    NearPy是一个Python框架,用于使用不同的局部敏感散列方法在高维向量空间中进行快速(近似)最近邻搜索。
    你可以使用NearPy去进行试验和评估新的(研究)方法,但也可以直接用于实际应用。NearPy配有一个redis存储适配器。
    要安装它,只需执行 pip install NearPy。它还将安装scipy,numpy和redis。
    现在支持密集和稀疏(scipy.sparse)向量。
    点击此处了解更多信息:http://pixelogik.github.io/NearPy/

    (文中向量和矢量是同一个意思,都翻译于vector)

    原理

    为了找到查询向量的近似最近邻居,首先索引要存储的向量。对于应该被索引(’存储’)的每个向量,生成散列,即字符串值。该散列用作存储向量的后备数据单元的键。在大多数情况下,后备数据单元只是一个系列的向量,后备数据单元是在这种应用下使用的术语。
    这样生成的后备数据单元(bucket)的键(即向量散列值)对于查找查询向量的最近邻居没有任何用处。因此,NearPy实现近似最近邻算法的机制的“秘密”是使用所谓的一些局部敏感哈希函数—LSH。这些局部敏感哈希函数考虑了空间性,因此它们倾向于为近似向量生成相同的散列值(后备数据的键)。这使得在给定查询向量的情况下获得接近向量的速度非常快。因为这是一种非常粗略的方法,所以它被称为近似最近邻搜索,因为您可能无法获得真正的最近邻居。在许多应用程序中这是很好的一种折中方式,因为你只想得到20个“足够相等”的向量。

    Engine — 发动机

    使用NearPy时,您将主要通过配置和使用Engine对象来完成此操作。Engines是可配置的管道,用于使用局部敏感哈希(LSH)进行近似最近邻搜索(ANNS)。
    在这里插入图片描述

    使用构造函数配置Engine,该构造函数接受管道中的不同组件:

    def  __init__(self,dim,lshashes = [RandomBinaryProjections(' default ',10)],
                  distance = CosineDistance(),
                  vector_filters = [NearestFilter(10)],
                  storage = MemoryStorage()):
    

    ANNS管道配置为特征空间的固定维度,可以使用构造函数的dim参数设置。dim必须是正整数值。
    Engine可以使用多个局部敏感哈希函数LSH,可以通过lshashes参数中设置,该参数必须是LSHash对象的数组。
    根据查询期间使用的过滤器类型,可以指定距离度量。只有在使用需要距离的过滤器(如 NearestFilterDistanceThresholdFilter)时才需要指定距离度量。
    在查询最近邻居期间,过滤器用于最后一步。现有的实现是NearestFilterDistanceThresholdFilterUniqueFilter
    fetch_vector_filters是Engine构造函数的另一个参数,它是在从后备数据单元(Buckets)中提取候选矢量(vector)之后和使用距离或矢量滤波器之前执行的。默认情况下,该参数是一个UniqueFilter,并且该参数应该始终是UniqueFilter。将这个参数作为保留,万一以后有特殊的用途。
    Engine 支持多种索引向量(和后备数据单元)的存储方式。当前的存储实现是MemoryStorageRedisStorage
    引擎有两种主要方法:

    store_vector(self,v,data = None)
    neighbours(self,v)
    

    store_vector() 使用所有已配置的LSH对向量v进行哈希处理,并将其(向量v)存储在哈希结果相匹配的后备数据单元(Bucket)中 (每个哈希结果对应一个后备数据单元Bucket?)。可选的data参数必须是JSON可序列化的。它与向量一起存储,并将在搜索结果中返回。最佳做法是仅将数据库ID用作附加的“data”,并将实际数据存储在数据库中。
    neighbors() 使用所有配置的局部敏感哈希函数对向量v进行哈希计算,利用哈希的结果从后备数据单元中取出所有匹配的候选向量,应用距离函数(可选)和过滤函数(可选)构造返回的列表(向量,数据,距离) )元组或(向量,数据)元组。
    要从引擎中删除索引向量及其数据,可以使用以下两种方法:

    clean_all_buckets(self)
    clean_buckets(self,hash_name)
    

    Hashed — 哈希

    NearPy中的所有LSH实现都是继承于nearpy.hashes.LSHash,除了构造函数和重置方法之外,它还有一个主要方法。

    hash_vector(self,v)
    

    hash_vector() 函数计算指定的向量的哈希并返回包含一个或多个条目的后备数据库键。
    LSH RandomBinaryProjections将特定向量投影到特征空间中的n个随机归一化向量,并返回由’0’和’1’组成的字符串。如果向量v位于第n个法向量的正侧,则字符串中的第n个字符为’1’,如果v位于其负侧,则字符串中的第n个字符为’0 ”。这样,LSH将特征空间(“输入空间”)的每个可能向量投影到许多可能的后备数据单元中。
    LSH RandomDiscretizedProjections几乎与RandomBinaryProjections完全相同。唯一的区别是,即将投影值除以bin宽度,并使用每个随机投影中的bin索引作为bucket key(后备存储单元)的一部分。给定与RandomBinaryProjections相同的随机投影向量计数,这会在给定相同向量集的情况下产生更多Bucket(后备存储单元)。Bucket的密度可以由bin宽度控制,bin宽度是构造器的一部分。
    使用构造函数指定的向量训练集训练LSH PCABinaryProjections。构造函数执行PCA(主成分分析)以找到训练集中最高方差的方向。然后,它使用前n个主成分作为投影向量(或投影到子空间的维度)。这个想法是,这使得在桶之间获得良好的向量分布更加安全。我对此没有任何测试,也不知道这是否有意义。
    LSH PCADiscretizedProjections是RandomDiscretizedProjections的pca版本,不使用随机向量,而是训练集的前n个主成分,就像PCABinaryProjections的做法一样。

    Hash configurations — 哈希配置

    要在Redis中保存索引并在索引过程完成后重新使用它,您应该保持哈希配置 ,以便之后可以重新创建相同的引擎以进行更多索引或查询。
    示例代码如下:

    # Create redis storage adapter
    redis_object = Redis(host='localhost', port=6379, db=0)
    redis_storage = RedisStorage(redis_object)
    
    # Get hash config from redis
    config = redis_storage.load_hash_configuration('MyHash')
    
    if config is None:
        # Config is not existing, create hash from scratch, with 10 projections
        lshash = RandomBinaryProjections('MyHash', 10)
    else:
        # Config is existing, create hash with None parameters
        lshash = RandomBinaryProjections(None, None)
        # Apply configuration loaded from redis
        lshash.apply_config(config)
    
    # Create engine for feature space of 100 dimensions and use our hash.
    # This will set the dimension of the lshash only the first time, not when
    # using the configuration loaded from redis. Use redis storage to store
    # buckets.
    engine = Engine(100, lshashes=[lshash], storage=redis_storage)
    
    # Do some stuff like indexing or querying with the engine...
    
    # Finally store hash configuration in redis for later use
    redis_storage.store_hash_configuration(lshash)
    

    ===========
    Example usage:

    from nearpy import Engine
    from nearpy.hashes import RandomBinaryProjections
    
    # Dimension of our vector space
    dimension = 500
    
    # Create a random binary hash with 10 bits
    rbp = RandomBinaryProjections('rbp', 10)
    
    # Create engine with pipeline configuration
    engine = Engine(dimension, lshashes=[rbp])
    
    # Index 1000000 random vectors (set their data to a unique string)
    for index in range(100000):
        v = numpy.random.randn(dimension)
        engine.store_vector(v, 'data_%d' % index)
    
    # Create random query vector
    query = numpy.random.randn(dimension)
    
    # Get nearest neighbours
    N = engine.neighbours(query)
    

    ============

    本文翻译自NearPy的 README.md,翻译 By ysg
    如果翻译的有不当的地方,请评论区指出,共同进步。

    展开全文
  • 李航KD树最近邻搜索

    2019-12-04 21:13:02
    李航老师书上的的算法说明没怎么看懂,看了网上的博客,悟出一套循环(建立好KD树以后的最近邻搜索),我想应该是这样的(例子是李航《统计学习算法》第三章56页;例3.3):   步骤 结点查询标记 栈内...

    李航老师书上的的算法说明没怎么看懂,看了网上的博客,悟出一套循环(建立好KD树以后的最近邻搜索),我想应该是这样的(例子是李航《统计学习算法》第三章56页;例3.3):

      步骤 结点查询标记 栈内元素(本次循环结束后) 最近点 最近距离 说明
    A B C D E F G
    初始化 0 0 0 0 0 0 0 0 ABD M=空 Mdis = ∞ 初始化:先将S所在的区域找到,将经过的各个结点依次加入栈中,将查询标记初始化为0
    循环 1 0 0 0 1 0 0 0 AB M=D Mdis = dis(S,D) 取出栈顶元素D,D被查询,更新D的标记为1,计算S与D的距离,比当前最小值小,更新M=D,Mdis = dis(S,D),计算S到D的超平面的距离是否小于Mdis(这里二维就是以S为圆心,Mdis为半径的圆是否与D那维的直线相交,在这里是相交的),小于,将D两侧的子结点加入栈,但是D两侧没有子结点,不加
    2 0 1 0 1 0 0 0 A M=D Mdis = dis(S,D) 取出栈顶元素B,B被查询,更新B的标记为1,计算S与B的距离,不比当前最小值小,不更新,计算S到B的超平面的距离是否小于Mdis,大于,那就只加入B的S那一侧的子结点D,子结点D已经被标记为1,已被查询,不加入
    3 1 1 0 1 0 0 0 C M=D Mdis = dis(S,D) 取出栈顶元素A,A被查询,更新A的标记为1,计算S与A的距离,不比当前最小值小,不更新,计算S到A的超平面的距离是否小于Mdis,小于,将A两侧的子结点加入,子结点B已经被标记为1,被查询,不加入,子结点C标记为0,加入栈
    4 1 1 1 1 0 0 0 E M=D Mdis = dis(S,D) 取出栈顶元素C,C被查询,更新C的标记为1,计算S与C的距离,不比当前最小值小,不更新,计算S到C的超平面的距离是否小于Mdis,大于,只加入C的S那侧的子结点E,子结点E标记为0,没被查询,加入栈
    5 1 1 1 1 1 0 0   M=E Mdis = dis(S,E) 取出栈顶元素E,E被查询,更新E的标记为1,计算S与E的距离,比当前最小值小,更新M=E,Mdis = dis(S,D),计算S到E的超平面的距离是否小于Mdis,小于,将E两侧的子结点加入栈,但是E两侧没有子结点,不加
    6 1 1 1 1 1 0 0   M=E Mdis = dis(S,E) 栈空,循环结束

     

    如果有错,还望大佬们能够指正

    展开全文
  • 文章目录最近邻搜索的若干种方法基于树的方法哈希方法矢量量化方法 最近邻搜索的若干种方法 参考文献[5][6]很好的总结了相似搜索的几类方法,这里简要总结几个核心点。可以将方法分为三大类: 基于树的方法 KD树是其...

    最近邻搜索的若干种方法

    参考文献[5][6]很好的总结了相似搜索的几类方法,这里简要总结几个核心点。可以将方法分为三大类:

    基于树的方法

    KD树是其下的经典算法。一般而言,在空间维度比较低时,KD树的查找性能还是比较高效的;但当空间维度较高时,该方法会退化为暴力枚举,性能较差,这时一般会采用下面的哈希方法或者矢量量化方法。

    哈希方法

    LSH(Locality-Sensitive Hashing)是其下的代表算法。文献[7]是一篇非常好的LSH入门资料。
    对于小数据集和中规模的数据集(几个million-几十个million),基于LSH的方法的效果和性能都还不错。这方面有2个开源工具FALCONN和NMSLIB。

    矢量量化方法

    矢量量化方法,即vector quantization。在矢量量化编码中,关键是码本的建立和码字搜索算法。比如常见的聚类算法,就是一种矢量量化方法。而在相似搜索中,向量量化方法又以PQ方法最为典型。
    对于大规模数据集(几百个million以上),基于矢量量化的方法是一个明智的选择,可以用用Faiss开源工具。
    理解 product quantization 算法
    图像检索:再叙ANN Search

    展开全文
  • 针对高维特征向量存在的最近邻匹配正确率低的问题, 提出了一种基于SURF和快速近似最近邻搜索的图像匹配算法。首先用Fast-Hessian 检测子进行特征点检测, 并生成SURF特征描述向量; 然后通过快速近似最近邻搜索算法...
  • 编者按:最近邻搜索算法能够帮助人们在海量数据中快速搜索到有效内容,但是想要将其应用于实际,则需要解决如何缩短搜索时间的问题。本文将为大家介绍两种减少搜索时间的方法。基于哈希的近似最近邻搜索的方法通过...
  • SRS - 具有微小索引的高维欧几里德空间中的快速近似最近邻搜索 SRS-Mem 是一个 C++ 程序,用于在主存中的高维欧几里德空间中执行近似最近邻搜索。 当前的实现改编自我们的。 主要的修改是使用内存中的多维索引(而...
  • 这实现了用于最近邻和范围搜索的 KD... 最近邻搜索可以按 O(log(p) 时间的顺序进行。m 文件是用 C++ 编写的二进制 MATLAB 函数。包含源代码以及适用于 i386 和 x86_64 系统和 Windows (i386) 上的 Linux 的二进制文件。
  • K-d树进行最近邻搜索的过程演示和详细分解 In this tutorial we will go over how to use a KdTree for finding the K nearest neighbors of a specific point or location, and then we will also go over how to ...
  • 基于二维K-D树的最近邻搜索实现

    千次阅读 2018-06-03 20:55:00
    本文给出了对K-D树的最近邻搜索以及详细的代码,实现的灵感来自博主J_Outsider的博文。本文与前一篇博文《二维K-D树的构造及搜索》有很多的区别:首先,K-D树的构造上采用不同的方式:前一篇使用cell类型来构造树,...
  • 【面经笔记】范围搜索/最近邻搜索

    千次阅读 2017-07-24 16:15:31
    例1:平面上百万个点,设计数据结构求每个点最近的k个点 例2:游戏中打怪时已经各个小怪的坐标,你放一个技能是圆形范围,快速求能...最近邻搜索: k近邻搜索: 参考: http://blog.csdn.net/dark_scope/article/detai
  • 最近邻搜索算法flann repo https://github.com/mariusmuja/flann http://www.qhull.org/
  • 不断向开源社区添砖加瓦的微软近日又有大动作-- 将强大的最近邻搜索算法开源。2019年5月15日,GitHub存储库上的开源社区成员都可以访问微软的空间分区树和图(SPTAG)算法,该算法“允许用户充分利用学习模型在以...
  • 最近邻搜索在搜索领域是常用给的算法,拿我们的1:N的人脸识别举例,假如我们底库中有200百万照片的特征向量(这个数字已经算小的了),每个特征向量是512维,如果用线性搜索的话,那么我们要进行200*512百万次的加法...
  • 这种现象是计算机科学中广泛研究的问题,称为“最近邻搜索”。它的问题是,给定数据集和新的数据点,数据集中哪个数据离新数据点最近?这个问题出现的场景非常丰富,可以是基因搜索、图像查询,或者音乐推荐。 但是...
  • 近似最近邻搜索方法FLANN简介

    万次阅读 2015-09-23 16:50:46
    AR/VR群:244751474 ,欢迎加入,进行项目讨论! ---------------------------------------------...我们可以用下面的方式定义最近邻搜索(NNS)问题:在一个度量空间X给定一组点P=p1,p2,…,pn,这些点必须通过以下方
  • k-d树最近邻搜索算法伪代码: ''' 输入:k-d树根节点root,要查询的结点target 输出:k-d树中距离target最近的结点nearest_node ''' search(root, target): ## 1. 进行二叉查找,建立搜索路径,直到找到一个叶结点...
  • 算法一 knn 中的 最近邻搜索

    千次阅读 2014-11-17 14:35:52
    本文的主要目的是讲一下如何创建k-d tree对目标物体的特征点集合进行数据组织和使用k-d tree最近邻搜索来加速特征点匹配。上面已经讲了特征点匹配的问题其实上是一个最近邻(K近邻)搜索的问题。所以为了更好的引出k...
  • Approximate Nearest Neighbors为接近最近邻搜索,是查找准确度和查找时间데平衡。本文大致介绍了,K决策树、헤一些哈希方法。
  • 谢谢,kd-tree下的knn最近邻搜索具体是怎么工作的,希望不吝赐教。如果能提供源代码就更好了。就举个例子具体说明原理就可以了
  • 利用kd树实现最近邻搜索

    千次阅读 2018-06-09 07:57:53
    输出:x的最近邻1在kd树中找出包含目标点x的叶节点:从根结点出发,递归地向下访问kd树。若目标点x当前维的坐标小于切分点的坐标,则移动到左叶子结点,否则移动到右叶子结点。直到子节点为叶节点为止。2以此叶节点...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,066
精华内容 5,226
关键字:

最近邻搜索