AI基于近邻图的向量搜索案例(二)

发布时间:2024年01月21日

Graph部分

Graph部分,通过先构建KNN图,再根据RNG Rule移除不符合要求的边,得到RNG。

KNN图的构建

KNN图是指对于样本数据中的每一个点,将其自身与K个近邻点连接而形成的图。

由于样本数据规模非常大,我们采用了一定的算法构建近似的KNN图,具体算法[1]如下:

  1. 随机划分一组子空间。在这里我们可以采用不同的划分方式,SPTAG采用了TPTree[2]的方式划分,即通过构建一定深度的TPTree,取其中一个叶子结点的作为子空间。
  2. 对该子空间内的点,利用Brute-Force方式,构建KNN子图。
  3. 重复以上步骤N次。N越大,得到的KNN图越接近真实的KNN图。

由于每次随机划分一组子空间,会包含部分新的近邻点,而与之前划分的空间重叠的近邻点,可以将两组子空间构建的KNN子图连接成更大的KNN图。因此,划分次数越多,KNN子图越大,直到得到真实的KNN图为止。

例如,

  1. 第一次划分出一组子空间,样本中包含了两个p点的真实最近邻p4和p6,利用Brute-Force对该子空间构建KNN图后,P点会与这两个点连接,得到kNN子图。

  2. 在第二次划分子空间的时候,样本中包含了两个新的真实最近邻p3和p5,对该子空间构建KNN后,会使p点与p3和p5相连,此时的kNN图已经包含了4个p的真实最近邻。

  3. 继续重复多次划分并对划分的子空间构建KNN图后,会使p点与大部分的真实最近邻连通,从而构建比较接近真实KNN图的近似KNN图。

注:

KNG的构建

基于KNN图,我们需要根据RNG Rule删除不符合要求的边。这样做的目的是避免陷入局部最优。

RNG Rule:删除三角形中的最长的边。

对于KNN图,若点a, b, q相互连接,我们要分别计算3点的距离,删除最长的边。例如,图中需删除qb边,因为我们可以通过a从q访问到b。

SPTAG的使用

安装

确保安装以下依赖:

  • 斯威格>= 3.0
  • cmake >=3.12.0
  • 升压 == 1.67.0

Window安装可以参考文档:Windows Installation

构建

  1. 克隆仓库mcirosoft/SPTAG。

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>git clone https://github.com/microsoft/SPTAG
    </code></span></span></span>
  2. 进入克隆的仓库的目录,执行以下命令:

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> mkdir build
     cd build
     cmake -A x64 ..
    </code></span></span></span>

    注:如果提示“CMAKE Could not find Boost 1.67”,可以使用以下命令指定Boost目录。

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> cmake -DBOOST_ROOT=[your boost root] -DBOOST_INCLUDEDIR=[your boost include directory] -DBOOST_LIBRARYDIR=[your boost library directory] ..
    </code></span></span></span>

    其中,

    • BOOST_INCLUDEDIR:C:\INSTALL_DIR\boost_1_67_0\
    • BOOST_LIBRARYDIR:C:\INSTALL_DIR\boost_1_67_0\lib64-msvc-12.0
    • BOOST_ROOT:C:\INSTALL_DIR\boost_1_67_0\boost
  3. 进入刚刚新建的目录,在Visual Studio中打开,编译运行。buildSPTAGLib.sln

  4. 编译完成后,会在目录下生成我们需要的内容,将这个目录添加到环境变量中。build/releasePYTHONPATH

  5. 打开Python,执行,若无报错则已完成SPTAG的构建。import SPTAG

使用

完成了SPTAG的构建后,我们可以在Python中使用,下面是SPTAG的Python接口。详细使用内容请参考:SPTAG Quick Start

Python接口

  1. 初始化索引

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>SPTAG.AnnIndex(algo, type, dimension)
        algo: 索引算法的类型,可选'BKT', 'KDT'
        type: 向量数据类型,如'Float','Int8', 'Int16'
        dimension: 输入向量的维度
    </code></span></span></span>
  2. 设置构建参数

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> SPTAG.AnnIndex.SetBuildParam(key,value)
         key: 参数名
         value:参数值
    </code></span></span></span>
  3. 构建索引

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> SPTAG.AnnIndex.Build(vectors, sample_num)
         vectors: 输入向量数据集
         sample_num: 输入向量的数量
    </code></span></span></span>
  4. 保存索引

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> SPTAG.AnnIndex.Save(index)
         index: 输出保存的索引名,加载索引时需指定
    </code></span></span></span>
  5. 加载索引

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> SPTAG.AnnIndex.Load(index)
         index: 待加载的索引名 
    </code></span></span></span>
  6. 搜索

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> SPTAG.AnnIndex.Search(query, k)
         query: 查询向量
         k: 指定返回前k个最近邻
    </code></span></span></span>
  7. 添加至索引

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> SPTAG.AnnIndex.Add(vectors, sample_num)
         vectors: 待添加向量数据集
         sample_num: 待添加向量的数量
    </code></span></span></span>
  8. 从索引中删除

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> SPTAG.AnnIndex.Delete(vectors, sample_num)
         vectors: 待删除向量数据集
         sample_num: 待删除向量的数量
    </code></span></span></span>

使用示例

下面我们提供了两个SPTAG的使用示例。

随机数据示例

我们先随机生成包含100条2维的随机向量数据集

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>import numpy as np

d = 2  # Dimension
nb = 100  # Dataset size

np.random.seed(1234)
randomData = np.random.random((nb,d)).astype('float32')
</code></span></span></span></span>

利用生成的数据构建索引testIndex

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>import SPTAG

# Build index
algorithm = 'KDT' # 'BKT' or 'KDT'
distmethod = 'L2' # 'L2' or 'Cosine'

i=SPTAG.AnnIndex(algorithm,'Float',randomData.shape[1])
i.SetBuildParam("NumberOfThreads",'4')
i.SetBuildParam("DistCalcMethod",distmethod)

if i.Build(randomData,randomData.shape[0]):
    i.Save("testIndex")
</code></span></span></span></span>

任意指定查询向量,在此我们指定查询向量xq为[0.2, 0.4]。加载索引,搜索并指定返回前4个与xq的最近邻。testIndex

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code># Search

k=4 # Number of results to return
xq = np.array([0.2 , 0.4 ]).astype('float32') # The query vector

i = SPTAG.AnnIndex.Load('testIndex') # load index

result = i.Search(xq,k)

print(result[0]) # ids
print(result[1]) # distances
</code></span></span></span></span>
图片向量搜索示例

图片向量搜索的原理如下图:

首先,利用VGG16模型将图片数据集转换成向量,再利用SPTAG构建索引。

当给定查询图片时,我们利用同样的算法将图片转换成查询向量,使用查询向量在索引中搜索K个最近邻向量,搜索得到的结果中的metadata存储了向量对应的图片路径,通过该路径可以找出对应的图片。

文章来源:https://blog.csdn.net/2301_81887304/article/details/135689984
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。