基于內容的召回在推薦系統(tǒng)中是比較常見的召回策略,常見有基于用戶或物品的標簽召回或者基于用戶的年齡,地域等召回,一般該策略的實現(xiàn)是基于開源軟件 Elasticseach 實現(xiàn)的。雖然召回的結果都比較合理,但是召回的新穎度,驚喜度等都比較低。比如通過標簽“劉德華”進行召回,基本上召回的都是包含劉德華字眼的物品,不太可能召回出“黎明”,“張學友”等其他四大天王的物品。近年隨著萬物皆可 Embedding,特別是 word2vec,item2vec, graph2vec 等技術的成功應用,通過物品向量召回物品向量的方法也成為推薦系統(tǒng)中比較常用的召回策略。本文著重講述通過開源軟件 Vearch 來搭建一個向量搜索服務,并成功實現(xiàn)以圖搜圖的功能。
介紹
最近一直在做小視頻的推薦優(yōu)化,優(yōu)化的目標是人均入屏。按照之前資訊流的推薦經驗,希望根據(jù)用戶的播放記錄召回更多相關的小視頻來給用戶消費。小視頻的推薦場景和現(xiàn)在比較火爆的抖音有點類似,就是自動播放一小段視頻(5-30s左右),該小視頻基本占據(jù)了一整屏,用戶可以對這個小視頻進行點贊,分享,評論;如果不喜歡可以通過上滑來觀看下一個小視頻??紤]到決定用戶是否想看的因素不太可能是視頻下方兩行的視頻標題,更多的因素還在于視頻的封面圖能否引起用戶的興趣?;谶@樣的項目背景,所以才想搭建一個以圖搜圖的服務來進行小視頻的封面圖召回。
因為之前使用過 gRPC 封裝過 Faiss 來搭建向量召回服務,再加上之前做過圖片的分類項目,都是將圖片轉換為向量作為分類器的輸入,所以要做這個事基本要解決兩件事:
- 對圖片進行預處理,并將其轉換為固定長度的向量
- 將各個圖片的向量錄入 Faiss,并使用其完成向量搜索的任務
比如在博文Faiss 在項目中的使用中,作者就是使用 SIFT 算法進行圖片特征的提取,這些特征對應一個 128 維的向量。將每張圖片的特征向量輸入給 Faiss 進行相似向量的召回。比如在博文基于gRPC的Faiss server實踐中,MXPlayer的技術團隊對原先基于 Flask 框架開發(fā)的用戶/物品向量召回服務進行了 gRPC 的升級,單機壓測 QPS 比之前高了2倍以上。本來打算是魔改之前 基于 gRPC 的 Faiss 服務來滿足當期的業(yè)務場景需求的,但是偶然間發(fā)現(xiàn)京東開源的軟件 Vearch,就將之前的念頭掐滅了,并決定好好的學習這個開源軟件。
服務組成
以圖搜圖的服務由兩部分組成,一個是向量搜索服務,由 Vearch 提供;一個是將圖片的特征提取成特征向量,由 Vearch 的插件 python-algorithm-plugin 提供。
向量搜索服務-Vearch
Vearch 是對大規(guī)模深度學習向量進行高性能相似搜索的彈性分布式系統(tǒng)。它的核心是向量搜索,是基于 Faiss 實現(xiàn)的叫 Gamma 引擎。不過除了向量搜索外, Gamma 還可以存儲包含標量的文檔,并對這些標量字段進行快速索引和過濾。說白了,標量和矢量都支持,而一般的像 Elasticsearch只支持標量。Faiss 只能構建單機的向量搜索服務,而Vearch 以 Gamma 為向量搜索引擎,使用 Raft 協(xié)議實現(xiàn)多副本存儲,提供 Master 和 Router組件來構建向量相似搜索的彈性分布式系統(tǒng)。其架構圖如下:
圖中主要有三大組件: Master, Router,PartitionServer,其功能如下:
- Master 負責 schema 管理,進行集群級別的源數(shù)據(jù)和資源協(xié)調
- Router 提供增刪改查的 RESTful API,對請求進行路由轉發(fā)和結果合并
- PartitionServer 主要是基于raft協(xié)議實現(xiàn)多副本存儲,而具體的存儲,索引和檢索能力是由 Gamma 引擎提供。 從上面可以知道 Gamma 之于 Vearch,就相當于 Lucene 之于 Elasticsearch。
圖片處理服務-Vearch插件
圖像處理的服務 Vearch 也提供了對應的插件python-algorithm-plugin。Vearch 的目標是構建一個高性能相似搜索的彈性分布式系統(tǒng)。文本,圖片和視頻都可以轉換成向量,所以 Vearch 團隊提供了對應的插件來更好的集成到 Vearch 中。對于圖片,該插件提供了目標檢測,特征提取和相似搜索等功能。其處理邏輯如下:
其邏輯就是從圖片中抽取向量特征存儲進 Vearch 的 Gamma 引擎中,并提供檢索服務。
服務搭建
以圖搜圖的服務由兩個服務構成,一個是向量搜索服務,由 Vearch 提供;另一個是圖片特征提取為向量,由 Vearch 的插件python-algorithm-plugin提供。
vearch
Vearch 是用 Go 編寫的,而其核心引擎 Gamma 是用 C 編寫的(畢竟Faiss 也是 C 開發(fā)的),所以服務安裝部署比較簡單粗暴,只要設置好依賴的 lib 包(Faiss,Gamma,RocksDB),并有編譯好的二進制文件 vearch,對于單機模式直接使用 ./vearch -conf config.toml 進行服務的啟動,而對于集群服務,通過最后的命令參數(shù) ./vearch -conf config.toml ps/router/master 進行配置。
不過因為我們線上服務器 Gcc 的版本太低,沒有 Go 環(huán)境等因素,所以采用的是 Docker 方式。鑒于要詳細了解 Faiss 服務是如何演變?yōu)?Vearch 這個彈性分布式系統(tǒng)的,所以采用的源碼編譯安裝。
# 下載源碼git clone https://github.com/vearch/vearch# 切換到鏡像編譯目錄cd vearch/cloud# 打包環(huán)境鏡像 vearch/vearch_env:3.2.2,將gcc,git,faiss,rocksdb,go等安裝好# 這步打包比較慢,可以直接使用官方鏡像 docker pull vearch/vearch_env:3.2.2sh compile_env.sh# 使用 vearch_env 編譯二進制文件 vearch,主要是拉取 gamma 源碼進行編譯sh compile.sh# 打包 vearch/vearch:3.2.2, 將打包好的二進制文件vearch和依賴的庫放到鏡像中。# 可以直接使用官方鏡像 docker pull vearch/vearch:3.2.2sh build.sh
官方的鏡像打包還是有優(yōu)化的空間的,打包建議使用centos源,準備好 Faiss, RocksDB, Go等源文件。
圖像處理
圖像處理的服務沒有現(xiàn)成的 Docker 鏡像,而且 Github 倉庫上提供的鏡像打包有問題,可以使用以下的倉庫進行打包。
# 下載源碼(使用修正后的 Dockfile 文件)git clone -b study https://github.com/haojunyu/python-algorithm-plugin# 切換到鏡像目錄并打包鏡像 vearch/images:3.2.2# 可以直接使用打包好的鏡像 docker pull haojunyu/vimgs:3.2.2cd python-algorithm-plugin && docker build -t haojunyu/vimgs:3.2.2 .
swarm啟動
因為兩個服務都已經打包成 Docker 鏡像了,這里直接使用命令 docker stack deploy -c docker-compose.yml vearch 來啟動服務, docker-compose.yml 內容如下:
version: '3.3'services: vearch: image: vearch/vearch:3.2.2 ports: - "8817:8817" - "9001:9001" volumes: - ./config.toml:/vearch/config.toml - ./data:/datas - ./logs:/logs deploy: mode: replicated replicas: 1 restart_policy: condition: on-failure delay: 10s max_attempts: 3 logging: driver: "json-file" options: max-size: "1g" imgs: image: haojunyu/vimgs:3.2.2 ports: - "4101:4101" volumes: - ./python-algorithm-plugin/src/config.py:/app/src/config.py - ./images/imgs:/app/src/imgs command: ["bash", "../bin/run.sh", "image"] deploy: mode: replicated replicas: 3 restart_policy: condition: on-failure delay: 10s max_attempts: 3
注意: 掛載文件 python-algorithm-plugin/src/config.py 是圖片處理服務的配置文件,一般只需要針對自己的情況改動以下四個配置:
- port 指圖片處理服務的端口,默認 4101
- gpus 指定服務是否使用 gpu,默認不用為 -1
- master_address 和 router_address指 Vearch 服務的 master 和 router服務
服務用法
因為圖片服務和 Vearch 服務是高度集成的。一般是直接調用圖片服務,而圖片向量錄入 Vearch交給圖片服務自己處理。Vearch 詳細的操作可以參考文檔。
服務監(jiān)控
# 這里master_server指vearch主節(jié)點及其對應端口:localhost:8817# 查看集群狀態(tài)curl -XGET http://master_server/_cluster/stats# 查看健康狀態(tài)curl -XGET http://master_server/_cluster/health# 查看端口狀態(tài)curl -XGET http://master_server/list/server# 清除鎖(在創(chuàng)建表時會對集群加鎖,若在此過程中,服務異常,會導致鎖不能釋放,需要手動清除才能新建表。)curl -XGET http://master_server/clean_lock# 副本擴容縮容curl -XPOST -H "content-type: application/json" -d'{ "partition_id":1, "node_id": 1, "method": 0}' http://master_server/partition/change_member
庫和空間操作
庫和空間的概念類似mysql里面的數(shù)據(jù)庫和表的概念。
- 庫操作
# 查看及群眾所有的庫curl -XGET http://master_server/list/db# 創(chuàng)建庫curl -XPUT -H "content-type:application/json" -d '{ "name": "sv_month"}' http://master_server/db/_create# 查看庫curl -XGET http://master_server/db/$db_name# 刪除庫(庫下存在表空間則無法刪除)curl -XDELETE http://master_server/db/$db_name# 查看指定庫下所有表空間curl -XGET http://master_server/list/space?db=$db_name
- 表空間操作
# 在庫sv_month下創(chuàng)建表空間test(針對image)curl -XPUT -H "content-type: application/json" -d '{ "name":"test", "partition_num":1, "replica_num":1, "engine":{ "name":"gamma", "index_size":70000, "max_size":10000000, "id_type":"String", "retrieval_type":"IVFPQ", "retrieval_param":{ "metric_type":"InnerProduct", "ncentroids":256, "nsubvector":32 } }, "properties":{ "itemid":{ "type":"keyword", "index":true }, "feature1":{ "type":"vector", "dimension":512, "model_id":"vgg16", "format":"normalization" } }}' http://image_server:4101/space/sv_month/_create
數(shù)據(jù)操作
- 數(shù)據(jù)插入
# 插入本地圖片數(shù)據(jù)到表空間中curl -XPOST -H "content-type: application/json" -d' { "itemid":"COCO_val2014_000000123599", "feature1":{ "feature":"../images/COCO_val2014_000000123599.jpg" }} ' http://image_server:4101/sv_month/test/AW63W9I4JG6WicwQX_RC
- 數(shù)據(jù)搜索
# 查詢相似結果curl -H "content-type: application/json" -XPOST -d '{ "query": { "sum": [ { "feature":"../images/COCO_val2014_000000123599.jpg", "field":"feature1" }] }}' http://image_server:4101/sv_month/test/_search
服務效果及上線
效果
在服務構建成功后,就需要查看一下以圖搜圖的效果,而對于效果的鑒別初步以人工為準,最終以線上的指標數(shù)據(jù)為準。對于一個服務效果的好壞在搭建服務之初就應該有個預期,比如:
- 相同的圖片相似度得接近 100%
- 相同類型的應該得到相同類型的結果,比如用小狗搜索出小狗,用汽車搜索出汽車等
以下就是以圖搜圖的效果截圖:
總體來說效果還是挺不錯的。
上線
推薦策略的上線方式有以下幾種:
- 直接服務線上,像排序模型。這種方式要求服務支持高并發(fā),高性能和高可用
- 線上調用 緩存,像內容搜索。這種方式要求服務支持高性能和高可用,并且緩存有較大概率被命中
- 結果離線寫入緩存,像 cf,熱門等可以提前算好的結果。
導入了小視頻最近 7 天新增和最近 30 天曝光的視頻共 9 萬數(shù)據(jù)導入到單機模式的 Vearch 服務中,無法支撐兩個桶平均 48 QPS的沖擊,后使用第二種方式解決上線問題。而對應用戶向量(播放的圖片向量均值)搜索圖片向量策略通過第三種方式上線的。
參考文獻
- Faiss 在項目中的使用
- faiss-web-service
- 基于gRPC的Faiss server實踐
- 京東分布式向量檢索系統(tǒng)vearch
- vearch中文文檔
- vearch核心引擎gamma
- vearch圖像處理插件
- 圖片搜索頁面
如果該文章對您產生了幫助,或者您對技術文章感興趣,可以關注微信公眾號: 技術茶話會, 能夠第一時間收到相關的技術文章,謝謝!
版權聲明:本文內容由互聯(lián)網用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權/違法違規(guī)的內容, 請發(fā)送郵件至 舉報,一經查實,本站將立刻刪除。