寫在前面
高性能向量檢索庫(milvus & faiss)簡介
Milvus和Faiss都是高性能向量檢索庫,可以讓你在海量向量庫中快速檢索到和目標向量最相似的若干個向量,這里相似度量標准可以是內積或者歐式距離等。這里借用milvus官方的話再次說明這兩個庫的特點:
Milvus 是一款開源的、針對海量特征向量的相似性搜索引擎。基於異構眾核計算框架設計,成本更低,性能更好。 在有限的計算資源下,十億向量搜索僅毫秒響應。
說白了就是速度快,暫且不說十億向量,自己寫代碼去完成對100萬300維向量的余弦相似度計算並排序就需要不小的響應時間吧,就本人測試而言,即便使用scipy庫計算速度依然要比milvus和faiss慢很多。
本文主要內容
本文主要內容分為三塊:
- 兩個高性能搜索引擎的對比
- milvus安裝及其使用教程
- faiss安裝及其使用教程
milvus和faiss的對比
在milvus開源之前,也存在高性能向量相似性搜索引擎(庫),這個引擎就是Facebook的Faiss,功能都是一樣的,具體可以參考官網 。
就我個人而言,我是推薦使用milvus的,主要是在我個人看來,milvus有如下幾個好處:
- 多平台通用,mac,windows和linux都是支持的,因為milvus可以通過docker部署,因此平台通用性好了不少。
- 支持編程語言多,Java,c,c++和python都支持,要知道Faiss是不支持java的,這一點簡直讓人抓狂,github上好幾個項目就是關於把Faiss轉成java的,因為我Java和python都是要使用的,我把github上關於faiss轉java的項目都試了個遍,結論就是非常難安裝,只要Faiss版本更新了,必須要重來一遍,即便最后java可以用了,也不敢保證其穩定性。所以想在Java上用Faiss還是放棄吧。
- 在速度方面,就我自己測試而言,milvus不輸Faiss,但是我沒有使用GPU測試,有興趣的小伙伴可以試一下。
當然Faiss也並非一無是處,首先速度並不輸於Milvus,而且使用起來更方便,不需要使用docker,代碼寫起來更為簡潔(后面章節會有示例代碼,大家看了就知道faiss比較簡潔了),且有大廠做技術支持,如果部署環境就是python,Faiss也是一個很好的選擇。
milvus安裝及其使用教程
milvus 安裝步驟
milvus 一共有兩種安裝方式:自己編譯安裝和使用docker安裝。這里推薦大家使用docker安裝,docker安裝方便快捷,可在Windows上使用。自己編譯安裝,由於每個人環境不同,很容易出問題。本文只介紹基於docker的安裝,另外因為我比較窮,所以只介紹cpu版本的安裝,不過gpu安裝也是大同小異。
Step1 安裝docker
首先就是要安裝docker,還不了解docker可以了解一波,非常好用的虛擬機工具,強力推薦真是太香了,直接去Docker官網下載對應平台的安裝文件即可。
Step2 下載相應版本鏡像
安裝好docker后,要去pull對應的鏡像(image),首先進到dockerhub官網,然后搜索milvus,第一個結果就是。因為我們安裝的是CPU版本,所以在tags里找cpu-latest,然后pull下來就可以了,即在你的命令行窗口輸入
docker pull milvusdb/milvus:cpu-latest
。注意:隨着版本迭代更新,這一條命令在未來可能會失效,建議先去dockerhub搜索一下,去看一下應該用什么tag。
pull
好之后, 在docker images
看一下應該會有該鏡像,整個流程記錄如下圖:
Step3 設置配置文件和工作目錄
在創建啟動容器之前,我們要先設置配置文件。
在/home/$USER/milvus/conf 目錄下創建 server_config.yaml 文件,然后將 server config 文件 的內容復制到你創建的配置文件中。
一般情況下 server_config.yaml文件不需要再修改,如果有個人配置需求,可根據官網教程進行修改。
然后就需要配置工作目錄了,一共需要建立三個文件夾,在/home/$USER/milvus/目錄下建立db,logs和wal文件夾。
注意上述目錄均可根據自己需求進行修改,只是在啟動docker服務是一定要映射到對的目錄上!為了方便演示,我舉個自己的目錄例子,我的工作目錄是C:\Users\Zhdun\milvus
,我的目錄結構是:
milvus
│
├─conf //配置文件目錄
│ server_config.yaml //配置文件 搜索引擎配置都在這里修改
│
├─db //數據庫存儲目錄 你的索引與向量存儲的位置
│
└─logs //日志存儲目錄
│
└─wal // 預寫式日志相關配置
Step4 啟動docker服務
設置好工作目錄后,就可以使用鏡像創建容器了,以我自己工作目錄為例,需要如下命令
docker run -td --name mymilvus -e "TZ=Asia/Shanghai" -p 19530:19530 -p 19121:19121 -v C:\Users\Zhdun\milvus\db:/var/lib/milvus/db -v C:\Users\Zhdun\milvus\conf:/var/lib/milvus/conf -v C:\Users\Zhdun\milvus\logs:/var/lib/milvus/logs -v C:\Users\Zhdun\milvus\wal:/var/lib/milvus/wal milvusdb/milvus:cpu-latest
命令看起來有點長, 我稍微解釋下,-td是后台運行,--name是給自己的容器起個名字,-p是端口映射,不想用默認的話,可以去服務器配置文件里改,-v就是為了映射三個工作目錄。具體可以參考docker的run命令。
執行完命令后,運行docker ps -a,如果發現自己創建的容器Exited的了,那就說明報錯了,那就docker logs <container id>
一下,看出了什么問題。如果發現容器在運行了,就代表基本沒問題了。
正常啟動記錄如下截圖:
接下來我會說一下常見的安裝問題。
安裝時的常見問題及解決
Config check fail: Invalid config version: . Expected config version: 0.1 遇到這種問題就在服務器的配置文件第一行加上version: 0.1
。
Config check fail: Invalid cpu cache capacity: 1. Possible reason: sum of cache_config.cpu_cache_capacity and db_config.insert_buffer_size exceeds system memory.
這種問題就說明內存超出了限制,首先檢查服務器配置里的 cpu_cache_capacity 和 insert_buffer_size 是不是過大了。
然后再檢查給定docker設定的內存是多少,可以通過docker info來檢查。
milvus 基本使用
安裝完成后,終於可以開始使用milvus了,milvus支持python,java和c++。在這里我只介紹python的使用。
首先安裝 pymilvus庫:pip install pymilvus
,然后就可以使用這個庫來寫代碼了,接下來我會直接把自己寫的范例代碼貼上去,其中每一步的具體含義以及可能的擴展我會直接在注釋里告訴大家,如有錯誤還請各位指出。
# -*- coding: utf-8 -*-
# 導入相應的包
import numpy as np
from milvus import Milvus, MetricType
# 初始化一個Milvus類,以后所有的操作都是通過milvus來的
milvus = Milvus(host='localhost', port='19530')
# 向量個數
num_vec = 5000
# 向量維度
vec_dim = 768
# name
collection_name = "test_collection"
# 創建collection,可理解為mongo的collection
collection_param = {
'collection_name': collection_name,
'dimension': vec_dim,
'index_file_size': 32,
'metric_type': MetricType.IP # 使用內積作為度量值
}
milvus.create_collection(collection_param)
# 隨機生成一批向量數據
# 支持ndarray,也支持list
vectors_array = np.random.rand(num_vec, vec_dim)
# 把向量添加到剛才建立的collection中
status, ids = milvus.insert(collection_name=collection_name, records=vectors_array) # 返回 狀態和這一組向量的ID
milvus.flush([collection_name])
# 輸出統計信息
print(milvus.get_collection_stats(collection_name))
# 創建查詢向量
query_vec_array = np.random.rand(1, vec_dim)
# 進行查詢,
status, results = milvus.search(collection_name=collection_name, query_records=query_vec_array, top_k=5)
print(status)
print(results)
# 如果不用可以刪掉
status = milvus.drop_collection(collection_name)
# 斷開、關閉連接
milvus.close()
這里也推薦下官方示例代碼,寫的很好,更加權威,可借鑒學習。
faiss安裝及其使用教程
faiss的安裝
faiss有三種安裝方式:
1 源碼編譯安裝
根據官方教程來。做好踩坑的准備,這個能寫好多,我就不寫了,遇到問題私聊我吧
2 conda 安裝
最為簡單,但是需要conda。
# CPU version only
conda install faiss-cpu -c pytorch
# GPU version
conda install faiss-gpu cudatoolkit=8.0 -c pytorch # For CUDA8
conda install faiss-gpu cudatoolkit=9.0 -c pytorch # For CUDA9
conda install faiss-gpu cudatoolkit=10.0 -c pytorch # For CUDA10
3 第三方預編譯庫
有熱心網友自己預編譯了,可以直接pip install,私人編譯,非官方,穩定性和成功率不保證,我自己用過沒啥問題,詳見https://pypi.org/project/faiss/
最后的最后,血和淚的教訓,環境一定要安裝openblas,注意不是blas,是openblas,那不然多核利用率會變得極差
faiss的使用
就像使用milvus一樣,同樣提供一份范例代碼加以詳細的注釋,如有錯誤還請指正!
# 導入庫
import numpy as np
import faiss
# 向量個數
num_vec = 5000
# 向量維度
vec_dim = 768
# 搜索topk
topk = 10
# 隨機生成一批向量數據
vectors = np.random.rand(num_vec, vec_dim)
# 創建索引
faiss_index = faiss.IndexFlatL2(vec_dim) # 使用歐式距離作為度量
# 添加數據
faiss_index.add(vectors)
# 查詢向量 假設有5個
query_vectors = np.random.rand(5, vec_dim)
# 搜索結果
# 分別是 每條記錄對應topk的距離和索引
# ndarray類型 。shape:len(query_vectors)*topk
res_distance, res_index = faiss_index.search(query_vectors, topk)
print(res_index)
print(res_distance)
代碼是為了拋磚引玉,大概介紹使用流程,高階用法可以去看官網wiki。
最后感謝各位閱讀, 希望能幫到你們.
文章可以轉載, 但請注明出處: