在嵌入上进行 1 与所有查找的最快方法

数据挖掘 机器学习 伯特 嵌入 余弦距离 类似文件
2022-02-22 15:48:06

我有一个包含大约 1 000 000 条文本的数据集,我用语言模型计算了它们的句子嵌入,并将它们存储在一个 numpy 数组中。

我希望将一个新的看不见的文本与所有 1 000 000 个预先计算的嵌入进行比较,并执行余弦相似度来检索语料库中语义最相似的文档。

执行这种 1-vs-all 比较最有效的是什么?

我会感谢任何指示和反馈!

3个回答

有专门从事该任务的库,例如Facebook AI Research 的FAISS

Faiss 是一个用于高效相似性搜索和密集向量聚类的库。它包含在任意大小的向量集中搜索的算法,直到那些可能不适合 RAM 的向量。它还包含用于评估和参数调整的支持代码。Faiss 是用 C++ 编写的,带有 Python/numpy 的完整包装器。一些最有用的算法是在 GPU 上实现的。它由 Facebook AI Research 开发。

对于余弦相似度,您可以使用 FAISS 类IndexFlatIP首先对向量进行归一化,如 FAISS 文档中所述

如果你想了解更多关于 FAISS 背后的技术,你可以看看他们的研究论文,如果你想了解更多关于相似度搜索的基本知识,你可以看看Flickr 的这篇博文。

FAISS 的一些替代品是AnnoyNMSLibYahoo 的 NGT您可以在此处此处找到这些库和其他库的一些比较

@lsbister,

您可以创建一个 pandas 数据框并使用 dask 函数/lambda 函数同时并行化一个与所有的计算。

如果您使用 dask,您可以创建分区并将响应映射回来。如果您使用 pandas,您可以使用 apply 函数并在一定程度上并行计算。

我建议也给 gensim 一个机会。与其他自行编写的“余弦相似度检索 top_n”函数相比,它的速度非常快。
将嵌入保存在 .txt 或 .csv 文件中,然后使用命令“load_word2vecformat”加载它。加载模型后,您可以使用函数 'similar_by_word' 或 'similar_by_vector' 来检索 n 个最接近的向量。

from gensim.models import KeyedVectors

model = KeyedVectors.load_word2vec_format(datapath('model_file'), binary=False)   
top_10 = model.similar_by_word('cat')

当您保存文件以将嵌入的数量(在您的情况下为 1M)和向量维度包含为第一行时,请注意。它只是 gensim 标准格式,文件应该是这样的:

1000000, 300
'.', -0.0001, -0.0001, ... 
',', -0.0001, -0.0001, ...
'a', -0.0001, -0.0001, ...