facebook-faiss库 - YiLiang - CSDN博客

标签: | 发表时间:2018-10-12 10:59 | 作者:
出处:https://blog.csdn.net

三月初,Facebook AI Research(FAIR)开源了一个名为 Faiss 的库,Faiss 主要用于有效的相似性搜索(Similarity Search)和稠密矢量聚类(Clustering of dense vectors),包含了在任何大小的矢量集合里进行搜索的算法。Faiss 上矢量集合的大小甚至可以大到装不进 RAM。这个库基本上是用 C++ 实现的,带有可选的通过 CUDA 提供的 GPU 支持,以及一个可选的 Python 接口。

通过 Faiss 进行相似性搜索时,10 亿图像数据库上的一次查询仅耗时 17.7 微秒,速度较之前提升了 8.5 倍,且准确度也有所提升。

耗时 17.7 微秒、提速 8.5 倍,Facebook AI 相似性搜索库 Faiss 的核心奥义究竟在哪?

除图片检索外,相似性搜索还有更广阔的运用场景。例如,通过搜索数据库来判断某一罪行是否属于较严重的犯罪形式,或有重罪趋势;通过搜索和成功店铺所在地相似的人口特征和环境特征,来寻找零售商新店的最佳位置;通过相似城市的搜索,来衡量所在城市薪资水平是否合理等。

日前,Facebook 发布了一份关于 Faiss 原理的介绍,36氪对此进行了编译和整理,具体内容如下:

关于相似性搜索

传统的数据库由包含符号信息的结构化表格组成。举例来说,一个图片集合的呈现方式是一个列表,这个列表的每一行都有一张索引照片,同时包含图像标识、描述语句等信息。每一行的信息也可以连接其他表格,如一张包含人物的照片可以连接到姓名表上。

大部分 AI 工具都会生成高维矢量,如以 word2vec 为代表的文字嵌入工具,和用于深度学习训练的 CNN 描述符(Convolutional Neural Net)等。在这篇文章中,我们将阐述为什么高维矢量数据比固定符号数据更强大且灵活。不过,使用 SQL 查询的传统数据库并不适用这些新型表述方式:首先,海量的多媒体信息流创造了数十亿矢量;其次,更重要的一点是,找到类似的条目意味着要找到类似的高维矢量,这对标准的查询语言来说是极其低效甚至是不可能的。

如何应用矢量表述?

让我们假设你现在有一张建筑的照片,这个建筑是某个中型城市的市政府,但你已经记不清名字了,然后你想在整个图片集合中找到这个建筑的其他所有照片。这种情况下使用传统的 SQL 语句来完成关键字查询是不可能的,因为你已经忘记了这个城市的名字。

相似性搜索此刻却能派上用场,图片的矢量描述是为了针对相似图片制造出相似的矢量,这些矢量被定义为临近欧几里得空间的向量。

矢量描述的另一个应用是分类。假设你需要一个分类器来判定一个图像集合中哪些图片代表的是小雏菊。分类器的训练是一个比较知名的过程:该算法会输入雏菊图像和非雏菊图像(如汽车、绵羊、玫瑰、向日葵等)。如果分类器是线性的,则会输出一个分类矢量,

所以,针对相似性搜索和分类,我们需要进行如下操作:

  • 给定一个查询矢量,回到欧几里德空间中最接近这个矢量的数据库对象列表。

  • 给定一个查询矢量,回到有最高向量点积德数据库对象列表。

有一个挑战是,我们希望这些操作可以以数十亿矢量的规模来运行。

软件包

目前投入应用的软件工具还不足以支持上述数据研究的进行。传统的 SQL 数据库系统不切实际,因为它们是针对 hash-based searches 或 1D interval searches 而优化的。相似性搜索功能在 OpenCV 这类工具包中受到的扩展性限制较大,一些针对“小”数据集(比如仅 100 万个矢量)的相似性搜索算法库也是如此。

耗时 17.7 微秒、提速 8.5 倍,Facebook AI 相似性搜索库 Faiss 的核心奥义究竟在哪?

Faiss 是一个打破了以上提到的所有限制的算法库,其优点有:

  • Faiss 提供了多种相似性搜索方法,可以针对不同的使用方法,进行跨度较大的功能取舍。

  • Faiss 针对内存使用和速度进行了优化。

  • Faiss 为最相关的索引方法提供了先进的 GPU 实现方案。

评估相似性搜索

一旦矢量被学习机器提取(从图像、视频、文档等),就可以被输入到相似性搜索库中。

