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