作者:盧雨畋英特爾邊緣計算創新大使
本文演示了使用OpenVINO與Chinese-Clip進行中文圖文相似性匹配任務:CLIP 模型以自監督的方式在數億或數十億(圖像,文本)對上進行訓練,它從輸入圖像和文本中提取特征向量 embedding,根據特征相似度匹配可完成圖像分類和相似查找任務。CLIP 模型的 zero-shot 分類效果就能達到在 Imagenet 上監督訓練的 ResNet 分類效果,且有更好的泛化和抽象能力。
得益于中文 Clip模型較小的計算開銷與OpenVINO 的優化效果,我們能夠在英特爾開發者套件 AIxBoard 上良好的復現這一推理流程。
本文不會展示所有的代碼,所有資料和代碼的在文末的下載鏈接給出。
英特爾開發者套件
AIxBoard(愛克斯板)
英特爾開發套件AIxBoard(愛克斯板)由 2023 年藍蛙智能推出的人工智能嵌入式開發板,專為支持入門級人工智能應用和邊緣智能設備而設計,是一款面向專業創客、開發者的功能強大的小型計算機。借助OpenVINO工具套件,能夠實現 CPU + iGPU 的高效異構計算推理。
CLIP 原理
CLIP 模型(Contrastive Language-Image Pre-Training) 是來自 OpenAI 的經典圖文表征模型,采用雙塔模型結構(如下圖),利用大規模圖文對平行語料進行對比學習,從而能夠實現圖片和文本的跨模態語義特征抽取。
CLIP 模型基于英文圖文語料,不能用于中文的圖文表征提取場景。得益于達摩院的工作,達摩院的中文 CLIP 以英文 CLIP 視覺側參數和中文 Roberta 參數,作為模型初始化值,使用大規模中文數據進行訓練(~2 億圖文對);最終可用于中文場景下的圖文檢索和圖像、文本的表征提取,應用于搜索、推薦等應用。
二階段預訓練策略(一階段僅訓練文本側,二階段同時訓練)如下所示:
CLIP 應用
CLIP 可以應用于各類不同的場景:
Zero Shot分類
將圖像與類別文本相比較,以得到最接近的分類結果。(例如:圖像分類)
Retrieval
對于給定的輸入文本和圖像,在大量文本與圖像數據中找到最匹配的結果。(例如:clip-retrieval)
CLIP Guidance
對于圖像生成模型,結合生成結果與輸入文本間的 CLIP 距離生成更好的圖片(例如:VQGAN + CLIP)
CLIP Captioning
利用 CLIP encoding 提取特征,以該特征的映射結果結合 GPT2 生成 caption.(例如:ClipCap)
在本文中,你將學會如何使用中文Clip進行Zero Shot分類,以及處理簡單的文字與圖像檢索任務。
模型下載
為節省時間,這里我直接提供了中文clip onnx模型;你也可以根據導出教程,自行導出onnx模型。值得注意的是,OpenVINO也支持Pytorch模型到 OpenVINO IR的轉換方式,如果有興趣你可以參考轉換教程,與源碼自行轉換直接得到OpenVINO模型。
(注意:在這里我提前導出了base的模型,如果你發現在部分任務下效果不是很好,可以嘗試large模型或者進行微調,中文 Clip的官方倉庫中提供了所有的可參考資料。)
模型的加載與運行
01通用模型類
準備用于結果預測的通用模型類,包括模型的初始化與推理。
OpenVINO 模型初始化有四個主要步驟:
1.初始化 OpenVINO Runtime。
2.從模型文件中讀取網絡和權重(支持pytorch onnx paddle tensorflow vinoIR多種中間格式的直接讀?。?/p>
3.將模型編譯為設備可用的形式。
4.獲取并準備節點的輸入和輸出名稱。
我們可以將它們放在一個類的構造函數中。為了讓 OpenVINO 自動選擇最佳設備進行推理,只需使用“AUTO”。大多數情況下,最佳設備是“GPU”(性能更好,但啟動時間稍長)。
core = ov.Core() class VinoModel: def init(self, model_path, device=“AUTO”): self.model = core.read_model(model=model_path) self.input_layer = self.model.input(0) self.input_shape = self.input_layer.shape self.height = self.input_shape[2] self.width = self.input_shape[3] print(“input shape:”,self.input_layer.shape) print(“input names:”,self.input_layer.names) self.compiled_model = core.compile_model(model=self.model, device_name=device) self.output_layer = self.compiled_model.output(0) print(“output names:”,self.output_layer.names) def predict(self, input): result = self.compiled_model(input)[self.output_layer] return result img_model = VinoModel(“image_model.onnx”) txt_model = VinoModel(“text_model.onnx”)
左滑查看更多
02預處理
在輸入OpenVINO引擎推理之前,我們需要對數據進行適當的預處理操作,數據預處理函數改變輸入數據的布局和形狀以適配網絡輸入格式。
def preprocess(image:np.ndarray): image = cv2.resize(image, (224, 224), interpolation=cv2.INTER_CUBIC).astype(np.float32) / 255.0 mean = np.array([0.48145466, 0.4578275, 0.40821073]) std = np.array([0.26862954, 0.26130258, 0.27577711]) image = (image - mean) / std image = np.transpose(image, (2, 0, 1)) image = np.expand_dims(image,axis=0).astype(np.float32) return image
左滑查看更多
03核心函數
在核心處理函數中,我們需要分別提取圖像和文本的Embedding特征,歸一化后一一匹配得到最接近的特征結果。
def run_clip(image:np.ndarray,input_strs:List[str]): image_features = _img_feature(preprocess(image)) text_features = _text_feature(input_strs) logits_per_image = 100 * np.dot(image_features, text_features.T) exp_logits = np.exp(logits_per_image - np.max(logits_per_image, axis=-1, keepdims=True)) max_logit = exp_logits / np.sum(exp_logits, axis=-1, keepdims=True) max_str = input_strs[max_logit.argmax()] max_str_logit = max_logit.max() return max_str, max_str_logit
左滑查看更多
接下來我們將進行Clip模型的推理,我們選擇一個青蛙的圖片作為推理對象。
我們可以初始化一個字符串列表,從而得到該圖最匹配的一個文本信息。
你可以構建一個自己想要進行分類的字符串列表,從而達到在不同任務上分類的目的。
text = [“大象”, “猴子”, “長頸鹿”, “青蛙”] max_str, max_str_logit = run_clip(image,text) print(f”最大概率:{max_str_logit}, 對應類別:{max_str}“)
左滑查看更多
結果顯示為:
最大概率:0.9436781406402588, 對應類別:青蛙
左滑查看更多
你可以根據自己的需求構建不同的分類文本標簽,達到zero shot分類的目的。
除此之外,我們還可以利用OpenVINO提供的Benchmark工具,來更好的觀察Clip模型運行的吞吐量與效率
(注意:你可以將AUTO顯式指定為GPU觀察結果的區別,你也可以嘗試把之前加載的模型重新編譯到GPU觀察性能和結果是否有所區別。)
!benchmark_app-mimage_model.onnx-dAUTO-apisync-t30
左滑查看更多
圖文檢索
接下來,我們將結合之前的推理Embedding結果,利用端到端機器學習Embedding開源庫Towhee以及Meta向量數據庫Faiss,構建一個高效的文圖檢索與圖圖檢索引擎。通過在邊緣設備上部署檢索引擎,我們能夠有效地篩選和總結推理檢測結果,從而更好地進行綜合統計分析。
除此之外,Chinese-Clip同時提供了微調的接口,通過對指定商品數據的微調,你可以結合檢索引擎實現一個商品檢索裝置,抑或是端側商品推薦系統。
(注意:這里只是一個范例,你可以使用端側設備得到Embedding但使用云端數據庫進行匹配,又或者是利用它減少端側數據的篩選時間。)
from towhee.operator import PyOperator from towhee import ops, pipe, DataCollection,register import glob @register class img_embedding(PyOperator): def call(self, path): image = np.array(Image.open(path).convert(‘RGB’)) return _img_feature(preprocess(image))[0] @register class text_embedding(PyOperator): def call(self, input_strs): return _text_feature(input_strs)[0]
左滑查看更多
通過構建自定義 Towhee ops 進行 pipeline 推理,我們可以很容易進行文圖檢索:
decode = ops.image_decode.cv2(‘rgb’) text_pipe = ( pipe.input(‘text’) .map(‘text’, ‘vec’, ops.text_embedding()) # faiss op result format: [[id, score, [file_name], …] .map(‘vec’, ‘row’, ops.ann_search.faiss_index(‘./faiss’, 5)) .map(‘row’, ‘images’, lambda x: [decode(item[2][0]) for item in x]) .output(‘text’, ‘images’) ) DataCollection(text_pipe([‘吃東西的人’])).show()
左滑查看更多
我們輸出了topk前 5 的結果,你可以根據自己的需求修改需要展示多少相關圖片。
不局限于文圖搜索,我們也可以實現圖圖檢索的功能:
image_pipe = ( pipe.input(‘img’) .map(‘img’, ‘vec’, ops.img_embedding()) # faiss op result format: [[id, score, [file_name], …] .map(‘vec’, ‘row’, ops.ann_search.faiss_index(‘./faiss’, 5)) .map(‘row’, ‘images’, lambda x: [decode(item[2][0]) for item in x]) .output(‘img’, ‘images’) ) DataCollection(image_pipe(‘images/000000005082.jpg’)).show()
左滑查看更多
是不是覺得很神奇?即使是小型邊緣設備也能夠運行Clip這樣的大型模型,快通過下方鏈接獲取所有資料,與我一起感受中文Clip與OpenVINO共同帶來的便捷體驗。
審核編輯:湯梓紅
-
英特爾
+關注
關注
60文章
9880瀏覽量
171485 -
人工智能
+關注
關注
1791文章
46845瀏覽量
237535 -
開發套件
+關注
關注
2文章
151瀏覽量
24262 -
OpenVINO
+關注
關注
0文章
87瀏覽量
181
原文標題:在英特爾開發套件上用 OpenVINO? 實現中文圖文檢索 | 開發者實戰
文章出處:【微信號:英特爾物聯網,微信公眾號:英特爾物聯網】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論