我们拥有一个作为参考的暴力算法,能精确而详尽地计算出所有相似性,并且返回到最相似的元素列表中。这提供了一个“黄金标准”参考结果列表。但值得注意的是,高效实施暴力算法并不容易,并且暴力算法经常会影响到系统其他组件的效果。

如果我们愿意牺牲一部分精确度,相似性搜索的速度可以提高几个数量级,但是会偏离参考结果。例如,将图像相似性搜索的第一和第二个结果交换,可能没有什么太大影响,因为它们都是给定查询的正确结果。加速搜索涉及一些数据集合的预处理,我们将这项操作称之为“索引”。

这使我们确定了三个感兴趣的研究指标:

  • 速度

在整个数据库中寻找 10 个(或其他数字)最相近的矢量需要花费多长时间?最好的情况是比暴力算法耗时短,否则索引就没有任何意义了。

  • 内存用量

这个方法需要多少 RAM?比传统矢量多还是少?Faiss 仅支持在 RAM 搜索,因为磁盘数据库的数量级要慢一些,即使是 SSD。

  • 准确度

返回的结果列表和暴力搜索结果的匹配度如何?准确度可以通过对结果列表中优先返回最邻近单位的检索数量进行评估,或者是通过衡量 10 个最先返回的最邻近单位的平均分数来评估(这种方法被称为“10-intersection”)。

我们通常会评估固定内存使用速度和精度之间的关联。Faiss 采用的是压缩原始矢量的方法,因为这是扩展到十亿级矢量数据库的唯一方法:以每个矢量占用 32 字节计,当规模达到 10 亿矢量后,这些矢量会占据大量的存储空间。

大部分索引库包含约 100 万个矢量,我们认为这个规模很小。比如说, nmslib 拥有非常有效的算法,速度比 Faiss 快,但同时需要更多的存储空间。

评估十亿个矢量

工程界中对于这种规模的数据集并没有一个完善的标准,我们比较了一些研究结果,并进行评估。

Deep1B 是一个有 10 亿张照片的图像库,我们在这上面评估精度。每张照片都被卷积神经网络(CNN)处理过,且 CNN 中的一个激活图(activation map)会被当作图像描述符(descriptor)。这些矢量可以和欧氏距离进行比较,以量化图像之间的相似度。

Deep1B 有一个小的图像检索库,且处理了这些图像的暴力算法提供了一个真实的相似性搜索结果。因此,如果我们运行搜索算法,我们可以评估结果中的 1-recall@1。

选择索引

为了评估,我们把内存空间大小限定为 30GB RAM。这个内存空间约束我们选择索引方法和参数。在 Faiss 中,索引方法具体表现为一个字符串,如:OPQ20_80,IMI2x14,PQ20。

这个字符串指示了用于矢量预处理的具体步骤(OPQ20_80),一个指示数据库应该如何被分割的选择机制(IMI2x14),以及一个指示产品量化编码矢量的编码组件(PQ20),这个编码组件会产生成 20 字节的代码。因此,内存使用(包括间接使用)低于 30 GB RAM。

我们知道这听起来有点“太技术”,因此 Faiss 的开发文件会提供相应的指导,即如何根据你的需求来提供最合适的索引类型。

一旦确定了索引类型,检索就开始了。这个算法会处理 10 亿个矢量,并将这些矢量置于所一个索引中。索引可以存储在磁盘上,或者立即使用,同时索引中的搜索、添加/删除可以交叉输入。

在索引中检索

索引就绪后,可以设置一组搜索事件参数来调整检索方法。为了评估,我们使用单线程进行搜索。由于内存使用量已经被固定,我们需要优化精确度和搜索时间之间的权衡。这也意味着,我们要能在尽可能少的时间内,使 1-recall@1 达到 40%。

幸好,Faiss 有一个自动调节机制,可以扫描参数空间,并收集提供最佳操作点的空间,也就是在给定精度的情况下最好的潜在搜索时间,反之亦然。在 Deep1B 中,操作点可以进行可视化,如下图所示:

耗时 17.7 微秒、提速 8.5 倍,Facebook AI 相似性搜索库 Faiss 的核心奥义究竟在哪?

在这个量化表中,我们可以看到,使 1-recall@1 达到 40% 的查询时间少于 2 微秒/矢量,或者将时间限定为 0.5 微秒,我们可以达到 30%。2 微秒的检索时间意味着在一个单核上每秒查询 500 次(500 QPS)。

