🚀 免費嘗試 Zilliz Cloud,完全托管的 Milvus,體驗速度提升 10 倍!立即嘗試

milvus-logo
LFAI

開始使用 HNSWlib

  • Engineering
November 25, 2024
Haziqa Sajid

語意搜尋可讓機器理解語言,並產生更好的搜尋結果,這在人工智能和資料分析中是不可或缺的。一旦將語言表示為嵌入式,就可以使用精確或近似的方法進行搜尋。近似最近鄰(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 如何運作

  1. 分層:HNSW 將資料組織為層次分明的圖層,每層包含由邊連接的節點。頂層較為稀疏,允許在圖表上廣泛「跳過」,就像放大地圖,只看到城市之間的主要高速公路一樣。較低的圖層密度會增加,提供更細緻的細節以及更多近鄰之間的連結。

  2. 可導航的小世界概念:HNSW 中的每一層都建立在「小世界」網路的概念上,其中節點(資料點)之間只有幾個「跳」的距離。搜尋演算法會從最高、最稀疏的層開始,然後向下移動,逐漸移到密度較高的層,以精細搜尋。這種方法就像是從全局觀往下移動到鄰近層的細節,逐漸縮小搜尋範圍。

圖 1:可導航的小世界圖表範例

  1. 類似跳列表的結構:HNSW 的層級結構類似於跳躍清單 (skip list),這是一種概率資料結構,其中較高層級的節點較少,可加快初始搜尋速度。

圖 2:Skip List 結構範例

要在給定的跳躍清單中搜尋 96,我們從最左邊的頂層開始,從頭節點開始。向右移動時,我們遇到 31,小於 96,因此我們繼續到下一個節點。現在,我們需要向下移動一層,再次看到 31;由於它仍然小於 96,所以我們再向下移動一層。再一次找到 31,然後我們向右移動,到達 96,也就是我們的目標值。因此,我們無需下到跳過清單的最低層就可以找到 96。

  1. 搜尋效率:HNSW 演算法從最高層的入口節點開始,每一步都會邁向較近的鄰居。它會逐層下降,利用每個層級進行粗粒度到細粒度的探索,直到達到可能找到最相似節點的最低層。這種分層導航減少了需要探索的節點和邊緣的數量,使得搜尋快速而精確。

  2. 插入和維護:新增節點時,演算法會根據概率決定其進入層,並使用鄰居選擇啟發式將其連接到鄰近的節點。啟發式的目的是優化連線性,建立可改善導航性的連結,同時平衡圖形密度。這種方法可以保持結構的穩健性,並適應新的資料點。

儘管我們對 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 支援多種資料類型 - 向量、標量和結構化資料 - 允許在單一系統中進行無縫管理和分析。

  • 活躍的社群 與支援:一個蓬勃發展的社群提供定期更新、教學與支援,確保 Milvus 緊貼使用者需求與領域進展。

  • AI 整合:Milvus 已整合各種流行的 AI 框架與技術,讓開發人員更容易使用他們熟悉的技術堆疊建立應用程式。

Milvus 也在Ziliz Cloud 上提供全面的管理服務,無後顧之憂,速度比 Milvus 快 10 倍。

比較:Milvus vs. HNSWlib

特點MilvusHNSWlib
擴充性輕鬆處理數以億計的向量由於使用 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 Started

Like the article? Spread the word

繼續閱讀