我們?nèi)粘J褂玫母鞣N APP 中的許多功能,都離不開相似度檢索技術(shù)。比如一個接一個的新聞和視頻推薦、各種常見的對話機(jī)器人、保護(hù)我們?nèi)粘Y~號安全的風(fēng)控系統(tǒng)、能夠用哼唱來找到歌曲的聽歌識曲,甚至就連外賣配送的最佳路線選擇也都有著它的身影。
相信很多同學(xué)是第一次聽說它,或者只知道它的大名,而不知該如何使用它。本篇文章,我們就來聊聊 faiss,分享這個“黑科技”是如何發(fā)揮神奇的“魔法”的。
寫在前面
faiss 是相似度檢索方案中的佼佼者,是來自 Meta AI(原 Facebook Research)的開源項目[1],也是目前最流行的、效率比較高的相似度檢索方案之一。雖然它和相似度檢索這門技術(shù)頗受歡迎,在出現(xiàn)在了各種我們所熟知的“大廠”應(yīng)用的功能中,但畢竟屬于小眾場景,有著不低的掌握門檻和復(fù)雜性。
所以,不要想著一口氣就完全掌握它,咱們一步一步來。
當(dāng)然,如果你實在懶得了解,希望能夠和寫簡單的 Web 項目一樣,寫幾行 CRUD 就能夠完成高效的向量檢索功能,可以試試啟動一個 Milvus 實例[2]。或者更懶一些的話,可以試著使用 Milvus 的 Cloud 服務(wù)[3],來完成高性能的向量檢索。
了解 Faiss 的工作機(jī)制和適用場景
在正式使用 faiss 之前,我們需要先了解它的工作機(jī)制。
當(dāng)我們把通過模型或者 AI 應(yīng)用處理好的數(shù)據(jù)喂給它之后(“一堆特征向量”),它會根據(jù)一些固定的套路,例如像傳統(tǒng)數(shù)據(jù)庫進(jìn)行查詢優(yōu)化加速那樣,為這些數(shù)據(jù)建立索引。避免我們進(jìn)行數(shù)據(jù)查詢的時候,需要笨拙的在海量數(shù)據(jù)中進(jìn)行一一比對,這就是它能夠?qū)崿F(xiàn)“高性能向量檢索”的秘密。
我們熟知的互聯(lián)網(wǎng)企業(yè)中比較賺錢的“搜廣推”(搜索、廣告、推薦)業(yè)務(wù)中,會使用它解決這些場景下的向量召回工作。在這些場景下,系統(tǒng)需要根據(jù)多個維度進(jìn)行數(shù)據(jù)關(guān)聯(lián)計算,因為實際業(yè)務(wù)場景中數(shù)據(jù)量非常大,很容易形成類似“笛卡爾積”這種變態(tài)的結(jié)果,即使減少維度數(shù)量,進(jìn)行循環(huán)遍歷,來獲取某幾個向量的相似度計算,在海量數(shù)據(jù)的場景下也是不現(xiàn)實的。
而 Faiss 就是解決這類海量數(shù)據(jù)場景下,想要快速得到和查詢內(nèi)容相似結(jié)果(Top K 個相似結(jié)果),為數(shù)不多的靠譜方案之一。
和我們在常見數(shù)據(jù)庫里指定字段類型一樣, Faiss 也能夠指定數(shù)據(jù)類型,比如 IndexFlatL2、IndexHNSW、IndexIVF等二十來種類型,雖然類型名稱看起來比較怪,和傳統(tǒng)的字符串、數(shù)字、日期等數(shù)據(jù)看起來不大一樣,但這些場景將能夠幫助我們在不同的數(shù)據(jù)規(guī)模、業(yè)務(wù)場景下,帶來出乎意料的高性能數(shù)據(jù)檢索能力。反過來說,在不同的業(yè)務(wù)場景、不同數(shù)據(jù)量級、不同索引類型和參數(shù)大小的情況下,我們的應(yīng)用性能指標(biāo)也會存在非常大的差異,如何選擇合適的索引,也是一門學(xué)問。(下文會提到)
除了支持豐富的索引類型之外,faiss 還能夠運行在 CPU 和 GPU 兩種環(huán)境中,同時可以使用 C++ 或者 Python 進(jìn)行調(diào)用,也有開發(fā)者做了 Go-Faiss ,來滿足 Golang 場景下的 faiss 使用。
對 Faiss 有了初步認(rèn)識之后,我們來進(jìn)行 Faiss 使用的前置準(zhǔn)備。
環(huán)境準(zhǔn)備
為了盡可能減少不必要的問題,本篇文章中,我們使用 Linux 操作系統(tǒng)作為 faiss 的基礎(chǔ)環(huán)境,同時使用 Python 作為和 faiss 交互的方式。
在之前的文章中,我介紹過如何準(zhǔn)備 Linux 環(huán)境 和 Python 環(huán)境,如果你是 Linux 系統(tǒng)新手,可以閱讀這篇文章,從零到一完成系統(tǒng)環(huán)境的準(zhǔn)備:《在筆記本上搭建高性價比的 Linux 學(xué)習(xí)環(huán)境:基礎(chǔ)篇》[4];如果你不熟悉 Python 的環(huán)境配置,建議閱讀這篇文章《用讓新海誠本人驚訝的 AI 模型制作屬于你的動漫視頻》[5],參考“準(zhǔn)備工作”部分,完成 “Conda” 的安裝配置。
在一切準(zhǔn)備就緒之后,我們可以根據(jù)自己的設(shè)備狀況,選擇使用 CPU 版本的 faiss 還是 GPU 版本的 faiss,以及選擇是否要指定搭配固定 CUDA 版本使用:
#?創(chuàng)建一個干凈的環(huán)境
conda?create?-n?faiss?-y
#?激活這個環(huán)境
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,避免不必要的兼容性問題。在準(zhǔn)備好環(huán)境之后,我們就能夠正式進(jìn)入神奇的向量數(shù)據(jù)世界啦。
構(gòu)建向量數(shù)據(jù)
前文提到了,適合 faiss 施展拳腳的地方是向量數(shù)據(jù)的世界,所以,需要先進(jìn)行向量數(shù)據(jù)的構(gòu)建準(zhǔn)備。
本文作為入門篇,就先不聊如何對聲音(音頻)、電影(視頻)、指紋和人臉(圖片)等數(shù)據(jù)進(jìn)行向量數(shù)據(jù)構(gòu)建啦。我們從最簡單的文本數(shù)據(jù)上手,實現(xiàn)一個“基于向量檢索技術(shù)的文本搜索功能”。接下來,我將以我比較喜歡的小說 “哈利波特”為例,你可以根據(jù)自己的喜好調(diào)整要使用的文本數(shù)據(jù)。從網(wǎng)絡(luò)上下載好要處理為向量的文本數(shù)據(jù)(txt 文檔)。
簡單針對數(shù)據(jù)進(jìn)行 ETL
我這里的原始 TXT 文檔尺寸是 3 MB 大小,為了減少不必要的向量轉(zhuǎn)化計算量,我們先對內(nèi)容進(jìn)行必要的預(yù)處理(數(shù)據(jù)的 ETL 過程),去掉不必要的重復(fù)內(nèi)容,空行等:
cat?/Users/soulteary/《哈利波特》.txt?|?tr?-d?'?'?|?sed?'/^[[:space:]]*$/d'?>?data.txt
打開文本仔細(xì)觀察,數(shù)據(jù)中有一些行中的文本數(shù)據(jù)格外長,是由好多個句子組成的,會對我們的向量特征計算、以及精準(zhǔn)定位檢索結(jié)果造成影響的。所以,我們還需要進(jìn)行進(jìn)一步的內(nèi)容調(diào)整,將多個長句拆成每行一個的短句子。
為了更好的解決句子換行的問題,以及避免將一段人物對話中的多個句子拆散到多行,我們可以使用一段簡單的 Node.js 腳本來處理數(shù)據(jù):
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);
我們執(zhí)行 node .
將文本處理完畢之后,當(dāng)前文件夾中將出現(xiàn)一個名為 ready.txt
的文本文件。
為了方便后文中,我們更具象的了解向量數(shù)據(jù)庫的資源占用,我們順手查看下整理好的文本文件占磁盤空間是多少:
du?-hs?ready.txt?
5.5M????????ready.txt
使用模型將文本轉(zhuǎn)換為向量
為了將文本轉(zhuǎn)換為向量數(shù)據(jù),我們需要使用能夠處理文本嵌入的模型。我這里選擇的模型是來自人大、騰訊 AI Lab、北大(按論文作者順序)聯(lián)合推出的《UER: An Open-Source Toolkit for Pre-training Models》預(yù)訓(xùn)練模型。
關(guān)于這個預(yù)訓(xùn)練模型的相關(guān)資料:
-
HuggingFace uer/sbert-base-chinese-nli · Hugging Face
-
訓(xùn)練數(shù)據(jù) GitHub - liuhuanyong/ChineseTextualInference: ChineseTextualInference project including chinese corpus build and inferecence model, 中文文本推斷項目,包括88萬文本蘊(yùn)含中文文本蘊(yùn)含數(shù)據(jù)集的翻譯與構(gòu)建,基于深度學(xué)習(xí)的文本蘊(yùn)含判定模型構(gòu)建.
想要使用模型,我們需要先安裝一些 Python 的基礎(chǔ)軟件包:
pip?install?sentence_transformers?pandas
在依賴安裝完畢之后,我們可以在終端中輸入 python
來進(jìn)入 Python 交互式終端,首先將我們準(zhǔn)備好的文本文件使用 pandas
解析為 DataFrames 。
import?pandas?as?pd
df?=?pd.read_csv("ready.txt",?sep="#",header=None,?names=["sentence"])
print(df)
在執(zhí)行之后,我們將看到類似下面的結(jié)果:
??????????????????????????????????????sentence
0??????????????????????????????????《哈利波特》J.K羅琳
1????????????????????????????????第一部?第一章?幸存的男孩
2??????????住在四號普里懷特街的杜斯利先生及夫人非常驕傲地宣稱自己是十分正常的人。
3??????但是他們最不希望見到的就是任何奇怪或神秘故事中的人物因為他們對此總是嗤之以鼻。
4??????????????????????杜斯利先生是一家叫作格朗寧斯的鉆機(jī)工廠的老板。
...????????????????????????????????????????...
60023?????????????????哈利看著她茫然地低下頭摸了摸額頭上閃電形的傷疤。
60024????????????????????????????????“我知道他會的?!?60025?????????????????????????十九年來哈利的傷疤再也沒有疼過。
60026???????????????????????????????????一切都很好。
60027????????????????????????????????????(全書完)
[60028?rows?x?1?columns]
接下來,我們對載入內(nèi)存的文本進(jìn)行向量計算,對每一行數(shù)據(jù)進(jìn)行“特征向量抽取”:
from?sentence_transformers?import?SentenceTransformer
model?=?SentenceTransformer('uer/sbert-base-chinese-nli')
sentences?=?df['sentence'].tolist()
sentence_embeddings?=?model.encode(sentences)
這個過程會比較久,消耗時間將會和你的電腦性能相關(guān),我這邊使用一臺 Zen2 的普通筆記本,大概需要運行接近半個小時,所以這個時間不妨站起來動一動,緩解一天的疲勞。
當(dāng)數(shù)據(jù)向量完畢之后,我們可以先執(zhí)行 sentence_embeddings.shape
,看看數(shù)據(jù)的狀況:
(60028,?768)
執(zhí)行完畢,我們將看到類似上面的結(jié)果,有六萬條文本被向量化為了 768 維的向量數(shù)據(jù)。
最后
我們已經(jīng)搞定了“向量數(shù)據(jù)”,下一篇內(nèi)容中,我們將一起了解如何使用 Faiss 來實現(xiàn)向量相似度檢索功能。
作者:蘇洋
如果你覺得我們分享的內(nèi)容還不錯,請不要吝嗇給我們一些鼓勵:點贊、喜歡或者分享給你的小伙伴!
活動信息、技術(shù)分享和招聘速遞請關(guān)注:你好??,數(shù)據(jù)探索者https://zilliz.gitee.io/welcome/
如果你對我們的項目感興趣請關(guān)注:
用于存儲向量并創(chuàng)建索引的數(shù)據(jù)庫 Milvus文章來源:http://www.zghlxwxcb.cn/news/detail-448281.html
用于構(gòu)建模型推理流水線的框架 Towhee文章來源地址http://www.zghlxwxcb.cn/news/detail-448281.html
到了這里,關(guān)于向量數(shù)據(jù)庫入坑指南:初識 Faiss,如何將數(shù)據(jù)轉(zhuǎn)換為向量(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!