NGT:用于高速近似最近邻搜索的库

NGT 是一个高性能的开源深度学习库,适用于大规模和高维向量。
99 位读者喜欢这篇文章。
Houses in a row

27707 通过 Pixabay, CC0。由 Jen Wike Huger 修改。

近似最近邻 (ANN) 搜索在深度学习中用于最佳猜测给定集合中与另一点最相似的点。本文解释了 ANN 搜索与传统搜索方法之间的区别,并介绍了 NGT,这是一个由 Yahoo! Japan Research 开发的顶尖开源 ANN 库。

高维数据的最近邻搜索

不同的搜索方法用于不同的数据类型。例如,全文搜索用于文本数据,基于内容的图像检索用于图像,关系数据库用于数据关系。深度学习模型可以轻松地从各种数据中生成向量,从而使向量空间在源数据之间具有嵌入式关系。这意味着如果两个源数据相似,则来自这两个数据的向量将位于向量空间中彼此附近。因此,您所要做的就是搜索向量而不是源数据。

此外,向量不仅代表源数据的文本和图像特征,还代表产品、人类、组织等等。因此,您可以搜索相似的文档和图像,以及具有相似属性的产品、具有相似技能的人、具有相似特征的服装等等。例如,Yahoo! Japan 使用 NGT 提供基于相似性的时尚物品搜索。

Nearest neighbour search

由于深度学习模型中的维度数量趋于增加,因此当搜索超过数百万个高维向量时,ANN 搜索方法是必不可少的。ANN 搜索方法允许您在高维空间中搜索指定查询向量的邻居。

有许多最近邻搜索方法可供选择。 ANN Benchmarks 评估了最著名的 ANN 搜索方法,包括 Faiss (Facebook)、Flann 和 Hnswlib。根据此基准测试,NGT 实现了顶级的性能。

NGT 算法

NGT 索引结合了图和树。这种组合实现了非常好的搜索性能,其中图的顶点代表可搜索的对象。相邻的顶点通过边连接。

此动画展示了图是如何构建的。

NGT graph construction

在搜索过程中,可以通过下降图来找到指定查询的相邻顶点。密集连接的顶点使用户能够有效地探索图。

NGT graph

NGT 提供了命令行工具,以及 C、C++ 和 Python API。本文重点介绍命令行工具和 Python API。

使用 NGT 命令行工具

Linux 安装

下载最新版本的 NGT ZIP 文件,并在 Linux 上使用以下命令安装:

unzip NGT-x.x.x.zip
cd NGT-x.x.x
mkdir build
cd build 
cmake ..
make 
make install

由于 NGT 库默认安装在 /usr/local/lib(64) 中,请将该目录添加到搜索路径

export PATH="$PATH:/opt/local/bin"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"

示例数据集生成

在搜索大规模数据集之前,您必须生成一个 NGT 数据集。例如,从 fastText 网站下载 fastText 数据集,然后使用以下命令将其转换为 NGT 注册格式:

curl -O https://dl.fbaipublicfiles.com/fasttext/vectors-english/wiki-news-300d-1M-subword.vec.zip
unzip wiki-news-300d-1M-subword.vec.zip
tail -n +2 wiki-news-300d-1M-subword.vec | cut -d " " -f 2- > objects.ssv

Objects.ssv 是一个包含 100 万个对象的注册文件。文件中的一个对象被提取作为查询。

head -10000 objects.ssv | tail -1 > query.ssv

索引构建

可以使用以下命令构建 ngt_index

ngt create -d 300 -D c index objects.ssv

-d 指定向量的维度数。-D c 表示使用余弦相似度。

可以使用以下命令搜索 ngt_index

ngt search -n 10 index query.ssv

-n 指定结果对象的数量。

搜索结果是:

Query No.1
Rank    ID      Distance
1       10000   0
2       21516   0.184495
3       201860  0.240375
4       71865   0.241284
5       339589  0.267265
6       485158  0.280977
7       7961    0.283865
8       924513  0.286571
9       28870   0.286654
10      395274  0.290466
Query Time= 0.000972628 (sec), 0.972628 (msec)
Average Query Time= 0.000972628 (sec), 0.972628 (msec), (0.000972628/1)

有关更多信息,请参阅 NGT 命令行 README

从 Python 使用 NGT

虽然 NGT 具有 C 和 C++ API,但 ngtpy Python 绑定是编程最简单的选择。

安装 ngtpy

通过 PyPI 安装 Python 绑定 (ngtpy):

pip3 install ngt

示例数据集生成

使用此代码从您下载的示例数据集中为 Python 示例程序生成数据文件:

dataset_path = 'wiki-news-300d-1M-subword.vec'
with open(dataset_path, 'r') as fi, open('objects.tsv', 'w') as fov,
open('words.tsv', 'w') as fow:
    n, dim = map(int, fi.readline().split())
    fov.write('{0}¥t{1}¥n'.format(n, dim))
    for line in fi:
        tokens = line.rstrip().split(' ')
        fow.write(tokens[0] + '¥n')
        fov.write('{0}¥n'.format('¥t'.join(tokens[1:])))

索引构建

使用以下命令构建 NGT 索引:

import ngtpy

index_path = 'index'
with open('objects.tsv', 'r') as fin:
    n, dim = map(int, fin.readline().split())
    ngtpy.create(index_path, dim, distance_type='Cosine') # create an index
    index = ngtpy.Index(index_path) # open the index
    print('inserting objects...')
    for line in fin:
        object = list(map(float, line.rstrip().split('¥t')))
        index.insert(object) # insert objects
print('building objects...')
index.build_index()
print('saving the index...')
index.save()

近似最近邻搜索

这是一个 ANN 搜索程序示例:

import ngtpy

print('loading words...')
with open('words.tsv', 'r') as fin:
    words = list(map(lambda x: x.rstrip('¥n'), fin.readlines()))

index = ngtpy.Index('index', zero_based_numbering = False) # open index
query_id = 10000
query_object = index.get_object(query_id) # get the object for a query

result = index.search(query_object) # aproximate nearest neighbor search
print('Query={}'.format(words[query_id - 1]))
print('Rank¥tID¥tDistance¥tWord')
for rank, object in enumerate(result):
    print('{}¥t{}¥t{:.6f}¥t{}'.format(rank + 1, object[0], object[1], words[object[0] - 1]))

这是搜索结果,与 NGT 命令行选项的结果相同:

loading words...
Query=Horse
Rank    ID      Distance        Word
1       10000   0.000000        Horse
2       21516   0.184495        Horses
3       201860  0.240375        Horseback
4       71865   0.241284        Horseman
5       339589  0.267265        Prancing
6       485158  0.280977        Horsefly
7       7961    0.283865        Dog
8       924513  0.286571        Horsing
9       28870   0.286654        Pony
10      395274  0.290466        Blood-Horse

有关更多信息,请参阅 ngtpy README

近似最近邻 (ANN) 原理是分析数据的重要特征。学习如何在您自己的项目中使用它,或理解您正在分析的数据,是建立关联和解释信息的强大方法。借助 NGT,您可以以任何您需要的方式使用 ANN,或者在其基础上添加自定义功能。

接下来阅读
标签
Avatar
他于 2007 年加入 Yahoo! JAPAN Research。他的研究兴趣包括图像识别、图像检索和高维数据检索。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.