pysparnn原理介绍

注意:当数据不稀疏的时候,faiss和annoy比较合适。但是,当数据维度较高,且为稀疏数据的时候,应该考虑使用PySparNN。

pysparnn使用的是一种cluster pruning(簇修剪)的技术,即,开始的时候对数据进行聚类,后续再有限个类别中进行数据的搜索,根据计算的余弦相似度返回结果。

数据预处理过程

  • 随机选择N \sqrt{N}N个样本作为leader
  • 选择非leader的数据(follower),使用余弦相似度计算找到最近的leader

查询过程

  • 计算每个leader和q的相似度,找到最相似的leader

  • 然后计算问题q和leader所在簇的相似度,找到最相似的k个,作为最终的返回结果


在上述的过程中,可以设置两个大于0的数字b1b2

  • b1表示在数据预处理阶段,每个follower选择b1个最相似的leader,而不是选择单独一个lader,这样不同的簇是有数据交叉的;

  • b2表示在查询阶段,找到最相似的b2个leader,然后再计算不同的leader中下的topk的结果。
    前面的描述就是b1=b2=1的情况,通过增加b1和b2的值,我们能够有更大的机会找到更好的结果,但是这样会需要更加大量的计算。

pysparnn实例化

在索引过程中,即:ci.MultiClusterIndex(features, records_data, num_indexes)中,num_indexes能够设置b1的值,默认为2。即leader,然后再计算不同的leader中下的topk的结果。

在搜索的过程中,cp.search(search_vec, k=8, k_clusters=10, return_distance=True,num_indexes)num_Indexes可以设置b2的值,默认等于b1的值。

代码

import pysparnn.cluster_index as ci
from sklearn.feature_extraction.text import TfidfVectorizer

data = [
    "hello world",
    "oh hello there",
    "Play it",
    "Play it again Sam",
]

tv = TfidfVectorizer()
tv.fit(data)
# 特征向量
features_vec = tv.transform(data)

# 建立搜索索引
cp = ci.MultiClusterIndex(features_vec, data)

# 搜索带有索引的
search_data = [
    "oh there",
    "Play it again Frank"
]

search_feature_vec = tv.transform(search_data)
# k是返回的个数,k_clusters代表聚类的个数
print(cp.search(search_feature_vec, k=1, k_clusters=2, return_distance=False))