这个结果可以和这个领域中最先进的研究结果进行比较。Babenko 和 Lempitsky 于 2016 年撰写了一篇名为 “ Efficient Indexing of Billion-Scale Datasets of Deep Descriptors” 的论文,论文中提到,使用 Deep1B 时,他们需要花费 20 微秒来使 1-recall@1 达到 45%。

用 GPU(图形处理器)处理十亿级数据集

许多的研究都在致力于  GPU 的实施,在原生多 GPU 的支持下,产生了令人惊讶的单机性能。GPU 的实施可以看作是对应 CPU 的替代,使用 GPU 时你甚至不需要知道 CUDA API。Faiss 支持所有 2012 年后发布的英伟达 GPU(开普勒,计算能力 3.5+)。

我们希望将  roofline model 作为指导,它指出,开发者应尽可能让内存带宽或浮点单位饱和。Faiss GPU 在单个 GPU 上的速度比相应的 Faiss CPU 快 5-10倍。如果是使用新的帕斯卡级硬件,如英伟达 P100,那么速度会快 20 倍以上。

以下是一些性能方面的数字:

  • 通过相似索引,可以在 35 分钟内(包括索引构建时间),在四路 Maxwell Titan X  GPU 上构建一个简单的 k-nearest-neighbor 图(k=10),基于 YFCC100M 数据集合 9500 万图像的 128D CNN 描述符,以及 0.8 的10-intersection。

  • 十亿矢量的 k-nearest-neighbor 图也已实现。开发者可以在 Deep1B 数据集上创建强力的 k-nearest-neighbor 图(k=10),0.65 的 10-intersection 在四路 Maxwell Titan X  GPU 下需要 12 个小时。而 0.8 的 10-intersection 在八路帕斯卡 P100-PCle GPU 上也需要 12 个小时。画质较低的图可以在五小时内通过 Titan X 生成。

  • 其他方面的性能也非常惊人。例如,构建上述 Deep1B 索引需要用 k-means 聚类生成 262,144 个几何中心和 6710 万 120-dim 矢量。在 25 E-M 次迭代下,四路 Titan X GPU(12.6 tflp/s)需要花 139 分钟处理,八路帕斯卡 P100 GPU(40 tflop/s)则需花 43.8 分钟。要注意的是聚类的训练集并不需要和 GPU 显存匹配,因为数据会按需及时导入到 GPU 中,不会影响性能。

其他技术

基于诸多研究成果和大量工程技术,Facebook AI  Research 团队自 2015 年开始研发 Faiss。针对 Faiss, Facebook 选择优化几项基础技术,尤其是在 CPU 方面,Facebook 大量运用了如下技术:

  • 多线程充分利用多核性能,并在多路 GPU 上进行并行搜索;

  • 运用 matrix/matrix 乘法在 BLAS 算法库中进行高效、精确的距离计算。如果没有 BLAS,高效的暴力算法很难呈现最优效果。BLAS/LAPACK 是 Faiss 必备的前提软件;

  • 机器 SIMD 矢量化和 popcount 被用于加速孤立向量的距离计算。

GPU 方面

由于典型的 CPU 算法(如 heap selection)并不适用于 GPU,此前应用在相似性搜索上的 GPU 和 k-selection(寻找 k-minimum 或 k-maximum 因素)一直存在性能方面的问题。对 Faiss GPU 来说,我们设计了文献记载中已知的最快的小 k-selection 算法(k<=1024)。所有的中间状态都被保存在寄存器中,这样有助于提升其速度。它能将输入的数据以 single pass 的方式进行 k-select,运行潜在峰值性能的 55%,这取决于峰值 GPU 的显存带宽。由于其状态仅保留在寄存器文件中,并且能和其他内核一起使用,从而能进行快速准确的相似搜索算法。

研究领域中,许多人把注意力放在高效的平铺策略和面向相似性搜索的内核执行上。Multi-GPU 支持由分片或复制数据来提供,开发者不会受到单 GPU 显存大小的限制。半精度浮点支持(float 16)也有提供,使得开发者可以在支持的 GPU 上进行完整的 float 16 运算。float 16 这样的编码矢量能在几乎不损失精度的情况下提高速度。

总之,连续不断的超量因素在实施中非常重要,Faiss 做了许多关注工程细节的痛苦的工作。

Faiss上手

