我们使用annoy
库(Approximate Nearest Neighbors Oh Yeah),它是一种基于随机树的近似最近邻搜索算法,具有类似的高效和可扩展性。
首先,需要安装annoy
库:
pip install annoy
然后,可以按照以下步骤实现一个简单的近似最近邻搜索Demo:
- 创建一些随机向量数据。
- 构建Annoy索引。
- 执行近似最近邻搜索。
import random
from annoy import AnnoyIndex
# 设置参数
vector_length = 40 # 向量的维度
num_vectors = 1000 # 向量的数量
num_trees = 10 # 用于构建Annoy索引的树的数量
# 初始化Annoy索引
index = AnnoyIndex(vector_length, 'euclidean')
# 创建随机向量并添加到索引中
for i in range(num_vectors):
vector = [random.gauss(0, 1) for _ in range(vector_length)]
index.add_item(i, vector)
# 构建索引
index.build(num_trees)
# 查询:找到距离给定向量最近的5个向量
query_vector = [random.gauss(0, 1) for _ in range(vector_length)]
nearest_neighbors = index.get_nns_by_vector(query_vector, 5)
# 输出结果
print("Query vector:", query_vector)
print("Nearest neighbors:", nearest_neighbors)
# 获取最近邻向量的距离
for neighbor in nearest_neighbors:
distance = index.get_distance(neighbor, query_vector)
print(f"Neighbor {neighbor} distance: {distance}")
# 保存索引到磁盘
index.save('annoy_index.ann')
# 加载索引
loaded_index = AnnoyIndex(vector_length, 'euclidean')
loaded_index.load('annoy_index.ann')
# 再次执行查询
nearest_neighbors_loaded = loaded_index.get_nns_by_vector(query_vector, 5)
print("Nearest neighbors (loaded index):", nearest_neighbors_loaded)
代码解释
-
初始化Annoy索引:
index = AnnoyIndex(vector_length, 'euclidean')
创建一个Annoy索引对象,指定向量的维度和距离度量方式(欧几里得距离)。
-
添加向量到索引:
for i in range(num_vectors): vector = [random.gauss(0, 1) for _ in range(vector_length)] index.add_item(i, vector)
生成随机向量并添加到索引中。
-
构建索引:
index.build(num_trees)
使用指定数量的树构建索引,树的数量越多,查询结果越准确,但构建和查询速度会稍慢。
-
执行查询:
query_vector = [random.gauss(0, 1) for _ in range(vector_length)] nearest_neighbors = index.get_nns_by_vector(query_vector, 5)
使用随机生成的查询向量,找到最近的5个邻居向量。
-
保存和加载索引:
index.save('annoy_index.ann') loaded_index = AnnoyIndex(vector_length, 'euclidean') loaded_index.load('annoy_index.ann')
将索引保存到磁盘,并从磁盘加载索引。