本文首发于 vivo 互联网技术微信公众号 mp.weixin.qq.com/s/wLMvJPXXa…git
做者:Eike Dehlinggithub
翻译:杨振涛数组
本文由来自 Textkernel 的软件与数据工程师 Eike Dehling 于2018年10月23日发布与其Linkedin 的 pulse 上,已得到翻译受权。微信
英文原文连接:www.linkedin.com/pulse/searc…数据结构
目录:
1、Fast Nearest Neighbours
2、Elasticsearch 插件
3、集成工做
4、结论elasticsearch
最近我在帮一个数据科学家同事工程化一个基于深度学习模型的搜索系统。他们的项目是关于在文档嵌入应用深度学习模型,而后使用嵌入向量到咱们的搜索系统中来查找类似文档。工具
一个文档嵌入本质上实际上是一个(长的)数值数组,查找类似文档就至关于查找其余与其较相近的(长的)数值数组;能够采用诸如欧氏距离等来衡量类似性。学习
能够借此来查找类似文档,可是由于不是直接基于关键词而是基于“嵌入”,因此能够自动得到与同义词扩展相媲美的效果。它会查找相关文档,即便它们使用不一样的关键词,所以能比关键词检索表现更好。搜索引擎
已经有解决这种问题的工具了,好比 facebook 的 FAISS 库(github.com/facebookres…)。这个类库速度很是快,而且支持多种智能方法使用嵌入向量实现快速检索。不过它不能友好地集成到相似 Elasticsearch 这样的搜索引擎中。插件
对于 Elasticsearch 来讲,也有一些插件(github.com/muhleder/el…)提供了类似度计算功能,可是它们的速度并不怎么样,由于它们只计算了向量类似度而没有作过滤。
因此咱们本身动手实现了更好的解决方案。
为了更快速检索一般会使用各类“索引”,这种数据结构支持高效地过滤出相关的匹配,而无需单独评估每个匹配。基于关键词的检索通常使用“倒排索引”;基于地理位置的检索,通常使用一种叫作 KD树 的数据结构。咱们也须要诸如此类的机制来快速过滤出最相关的匹配,所以咱们只须要在这个较小的集合上计算精确得分。这一点很是重要,由于在一个高维向量的超大集合上计算距离,是代价很是高昂(慢)的操做。
上文提到的 FAISS 库提供了多种方式来解决这个问题:
这些方法中的每一种都能实现高效的索引方法,所以能够快速地筛选出较近邻的文档,而后经过计算精确的距离来查找最近邻文档。在降维之后就可使用 KD树,聚类或者局部敏感哈希后也可使用倒排索引。
上图揭示了如何经过过滤数据集来加速计算,须要计算精确距离的文档数与计算时间之间是线性关系;同时也说明了高效地过滤掉不类似文档多么重要。
固然全部这些方法都是有可能在 Elasticsearch 里获得实现的,其优势是便于和其余检索系统集成。届时就能够组合使用关键词查询或其余基于深度学习的查询结果了。
实验代表在咱们的数据集上,结合了 PCA 降维后再使用 KD 树索引,能带给咱们速度和精度的最佳y组合。
上图揭示了缩小数据集是如何影响结果精确度的。可以看到,过滤得太狠意味着咱们会丢失一些最近邻文档;而若是过滤掉 50k 到 75k 的文档,就能够找到全部的最近邻文档,同时计算时间只占暴力计算全部距离的很小一部分。
在 Lucene 即 Elasticsearch的底层类库中,KD树的数据结构已经实现了,但尚未经过 Elasticsearch 的 API 暴露出来。已经有插件能够计算精确的向量距离,因此咱们只须要开发一个小插件来支持使用这种索引结构便可。参见这里:github.com/EikeDehling…
如今集成工做只是至关于把拼图图片按照正确的顺序拼到一块儿:
安装插件、建立索引以及添加文档请参考这里(github.com/EikeDehling…)。完成这些步骤后,如今就可使用咱们的嵌入向量了!请注意 pca_reduced_vector 上的范围查询,这才是咱们新插件起到的做用。
咱们展现了如何应用深度学习向量来实现高效的搜索。这一方法适用于想要寻找类似文档而普通关键词查询不够好的任何应用场景。其中的嵌入向量,可使用诸如 doc2vec 等来实现。
更多内容敬请关注 vivo 互联网技术 微信公众号
注:转载文章请先与微信号:labs2020 联系。