Faiss 以 C++ 实现,支持 Python。想要上手,需要从 GitHub 上获取 Faiss,编译后将 Faiss 模块导入到 Python 中。Faiss 与 numpy 完全集成,所有的函数都是用 numpy 数组来实现的(in float32)

相关 [facebook faiss yiliang] 推荐:

facebook-faiss库 - YiLiang - CSDN博客

- -
三月初,Facebook AI Research(FAIR)开源了一个名为 Faiss 的库,Faiss 主要用于有效的相似性搜索(Similarity Search)和稠密矢量聚类(Clustering of dense vectors),包含了在任何大小的矢量集合里进行搜索的算法. Faiss 上矢量集合的大小甚至可以大到装不进 RAM.

Faiss,开源的向量索引库

- - IT瘾-dev
《向量数据库,LLM生态的核心组件》介绍了vector index和vector databases,这篇文章介绍 Faiss,它是一个非常流行的vector index,通过这篇文章能大概理解如何应用 Faiss. Faiss 是Facebook开源的一个Python包,它的目标:. It contains algorithms that search in sets of vectors of any size, up to ones that possibly do not fit in RAM..

faiss相似性搜索和向量聚类库 faiss: A library for efficient similarity search and clustering of dense vectors.

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

FAISS + SBERT实现的十亿级语义相似性搜索

- - 雷锋网
译者:AI研习社( FIONAbiubiu). 双语原文链接: Billion-scale semantic similarity search with FAISS+SBERT. 语义搜索是一种关注句子意义而不是传统的关键词匹配的信息检索系统. 尽管有许多文本嵌入可用于此目的,但将其扩展到构建低延迟api以从大量数据集合中获取数据是很少讨论的.

中国的Facebook?

- Lorna - It Talks--上海魏武挥的博客
腾讯近日很低调地推出了一个名为“朋友”的网络服务(也是一个使用独立域名的网站),这是一个与时下社交网站,比如人人、开心等非常类似的产品. 与它们一样,目前这个“朋友”上也加载了一些应用,当然,一贯的,以腾讯自家出品为主. 而且,我个人以为,未来会有更多的腾讯在QQ这个客户端上的应用,逐步向这个网站迁移.

Facebook初探

- 亦农 - 王建硕
今天的湾区阳光灿烂,280州际公路两边的绿色山坡和蔚蓝的白云,让人觉得自己是Windows XP桌面上的一个图标. 下午,2点,终于来到Facebook这个神奇的公司. 他们的新家在南加利福尼亚街的最里面,一幢两层的楼里. 他们刚刚从车位紧张的Palo Alto城里搬到这里,据说一层楼又要搬了. 我好像是他们再次搬地方前的最后一批访客.

Facebook败给Foursquare

- We_Get - GeekPark 捕风捉影
除了我们熟知的QQ,互联网世界里以自身强大资源来复制小公司的产品和服务的事,绝不少见. 去年8月份,Facebook推出了Facebook Places,这是一个类似Foursquare的基于地理位置的手机在线签到功能. Foursquare当时是社交网站新贵,几个月以后它成了代表着全球互联网方向中的SoLoMo中的Lo—Location.

Facebook的标语

- - 阮一峰的网络日志
Facebook即将 上市,一时之间成为全球新闻热点. 为了不错过商机,有人将Facebook内部的标语做成 海报,每张20美元,放到网上卖. 据说,从扎克伯格创业初期,这些标语就贴在Facebook的办公室,作为行动准则,激励员工. 虽然这些标语很简单,但是我发现,它们真的具有警醒的效果,能指导你做出正确的事.

读facebook效应

- - 搜索引擎技术博客
     我的一位室友说:“嘿,我来帮你”. 我回答他:“兄弟,你不会编程”,然后他周末回家买了一个perl编程入门的书,告诉我‘我现在准备好了’. 我就说;“兄弟,网站不是用perl语言编写的”.      我们并不想让用户在网站停留尽可能长的时间,我们所做的是让人们可以在网站用户好的体验,使他们在上面所花的时间有价值.

Facebook 开源 Detectron

- - 最新更新 – Solidot
Facebook 在 Apache 2.0 许可证下 开源了它的目标识别平台 Detectron, 源代码托管在 GitHub 上. Detectron 用 Python 开发,基于 Caffe2 深度学习框架. Facebook 同时公开了超过 70 个预先训练的模型. Detectron 项目始于 2016 年,实现了一系列最新的目标识别算法如 Mask R-CNN,该软件平台在社交巨人的视觉感知系统的进步上扮演了重要角色.