我们日常使用的各种 APP 中的许多功能,都离不开相似度检索技术。比如一个接一个的新闻和视频推荐、各种常见的对话机器人、保护我们日常账号安全的风控系统、能够用哼唱来找到歌曲的听歌识曲,甚至就连外卖配送的最佳路线选择也都有着它的身影。

相信很多同学是第一次听说它,或者只知道它的大名,而不知该如何使用它。本篇文章,我们就来聊聊 faiss,分享这个“黑科技”是如何发挥神奇的“魔法”的。

写在前面

faiss 是相似度检索方案中的佼佼者,是来自 Meta AI(原 Facebook Research)的开源项目[1],也是目前最流行的、效率比较高的相似度检索方案之一。虽然它和相似度检索这门技术颇受欢迎,在出现在了各种我们所熟知的“大厂”应用的功能中,但毕竟属于小众场景,有着不低的掌握门槛和复杂性。

所以,不要想着一口气就完全掌握它,咱们一步一步来。

当然,如果你实在懒得了解,希望能够和写简单的 Web 项目一样,写几行 CRUD 就能够完成高效的向量检索功能,可以试试启动一个 Milvus 实例[2]。或者更懒一些的话,可以试着使用 Milvus 的 Cloud 服务[3],来完成高性能的向量检索。

了解 Faiss 的工作机制和适用场景

在正式使用 faiss 之前,我们需要先了解它的工作机制。

当我们把通过模型或者 AI 应用处理好的数据喂给它之后(“一堆特征向量”),它会根据一些固定的套路,例如像传统数据库进行查询优化加速那样,为这些数据建立索引。避免我们进行数据查询的时候,需要笨拙的在海量数据中进行一一比对,这就是它能够实现“高性能向量检索”的秘密。

我们熟知的互联网企业中比较赚钱的“搜广推”(搜索、广告、推荐)业务中,会使用它解决这些场景下的向量召回工作。在这些场景下,系统需要根据多个维度进行数据关联计算,因为实际业务场景中数据量非常大,很容易形成类似“笛卡尔积”这种变态的结果,即使减少维度数量,进行循环遍历,来获取某几个向量的相似度计算,在海量数据的场景下也是不现实的。

而 Faiss 就是解决这类海量数据场景下,想要快速得到和查询内容相似结果(Top K 个相似结果),为数不多的靠谱方案之一。

和我们在常见数据库里指定字段类型一样, Faiss 也能够指定数据类型,比如 IndexFlatL2、IndexHNSW、IndexIVF等二十来种类型,虽然类型名称看起来比较怪,和传统的字符串、数字、日期等数据看起来不大一样,但这些场景将能够帮助我们在不同的数据规模、业务场景下,带来出乎意料的高性能数据检索能力。反过来说,在不同的业务场景、不同数据量级、不同索引类型和参数大小的情况下,我们的应用性能指标也会存在非常大的差异,如何选择合适的索引,也是一门学问。(下文会提到)

除了支持丰富的索引类型之外,faiss 还能够运行在 CPU 和 GPU 两种环境中,同时可以使用 C++ 或者 Python 进行调用,也有开发者做了 Go-Faiss ,来满足 Golang 场景下的 faiss 使用。

对 Faiss 有了初步认识之后,我们来进行 Faiss 使用的前置准备。

环境准备

为了尽可能减少不必要的问题,本篇文章中,我们使用 Linux 操作系统作为 faiss 的基础环境,同时使用 Python 作为和 faiss 交互的方式。

在之前的文章中,我介绍过如何准备 Linux 环境 和 Python 环境,如果你是 Linux 系统新手,可以阅读这篇文章,从零到一完成系统环境的准备:《在笔记本上搭建高性价比的 Linux 学习环境:基础篇》[4];如果你不熟悉 Python 的环境配置,建议阅读这篇文章《用让新海诚本人惊讶的 AI 模型制作属于你的动漫视频》[5],参考“准备工作”部分,完成 “Conda” 的安装配置。

在一切准备就绪之后,我们可以根据自己的设备状况,选择使用 CPU 版本的 faiss 还是 GPU 版本的 faiss,以及选择是否要指定搭配固定 CUDA 版本使用:

# 创建一个干净的环境
conda create -n faiss -y
# 激活这个环境
conda activate faiss
# 安装 CPU 版本
conda install -c pytorch python=3.8 faiss-cpu -y
# 或者,安装 GPU 版本
conda install -c pytorch python=3.8 faiss-gpu -y
# 或者,搭配指定 CUDA 版本使用
conda install -c pytorch python=3.8 faiss-gpu cudatoolkit=10.2 -y

在配置安装的时候,推荐使用 3.8 版本的 Python,避免不必要的兼容性问题。在准备好环境之后,我们就能够正式进入神奇的向量数据世界啦。

构建向量数据

前文提到了,适合 faiss 施展拳脚的地方是向量数据的世界,所以,需要先进行向量数据的构建准备。

