開始使用 HNSWlib
語意搜尋可讓機器理解語言,並產生更好的搜尋結果,這在人工智能和資料分析中是不可或缺的。一旦將語言表示為嵌入式,就可以使用精確或近似的方法進行搜尋。近似最近鄰(ANN) 搜尋是一種用來快速找出資料集中最接近給定查詢點的方法,這與精確最近鄰搜尋不同,精確最近鄰搜尋對於高維資料的計算成本可能很高。近鄰搜索 (ANN) 可提供近似接近最近鄰的結果,從而加快檢索速度。
近似最近鄰 (ANN) 搜尋的演算法之一是HNSW(Hierarchical Navigable Small Worlds),在HNSWlib 下實作,這將是今天討論的重點。在這篇部落格中,我們將會
瞭解 HNSW 演算法。
探索 HNSWlib 及其主要功能。
設定 HNSWlib,涵蓋索引建立與搜尋執行。
與 Milvus 作比較。
瞭解 HNSW
Hierarchical Navigable Small Worlds(HNSW)是一種基於圖的資料結構,可透過建立「小世界」網路的多層圖,進行有效率的相似性搜尋,尤其是在高維空間。HNSW 於2016 年推出,可解決與傳統搜尋方法(如暴力搜尋和樹狀搜尋)相關的可擴展性問題。它非常適合涉及大型資料集的應用,例如推薦系統、圖像識別和檢索增量生成 (RAG)。
HNSW 的重要性
HNSW 可顯著增強高維空間中近鄰搜尋的效能。結合了層次結構與小世界導航能力,避免了舊式方法的計算效率低的問題,使其在處理大量複雜的資料集時也能有良好的表現。為了更了解這一點,我們現在就來看看它是如何運作的。
HNSW 如何運作
分層:HNSW 將資料組織為層次分明的圖層,每層包含由邊連接的節點。頂層較為稀疏,允許在圖表上廣泛「跳過」,就像放大地圖,只看到城市之間的主要高速公路一樣。較低的圖層密度會增加,提供更細緻的細節以及更多近鄰之間的連結。
可導航的小世界概念:HNSW 中的每一層都建立在「小世界」網路的概念上,其中節點(資料點)之間只有幾個「跳」的距離。搜尋演算法會從最高、最稀疏的層開始,然後向下移動,逐漸移到密度較高的層,以精細搜尋。這種方法就像是從全局觀往下移動到鄰近層的細節,逐漸縮小搜尋範圍。
圖 1:可導航的小世界圖表範例
- 類似跳列表的結構:HNSW 的層級結構類似於跳躍清單 (skip list),這是一種概率資料結構,其中較高層級的節點較少,可加快初始搜尋速度。
圖 2:Skip List 結構範例
要在給定的跳躍清單中搜尋 96,我們從最左邊的頂層開始,從頭節點開始。向右移動時,我們遇到 31,小於 96,因此我們繼續到下一個節點。現在,我們需要向下移動一層,再次看到 31;由於它仍然小於 96,所以我們再向下移動一層。再一次找到 31,然後我們向右移動,到達 96,也就是我們的目標值。因此,我們無需下到跳過清單的最低層就可以找到 96。
搜尋效率:HNSW 演算法從最高層的入口節點開始,每一步都會邁向較近的鄰居。它會逐層下降,利用每個層級進行粗粒度到細粒度的探索,直到達到可能找到最相似節點的最低層。這種分層導航減少了需要探索的節點和邊緣的數量,使得搜尋快速而精確。
插入和維護:新增節點時,演算法會根據概率決定其進入層,並使用鄰居選擇啟發式將其連接到鄰近的節點。啟發式的目的是優化連線性,建立可改善導航性的連結,同時平衡圖形密度。這種方法可以保持結構的穩健性,並適應新的資料點。
儘管我們對 HNSW 演算法有了基本的了解,但從頭開始實作可能會讓我們手足無措。幸運的是,社群已經開發了像HNSWlib這樣的函式庫來簡化使用方式,讓您無須撓頭也能使用。因此,讓我們仔細看看 HNSWlib。
HNSWlib 概觀
HNSWlib 是實作 HNSW 的流行函式庫,具有高效率和可擴充的特性,即使在數百萬點的情況下也能表現良好。它允許圖層間的快速跳躍,並針對密集的高維資料進行最佳化搜尋,因而達到次線性的時間複雜度。以下是 HNSWlib 的主要功能:
圖形結構:多層圖表代表資料點,允許快速的近鄰搜尋。
高維效率:針對高維資料進行最佳化,提供快速且精確的近似搜尋。
次線性搜尋時間:透過跳層達到次線性複雜性,大幅提升速度。
動態更新:支援即時插入和刪除節點,無需重建完整圖形。
記憶體效率:記憶體使用效率高,適用於大型資料集。
可擴充性:可順利擴充至數百萬個資料點,非常適合推薦系統等中等規模的應用程式。
注意:HNSWlib 非常適合建立向量搜尋應用程式的簡單原型。然而,由於擴充性的限制,可能會有更好的選擇,例如針對涉及數億甚至數十億資料點、更複雜的情境使用專門建立的向量資料庫。讓我們來看看實作。
開始使用 HNSWlib:逐步指南
本節將透過建立 HNSW 索引、插入資料和執行搜尋,示範如何使用 HNSWlib 作為向量搜尋資料庫。讓我們從安裝開始:
安裝與匯入
要開始使用 Python 中的 HNSWlib,首先使用 pip 安裝:
pip install hnswlib
然後,匯入必要的函式庫:
import hnswlib
import numpy as np
準備資料
在這個範例中,我們會使用NumPy
來產生一個隨機資料集,其中有 10,000 個元素,每個元素的維度大小為 256。
dim = 256 # Dimensionality of your vectors
num_elements = 10000 # Number of elements to insert
讓我們建立資料:
data = np.random.rand(num_elements, dim).astype(np.float32) # Example data
現在資料已準備就緒,讓我們建立索引。
建立索引
在建立索引時,我們需要定義向量的維度和空間類型。讓我們建立索引:
p = hnswlib.Index(space='l2', dim=dim)
space='l2'
:此參數定義類似性所使用的距離指標。將它設定為'l2'
表示使用歐氏距離 (L2 norm)。如果將它設定為'ip'
,則會使用內乘積,這對余弦相似性等任務很有幫助。
dim=dim
:此參數指定您要處理的資料點的維度。它必須與您計畫加入索引的資料維度相符。
以下是如何初始化索引:
p.init_index(max_elements=num_elements, ef_construction=200, M=16)
max_elements=num_elements
:Num_elements
是最大容量,所以我們設定為 10,000,因為我們要處理 10,000 個資料點。
ef_construction=200
:此參數可控制索引建立時準確性與建立速度的取捨。較高的值可提高召回率 (精確度),但會增加記憶體使用量和建立時間。常見值範圍從 100 到 200。
M=16
:此參數決定為每個資料點建立的雙向連結數,影響精確度和搜尋速度。典型值介於 12 到 48 之間;16 通常是精確度和速度的良好平衡。
p.set_ef(50) # This parameter controls the speed/accuracy trade-off
ef
:ef
參數是「探索因數」的縮寫,決定搜尋時要檢查多少個鄰居。ef
值越高,搜尋的鄰居數就越多,這通常會增加搜尋的精確度 (回復率),但也會使搜尋速度變慢。相反,較低的ef
值可以加快搜尋速度,但可能會降低精確度。
在這種情況下,將ef
設為 50 表示搜尋演算法在尋找最相似的資料點時,最多會評估 50 個鄰居。
注意:ef_construction
會在建立索引時設定鄰居搜尋工作,以提高精確度,但會減慢建立速度。ef
會在查詢時控制搜尋工作,動態平衡每個查詢的速度和召回率。
執行搜尋
要使用 HNSWlib 執行近鄰搜尋,我們首先要建立隨機查詢向量。在這個範例中,向量的維度與索引資料相符。
query_vector = np.random.rand(dim).astype(np.float32) # Example query
labels, distances = p.knn_query(query_vector, k=5) # k is the number of nearest neighbors
query_vector
:這一行會產生一個與索引資料相同維度的隨機向量,以確保最近鄰搜尋的相容性。knn_query
:該方法會在索引p
中搜尋k
query_vector
的最近鄰。它會返回兩個陣列:labels
, 包含最近鄰居的索引,以及distances
, 表示查詢向量到每個鄰居的距離。在這裡,k=5
指定我們要找出五個最近的鄰居。
以下是列印標籤和距離之後的結果:
print("Nearest neighbors' labels:", labels)
print("Distances:", distances)
> Nearest neighbors' labels: [[4498 1751 5647 4483 2471]]
> Distances: [[33.718 35.484592 35.627766 35.828312 35.91495 ]]
這就是使用 HNSWlib 的簡單指南。
如前所述,HNSWlib 是一個很棒的向量搜尋引擎,可用來建立原型或實驗中等大小的資料集。如果您有更高的擴充性需求或需要其他企業級的功能,您可能需要選擇專門打造的向量資料庫,例如開放原始碼的Milvus或其在Zilliz Cloud 上的完整管理服務。因此,在下一節中,我們將比較 HNSWlib 與 Milvus。
HNSWlib 與 Milvus 等特定用途向量資料庫的比較
向量資料庫以數學表示的方式儲存資料,讓機器學習模型能夠透過相似度指標來識別資料,以瞭解上下文,從而為搜尋、推薦和文字生成提供動力。
向量索引函式庫 (例如 HNSWlib) 可改善向量搜尋與檢索,但缺乏完整資料庫的管理功能。另一方面,向量資料庫 (如Milvus) 是專為處理向量嵌入而設計的規模化資料庫,在資料管理、索引和查詢功能方面具有獨立資料庫通常缺乏的優勢。以下是使用 Milvus 的其他優點:
高速向量相似性搜尋:Milvus 在十億級向量資料集上提供毫秒級的搜尋效能,非常適合影像擷取、推薦系統、自然語言處理(NLP) 和擷取擴增生成(RAG) 等應用。
可擴充性及高可用性:Milvus 專為處理大量資料而打造,可水平擴充,並包含複製與故障移轉機制,以提供可靠性。
分散式架構:Milvus 使用分散式、可擴充的架構,將儲存與運算分開在多個節點上,以提供彈性與穩健性。
靈活的資料支援:Milvus 支援多種資料類型 - 向量、標量和結構化資料 - 允許在單一系統中進行無縫管理和分析。
活躍的社群 與支援:一個蓬勃發展的社群提供定期更新、教學與支援,確保 Milvus 緊貼使用者需求與領域進展。
AI 整合:Milvus 已整合各種流行的 AI 框架與技術,讓開發人員更容易使用他們熟悉的技術堆疊建立應用程式。
Milvus 也在Ziliz Cloud 上提供全面的管理服務,無後顧之憂,速度比 Milvus 快 10 倍。
比較:Milvus vs. HNSWlib
特點 | Milvus | HNSWlib |
---|---|---|
擴充性 | 輕鬆處理數以億計的向量 | 由於使用 RAM,適合較小的資料集 |
適用於 | 原型、實驗和企業級應用程式 | 專注於原型與輕量級 ANN 任務 |
索引 | 支援 10 種以上的索引演算法,包括 HNSW、DiskANN、Quantization 及 Binary。 | 僅使用基於圖形的 HNSW |
整合性 | 提供 API 與雲端原生服務 | 提供輕量、獨立的函式庫 |
效能 | 針對大型資料、分散式查詢進行最佳化 | 提供高速但有限的擴充性 |
總體來說,Milvus 適合需要複雜索引的大型生產級應用程式,而 HNSWlib 則適合原型設計和較直接的使用個案。
結論
語意搜尋可能是資源密集型的,因此內部資料結構化(例如 HNSW 所執行的結構化)對於更快速的資料擷取是非常重要的。HNSWlib 之類的函式庫關心實作,因此開發人員已準備好食譜,可以進行向量功能的原型開發。只要幾行程式碼,我們就能建立自己的索引並執行搜尋。
HNSWlib 是一個很好的開始方式。不過,如果您想要建立複雜且可投入生產的 AI 應用程式,專門打造的向量資料庫是最佳選擇。舉例來說,Milvus是一個開放原始碼向量資料庫,具有許多企業就緒的功能,例如高速向量搜尋、可擴充性、可用性,以及在資料類型和程式語言方面的彈性。
進一步閱讀
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word