千萬量級圖片視訊快速檢索,輕鬆配置設計師的靈感挖掘神器

語言: CN / TW / HK

作者介紹:

James Zhang,飛書深諾集團的演算法工程師 ,畢業於芬蘭坦佩雷大學,感興趣的方向包括自然語言處理、計算機視覺等機器學習相關領域以及演算法工程化。

飛書深諾集團是專注海外數字營銷解決方案的綜合服務集團,為中國出海企業提供可定製組合的全鏈路服務產品,滿足遊戲、APP、電商、品牌等典型出海場景需求。

Milvus 在電商場景中的千萬量級素材搜尋實踐

專案背景

在服務電商客戶的場景下,創意部門常常要為客戶製作素材,如:廣告圖、宣傳視訊、宣傳文案等。創意部門往往通過以圖搜圖、以視訊搜視訊、文字搜文字的方式發掘素材,為設計師們提供創意上的參考。同時,熱度、效果值等其他條件也可以用來輔助搜尋,幫助創意部門充分選擇合適的素材。此專案的動機正是利用 Milvus 向量資料庫在內的一系列技術,為創意部門提供一個素材的綜合搜尋系統。

技術選型

由於業務介面需要實時返回,並承受一定程度的併發負載,因此我們認為 Milvus 是比較合適的向量檢索工具。它對 FAISS、ANN 等工具進行了封裝,建立自己的儲存檔案結構,同時提供了方便的服務化介面,可以算得上“開箱即用”了。在保持檢索速度快的同時,Milvus 可以通過引數設定,對向量檢索的準確性、資源佔用做一定的 Trade-off,比較適合在實際工程中使用。

我們在返回相似向量的同時,還需要圖片/視訊的一些對應資訊,我們通過 KV(Key-Value)的形式將這些資訊放在 Redis 快取裡,加快獲取的速度。在 Web 介面封裝方面,考慮到團隊內大部分為 Python 程式設計師,因此我們選用了 Nginx + Flask + Gunicorn + supervisor 的 Web 經典套餐。

使用到的各工具和框架

  • Milvus(圖片/視訊/文字的向量相似檢索)
  • Redis(業務快取)
  • Nginx(負載均衡)
  • Flask + Gunicorn (Web 框架 + 併發服務)
  • Supervisor(服務的程序啟動與異常自動重啟)
  • Docker(容器隔離部署)

專案實現

在我們的專案中,圖片使用 EfficientNet 來提取特徵向量;視訊通過提取關鍵幀之後,再將每一幀圖片進行向量提取之後疊加;文字採用 BERT 做特徵提取。

架構示意如下圖所示:

選擇合適的索引:

在得到圖片/視訊/文字向量檢索結果後,上層呼叫還要做一些業務操作,留給向量檢索的介面的時間就不能太多,系統需要做到 1s 內返回。由於向量檢索對速度的要求比較高,同時服務部署的機器記憶體又有一定的限制,我們選用了 IVF_PQ 作為向量索引。

IVF_PQ 是一種有失真壓縮的向量索引,它將所有向量分解成 m 段,每一小段分別進行聚類,每小段由所屬的聚類中心來表示,稱為索引值,用 Codebook (碼錶)來表示 。舉例說明這種壓縮方式:一個 D=128 維的原始向量被切分成了 M=8 個 D=16 維的短向量,同時每個 16 維短向量都對應一個量化的索引值,索引值即該短向量距離最近的聚類中心的編號,每一個原始向量就可以壓縮成 8 個索引值構成的壓縮向量,即每個向量都用這 8 個索引值來表示,相對於原始值有一定的誤差。

在實際使用的時候,IVF_PQ 這種索引方法預先計算好的各個聚類中心間的距離,通過查詢表得出兩個向量索引值的距離,來近似替代兩個向量的真實距離,這種方法加快了計算速度;在使用中可以通過引數 m 的設定,使得向量壓縮成很小的比例,也大量減少了記憶體佔用(約為向量原始空間大小的 5%~10%)。下圖為 IVF_PQ 索引壓縮示例:

根據 Milvus 官方提供的公式:

單個數據段計算量可估算為:目標向量數量 × (nlist+ (段內向量數 ÷nlist)× nprobe)

資料段的數量可估算為:集合資料總量 ÷ index_file_size

對集合查詢所需的計算總量則為:單個數據段計算量 × 資料段數量

我們計算得出合適的索引引數是 nlist=1024,m=8。

使用分割槽提高速度:

目前素材中,圖片總量接近 4kw,視訊總量大約 1kw,文字總量大約 3kw,為了提高檢索速度,分割槽變得十分必要。我們通過一些業務屬性,根據屬性值做笛卡爾積操作來建立分割槽:

例如,我們向量對應的 Item 有兩個屬性:

  • 對於屬性 A,取值 1,2,3,4

  • 對於屬性 B,取值 1,2,3

建立分割槽 A1_B1,A1_B2,A1_B3,A2_B1,A2_B2,A2_B3,...... ,A4_B3,一共 12 個。通過分割槽操作,我們將每個分割槽的向量規模控制在 500w 以下,進一步提高了檢索速度。

需要注意的是,用來建立分割槽的屬性應該是不會變動的基本屬性。因為如果發生變動,重新建立分割槽、匯入資料和建立索引將是非常漫長的過程,所以分割槽確定之後不要輕易改變。另外,分割槽及屬性值不能太多,否則各個屬性值相乘(笛卡兒積)會讓數量變得非常龐大,使程式變得過於複雜。如果要實現更多的素材屬性檢索或篩選,我們在 Milvus 向量搜尋的結果上另外封裝一層業務介面來實現。

系統效果

向量檢索服務以 REST 介面的形式對外提供,前端團隊呼叫介面,將結果展示在介面上。(請自行腦補一下谷歌的以圖搜圖,百度的以影搜影等等……)

效能指標 目前我們的圖片總量大約在 3kw+,視訊總量大約在 1kw,向量維數為 2048 維,文字總量為 3kw 左右,向量維數為 768 維。圖片檢索耗時 0.2s 左右;視訊檢索耗時 0.1s 左右;文字向量檢索耗時 <0.1s。

關於 Milvus 的一些經驗與總結 Milvus 整合各種常見向量索引,能滿足工程中大部分的需求,儲存操作和檢索速度都達到了工業級的水準,提供服務化的介面,基本上做到了開箱即用。不過 Milvus 目前還不支援其他型別(字元型、整型)的屬性檢索,官方表示新版本目前正在研發當中,期待早日上線。

總體來說,對於需要快速構建向量檢索服務、又不想花太大成本構造的輕量級專案來說,Milvus 是一個很好的選擇。

參考文獻

[1] Product quantization for nearest neighbor search. Hervé Jégou, Matthijs Douze, Cordelia Schmid

[2] https://Milvus.io/cn/docs/v1.1.1/tuning.md

Arch Meetup 深圳站開始報名啦,點選檢視活動議程!

GitHub @Milvus-io|CSDN @Zilliz Planet|Bilibili @Zilliz-Planet

Zilliz 以重新定義資料科學為願景,致力於打造一家全球領先的開源技術創新公司,並通過開源和雲原生解決方案為企業解鎖非結構化資料的隱藏價值。

Zilliz 構建了 Milvus 向量資料庫,以加快下一代資料平臺的發展。Milvus 資料庫是 LF AI & Data 基金會的畢業專案,能夠管理大量非結構化資料集,在新葯發現、推薦系統、聊天機器人等方面具有廣泛的應用。