本文作为入门篇,就先不聊如何对声音(音频)、电影(视频)、指纹和人脸(图片)等数据进行向量数据构建啦。我们从最简单的文本数据上手,实现一个“基于向量检索技术的文本搜索功能”。接下来,我将以我比较喜欢的小说 “哈利波特”为例,你可以根据自己的喜好调整要使用的文本数据。从网络上下载好要处理为向量的文本数据(txt 文档)。

简单针对数据进行 ETL

我这里的原始 TXT 文档尺寸是 3 MB 大小,为了减少不必要的向量转化计算量,我们先对内容进行必要的预处理(数据的 ETL 过程),去掉不必要的重复内容,空行等:

cat /Users/soulteary/《哈利波特》.txt | tr -d ' ' | sed '/^[[:space:]]*$/d' > data.txt

打开文本仔细观察,数据中有一些行中的文本数据格外长,是由好多个句子组成的,会对我们的向量特征计算、以及精准定位检索结果造成影响的。所以,我们还需要进行进一步的内容调整,将多个长句拆成每行一个的短句子。

为了更好的解决句子换行的问题,以及避免将一段人物对话中的多个句子拆散到多行,我们可以使用一段简单的 Node.js 脚本来处理数据:

const { readFileSync, writeFileSync } = require("fs");const raw = readFileSync("./hp.txt", "utf-8").split("\n").map((line) => line.replace(/。/g, "。\n").split("\n")).flat().join("\n").replace(/“([\S]+?)”/g, (match) => match.replace(/\n/g, "")).replace(/“([\S\r\n]+?)”/g, (match) => match.replace(/[\r\n]/g, "")).split("\n").map((line) => line.replace(/s/g, "").trim().replace(/s/g, "—")).filter((line) => line).join("\n");writeFileSync("./ready.txt", raw);

我们执行 node . 将文本处理完毕之后,当前文件夹中将出现一个名为 ready.txt 的文本文件。

为了方便后文中,我们更具象的了解向量数据库的资源占用,我们顺手查看下整理好的文本文件占磁盘空间是多少:

du -hs ready.txt
5.5M        ready.txt

使用模型将文本转换为向量

为了将文本转换为向量数据,我们需要使用能够处理文本嵌入的模型。我这里选择的模型是来自人大、腾讯 AI Lab、北大(按论文作者顺序)联合推出的《UER: An Open-Source Toolkit for Pre-training Models》预训练模型。

关于这个预训练模型的相关资料:

  • HuggingFace uer/sbert-base-chinese-nli · Hugging Face

  • 训练数据 GitHub - liuhuanyong/ChineseTextualInference: ChineseTextualInference project including chinese corpus build and inferecence model, 中文文本推断项目,包括88万文本蕴含中文文本蕴含数据集的翻译与构建,基于深度学习的文本蕴含判定模型构建.

想要使用模型,我们需要先安装一些 Python 的基础软件包:

pip install sentence_transformers pandas

在依赖安装完毕之后,我们可以在终端中输入 python 来进入 Python 交互式终端,首先将我们准备好的文本文件使用 pandas 解析为 DataFrames 。

import pandas as pd
df = pd.read_csv("ready.txt", sep="#",header=None, names=["sentence"])
print(df)

在执行之后,我们将看到类似下面的结果:

                                      sentence
0                                  《哈利波特》J.K罗琳
1                                第一部 第一章 幸存的男孩
2          住在四号普里怀特街的杜斯利先生及夫人非常骄傲地宣称自己是十分正常的人。
3      但是他们最不希望见到的就是任何奇怪或神秘故事中的人物因为他们对此总是嗤之以鼻。
4                      杜斯利先生是一家叫作格朗宁斯的钻机工厂的老板。
...                                        ...
60023                 哈利看着她茫然地低下头摸了摸额头上闪电形的伤疤。
60024                                “我知道他会的。”
60025                         十九年来哈利的伤疤再也没有疼过。
60026                                   一切都很好。
60027                                    (全书完)[60028 rows x 1 columns]

接下来,我们对载入内存的文本进行向量计算,对每一行数据进行“特征向量抽取”:

from sentence_transformers import SentenceTransformer
model = SentenceTransformer('uer/sbert-base-chinese-nli')
sentences = df['sentence'].tolist()
sentence_embeddings = model.encode(sentences)

这个过程会比较久,消耗时间将会和你的电脑性能相关,我这边使用一台 Zen2 的普通笔记本,大概需要运行接近半个小时,所以这个时间不妨站起来动一动,缓解一天的疲劳。

当数据向量完毕之后,我们可以先执行 sentence_embeddings.shape,看看数据的状况:

(60028, 768)

执行完毕,我们将看到类似上面的结果,有六万条文本被向量化为了 768 维的向量数据。

最后

我们已经搞定了“向量数据”,下一篇内容中,我们将一起了解如何使用 Faiss 来实现向量相似度检索功能。

作者:苏洋


如果你觉得我们分享的内容还不错,请不要吝啬给我们一些鼓励:点赞、喜欢或者分享给你的小伙伴!

活动信息、技术分享和招聘速递请关注:你好

向量数据库入坑指南:初识 Faiss,如何将数据转换为向量(一)相关推荐

  1. 向量数据库入坑指南:聊聊来自元宇宙大厂 Meta 的相似度检索技术 Faiss

    我们日常使用的各种 APP 中的许多功能,都离不开相似度检索技术.比如一个接一个的新闻和视频推荐.各种常见的对话机器人.保护我们日常账号安全的风控系统.能够用哼唱来找到歌曲的听歌识曲,甚至就连外卖配送 ...

  2. 向量数据库入坑:使用 Docker 和 Milvus 快速构建本地轻量图片搜索引擎

    本篇文章,我来分享如何使用 Docker 来搭建一个能够跑在本地的轻量图片搜索引擎,实现日常生活中我们习以为常,但是实现起来颇为麻烦的功能:以图搜图. 写在前面 之前网上看到一个问题<如何在自己 ...

  3. 向量数据库入坑:传统文本检索方式的降维打击,使用 Faiss 实现向量语义检索

    在上一篇文章<聊聊来自元宇宙大厂 Meta 的相似度检索技术 Faiss>中,我们有聊到如何快速入门向量检索技术,借助 Meta AI(Facebook Research)出品的 fais ...

  4. python web-python web入坑指南

    原标题:python web入坑指南 Invest regularly in your knowledge portfolio. Make learning a habit. 自学python web ...

  5. Rust 入坑指南:鳞次栉比 | CSDN 博文精选

    作者 | Jackyzhe 责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 很久没有挖Rust的坑啦,今天来挖一些排列整齐的坑.没错,就是要介绍一些集合类型的数据类型."鳞次栉 ...

  6. 开发工具篇第九讲:菜鸟入坑指南

    摘要:本文是开发工具篇第九讲:菜鸟入坑指南.针对新人上手慢的问题,写了这篇入坑指南,方便自己回顾,总结.本文分为四个部分,分别为jenkins使用技巧:常用软件操作命令:开发手册:调试手册.主要材料来 ...

  7. Phalcon在Windows上安装 《Phalcon入坑指南系列 一》

    Phalcon入坑指南 本系列目录 前言 一.安装 二.Phalcon 开发工具安装 三.环境变量配置 四.Phalcon 开发工具的使用 生成项目框架 生成控制器 / 模型 夸一下phalcon 五 ...

  8. Rust入坑指南:鳞次栉比

    很久没有挖Rust的坑啦,今天来挖一些排列整齐的坑.没错,就是要介绍一些集合类型的数据类型."鳞次栉比"这个标题是不是显得很有文化? 在Rust入坑指南:常规套路一文中我们已经介绍 ...

  9. rust的矿坑_Rust入坑指南:鳞次栉比

    很久没有挖Rust的坑啦,今天来挖一些排列整齐的坑.没错,就是要介绍一些集合类型的数据类型."鳞次栉比"这个标题是不是显得很有文化? 在Rust入坑指南:常规套路一文中我们已经介绍 ...

最新文章

  1. 三棱锥四面体html css,CSS transform属性实现旋转的四面体
  2. Awk 实例,第 1 部分
  3. Java在线问题诊断工具Greys
  4. 【深度学习的数学】交叉熵公式如何推导?
  5. 此计算机支持多个rdp侦听程序,远程桌面侦听器证书配置
  6. Android doc|Getting Started| Training部分 --翻译 Working with System Permissions
  7. CSS webkit
  8. 创建Dockerfile,构建jdk+tomcat环境
  9. JAVA代码 httpclient 模拟NTLM域登录 GET、POST两种连接方式
  10. android网页去广告插件下载,Adblock Plus(去广告插件)APP增强稳定版
  11. 计算机组成原理中EMAR是什么,计算机组成原理(罗克露)第3章cpu.ppt
  12. rar x64 5.50 linux,WinRAR 5.50简体中文注册版(已含Key文件和32位、64位)
  13. 小程序体验版白屏(已解决)
  14. Java用递归计算1加到100
  15. Tomcat 8.5 HTTP 报文只返回200 不返回 OK
  16. OpenCV画椭圆、实心圆、凹多边形、线段、矩形
  17. 可落地的DDD(5)-战术设计
  18. 阅读笔记--计算机网络 自顶向下方法
  19. P3975 [TJOI2015]弦论 (SAM)
  20. 惠头条全行业开户竞价推广投放怎么避免无效点击

热门文章

  1. 关于字体——Web Fonts
  2. ESP32设备驱动-LIS3DSH加速度传感器驱动
  3. Javscript数组的常用方法有哪些?
  4. 「收藏级干货」终于有人把趋势线说透了,浓缩万卷书精华!(图文并茂)
  5. SpringBoot -- request输入流重复可读
  6. 怎么修复局部曝过照片?分享三个方法给你
  7. CV2简单阈值函数:cv2.threshold()
  8. 浏览器 卸载java应用_Java卸载工具JavaUninstallTool下载使用
  9. IDEA 插件开发 - 动态设置表格的表头和数据,动态刷新
  10. 蓝桥杯——历届试题 纸牌三角形