簡介 身為一個人工智慧(AI)從業人員,好不容易費盡千辛萬苦訓練好一個模型並且得到不錯的推論準確度後,總會遇到客戶抱怨「這個模型太大塞不進我的硬體,這個推論的速度不能再快一些嗎?」。當換了一個較小、速度快一點的模型,又被抱怨「這個推論的準確度不能再高一點嗎?」。此時腦中總會想起星爺的電影「九品芝蔴官」豹子頭的那句經典台詞「我全都要」,難道就沒有折衷一點的辦法,讓我在 AI 推論速度、準確度和模型大小都能滿足嗎? Intel OpenVINO 算是聽到大家的心聲了吧,日前推出了「Post-Training Optimization Tool (以下簡稱 POT)」來幫助大家,在不用重新訓練模型的情況下,只需執行幾個簡單的命令,模型瞬間縮小,且在僅僅損失一點點推論準確度情況下就能得到 1.1 到 3.3 倍左右推論速度的提升! POT 究竟用了何種方式才能達成這個結果,接下來就從「何謂量化(Quantization)」、「量化算法(Quantization Algorithms)」、「使用 DL Workbench 快速優化」、「安裝 POT 相依套件」等面向來作一些簡單說明,最後再用一個「影像分類 MobileNet 模型優化」實際案例說明其執行方式及優化結果,希望能讓大家有更愉快的 AI 落地開發體驗。 何謂量化 (Quantization) 相信大家平常都有在拍數位照片,一張 1920×1080(俗稱 200 萬畫素)解析度全彩的照片原始檔案大小就要 6,220.8KB,如果不經過壓縮,大概拍沒幾張記憶卡就爆了,所以就有破壞性壓縮的影像格式產生,如 JPG 格式。同樣一張照片經過破壞性壓縮後,檔案就只剩不到 200KB(不同影像壓縮比例不同),檔案大小縮小了 30 倍以上,但人眼卻很難察覺其中的差異,而其中最大的功臣就是「量化(Quantization)」及「編碼(Encoding)」技術。於是就有人想到是否可以套用這樣的概念到 AI 模型壓縮上。 那什麼是量化呢?首先要先了解為什麼要量化。在真實世界中大部份的物理量(如色彩、亮度、音量等)都是連續數值(類比信號),我們很難完整直接記錄所有的內容,於是就有了把類比信號轉換成數位信號再記錄的方式產生。而影響數位信號是否能完美還原成類比信號的兩大參數就是「解析度」及「取樣頻率」。 其中「解析度」又可分為純整數及整數加小數點表示。前者會以 2 的 n 次方來表示,而為了配合電腦運算,n 通常為 8, 16, 32, 64,又可寫作 INT8, INT16, INT32 及 INT64。而後者為了表示小數點,通常採用浮點數表示,常見有半精度(FP16)、單精度(FP32)及倍精度(FP64)浮點數。 這裡明顯可看出不同的數值表示方式,在儲存空間及解析能力有明顯的差異。以 INT8 和 FP32 來舉例比較,INT8 只需 8 個 bit 來表示整數,最多只能表示 2 的 8 次方 256 位階(+127 到 -128 或者 0 到 255)。而 FP32 需要 32bit 來表示整數加小數點,其中 1 bit 表示正負值,8 bit 表示指數(-128 到 +127),23 bit 表示數值,整體可表現的動態範圍大約是在 -1.410-45 到 +3.410+38。 因此資料壓縮最快速的方式就是改變連續(類比)數值「量化」方式,而最直覺的想法就是把高解析度降到低解度,把浮點數降到整數,那儲存空間馬上大幅減少。以 FP32 轉成 INT8 來看,儲存空間從 32 bit 變成 8 bit,一下就少了 3/4(相當於 75%)。而計算從浮點數轉換成整數後,更可透過 INTEL CPU 的單指令多資料(Single Instruction Multiple Data, SIMD)平行計算指令集(如 SSE4.2, AVX2, AVX512 等)加速運算,讓計算速度提升數倍到數十倍。如 Fig. 1 所示。 Fig. 1 數值量化及單指令多資料(SIMD)平行運算指令集示意圖。(OmniXRI Apr. 2021整理製作) 量化算法(Quantization Algorithms) 一般來說,為求得深度學習模型有較好的訓練結果,通常會使用 FP32 做為參數初始的數值表示方式,包括權重值(Weights)及激活值(Activations)。待訓練完成後透過 POT 插入「偽量化(Fake Quantize)」步驟將 FP32 降至 INT8 數值格式,如此便不用重新訓練模型,就可得到較小儲存空間的模型及較快速運算速度。 亦可調整相關參數使其成為「對稱量化(Symmetric Quantization)」或「非對稱量化(Asymmetric Quantization)」。以 FP32 轉換至 INT8 為例,首先找出 FP32 所有參數的最大值(max.)和最小值(min),再將 FP32 的值重新依比例映射到 INT8 空間中,如 Fig. 2 所示。 Fig. 2 對稱式、非對稱式量化及偽量化示意圖。(OmniXRI Apr. 2021整理製作) 目前 POT 提供了兩種 INT8 的量化算法,「預設量化(DefaultQuantization)」及「準確度感知量化(AccuracyAwareQuantization)」。前者提供較快速推論結果,但推論準確度會下降一些。而後者可指定推論準確度容許下降的幅度,但需要較多時間進行調整,且推論速度略差於前者,如 Fig. 3 所示。以下就簡單描述二種作法的差異。 1. 預設量化(DefaultQuantization) 輸入正常訓練後的模型,將卷積層輸出之激活值範圍做一簡單對齊,減少量化時的誤差。再根據量化前最大及最小值在權重值及激活值自動插入偽量化層。最後基於卷積及全連結層量化誤差調整偏置量(Bias),使得整體誤差保持不變。 可參考:DefaultQuantization Algorithm 2. 準確度感知量化(AccuracyAwareQuantization) 首先使用預設量化算法對輸入模型進行 INT8 量化。接著測試驗證資料集量化前及量化後的準確度。若符合指定容許下降的準確度範圍,就結束量化調整動作,得到新的模型權重值及激活值。若推論準確度下降超過指定範圍,則取得逐層對準確度下降的貢獻並排序,即找出造成不準的主要源頭。接著將有問題的層還原為原數值精度(如 FP32),再重新驗證推論準確度,直到滿足限制下降的容許度。如果限制下降幅度要求很小,則最差狀況可能將所有 INT8 內容全部還原回 FP32,等於模型參數完全沒調整、沒重新量化。 可參考:AccuracyAwareQuantization Algorithm Fig. 3 OpenVINO POT INT8 量化算法,(a) 預設量化,(b) 準確度感知量化。 使用 DL Workbench 快速優化 在文章「不用寫程式也能玩轉深度學習模型 ─ OpenVINO™ DL Workbench圖形化介面工具簡介」最後留了一個小彩蛋,這裡就幫大家補充說明,其實 Workbench 可在建立基準點時順便選擇優化(Optimize)方式,執行 POT 來得到轉換成 INT8 格式的 IR(*.bin & *.xml) 中間表示檔案,下載後就可使用,不用寫任何程式,接下來就簡單說明如何操作。 參考「不用寫程式也能玩轉深度學習模型 ─ OpenVINO™ DL Workbench圖形化介面工具簡介」實際案例操作執行步驟,當進入 [5.建立建立基準點] 時,會自動建立第一個基準點,此時可切換到優化 [Optimize] 頁面,選擇 [INT8] 選項,就會進到數值校正方式(Calibration Method) 選擇,即上一節中提及的 POT 量化算法。 這裡可選擇 [預設量化(Default Method)] 或 [準確度感知量化(AccuracyAware Method)],若選後者則可再輸入期望容許下降的幅度(%),建議不要太小,以免失去優化速度和模型大小的目的。最後按下 [Optimize] 鍵就會自動產生新的工作組態,不過這裡可能會視電腦的等級、模型的大小、複雜度及容許下降幅度,需要等待數分鐘到數十分鐘不等的轉換時間。完整操作流程如 Fig. 4 所示。 當產生新的工作組態後,應該會自動計算第一次的測試結果,包括輸出速度(Best Throughout, FPS)、延時(Respective Latency, ms)及準確度(Accuracy)。若數值空白則按一下更新符號(藍色旋轉箭頭)進行重新計算。由 Fig. 4 案例來看,經過優化(INT8 預設量化)後,輸出速度快了 1.6 倍,延時也降了 1.6 倍,而準確度只掉了 1%,表現相當不錯。當然不同的模型及優化後的改善幅度也會有所不同。 Fig. 4 DL Workbench 使用 POT 優化操作流程圖。(OmniXRI Apr. 2021整理製作) 安裝 POT 相依套件 若不想使用 DL Workbench 來取得 POT 優化結果,亦可以使用命令列方式進行操作。首先要說明的是 OpenVINO POT 並不在開源的範圍,無法從官方 Github 上取得,只能透過一般正常安裝包取得,安裝 POT 前須先安裝好 OpenVINO Toolkit 完整版。以下就使用 Ubuntu 18.04 環境安裝來進行說明,依序要安裝好「模型優化器(Model Optimizer, MO)」、「準確度檢查器(Accuracy Checker, AC)」及「訓練後優化工具(Post-training Optimization Tool, POT)」。 #若系統上同時存在Python 2.x和3.x版,則使用python3進行安裝,Python版本建議大於3.5版以上。 #預設在Unbuntu上安裝完OpenVINO後會存放在 /opt/intel/openvino_2021 路徑下,不同版本請自行修改路徑名稱 #1.進入命令列模式後,一定要先設定環境變數,不然後面很多操作會出現錯誤,找不到對應工作路徑及變數。 cd /opt/intel/openvino_2021/bin/ ./setvars.sh #2.接著切換路徑,安裝模型優化器(MO)預要求項目。 cd /opt/intel/openvino_2021/deployment_tools/model_optimizer/install_prerequisites sudo ./install_prerequisites.sh #3.若成功,回到上一層,執行下列命令,顯示MO各參數說明文字。 cd .. python3 mo.py -h #4.切換路徑,安裝並執行準確度確認器(AC),顯示AC各參數說明文字。 cd /opt/intel/openvino_2021/deployment_tools/open_model_zoo/tools/accuracy_checker python3 setup.py install accuracy_check -h #5.切換路徑,安裝並執行訓練後優化工具(POT),顯示POT各參數說明文字。 cd /opt/intel/openvino_2021/deployment_tools/tools/post_training_optimization_toolkit python3 setup.py install pot -h 影像分類 MobileNet 模型優化 接下來就以常見的影像分類模型 MobileNet-v2 來說明如何利用 POT 執行優化工作。 1. 環境設定、下載模型並轉換至 IR 格式 首先依據上一節說明把模型優化器(MO)、準確度檢查器(AC)及訓練後優化工具(POT)安裝好,創建一個可供下載模型的路徑並下載模型。接著把下載到的模型轉換成 OpenVINO 專用的中間表示格式IR(*.bin, *.xml)檔案,包含 FP16 及 FP32 數值精度。更多公開模型類型及名稱可參考說明:Overview of OpenVINO™ Toolkit Public Models。 #在使用者名稱下創建一個Models的路徑並切換至該路徑 mkdir /home//Models cd /home//Models #下載mobilenet-v2模型,這裡可替換成其它常用公開模型 python3 /opt/intel/openvino_2021/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name mobilenet-v2 #完成下載後會在 /home//Models/public/mobilenet-v2路徑下看到Caffe格式模型檔 mobilenet-v2.caffemodel及mobilenet-v2.prototxt,不同模型可能由不同框架產生(如TensorFlow, PyTorch, ONNX…) #轉換模型變成OpenVINO中間表示格式IR檔案(*.bin, *.xml) python3 /opt/intel/openvino_2021/deployment_tools/open_model_zoo/tools/downloader/converter.py --name mobilenet-v2 #完成轉換後會在 /home//Models/public/mobilenet-v2路徑下產生/FP16及/FP32二種數值精度格式的IR檔(*.bin, *.xml) 2. 模型原始數值精度的性能基準測試 為了得知後續優化程度,這裡可以先進行一些性能基準測試(Performance Benchmark),了解原始數值精度(FP16 / FP32) 的表現,經計算後可得到其延遲時間(ms)及輸出速度(FPS)。 #對IR檔進行FP32性能基準測試,亦可替換成FP16進行測試,請自行替換成自己電腦上使用者的名字 python3 /opt/intel/openvino_2021/deployment_tools/tools/benchmark_tool/benchmark_app.py -m /home//Models/public/mobilenet-v2/FP32/mobilenet-v2.xml #這裡是以Intel Core i5-4440 @3.10GHz * 4, 8GB RAM, Ubuntu 18.04.5 LTS 64ibt環境進行測試,完成測試後會得到如下數值。 Latency: 17.09 ms Throughput: 222.71 FPS 3. 準備資料集 這裡不限何種資料集,可自行準備,只要滿足 OpenVINO 的規範即可,建議選用 ImageNet, VOC, COCO 等常用資料集格式會較方便。這裡以 ImageNet 來舉例,首先到 ImageNet 官網申請一個帳號,點選同意用於非商業用途,它會寄出確認信,點擊回覆後就能開通,但請注意他們不接受 hotmail 或 gmail 的電子信箱申請。 接著切換到下載(Download)頁面,移到最下方 Download links to ILSVRC image data,點選 2012,挑選 Validation images(all tasks) 6.3GB 下載驗證影像集,另外可從 ImageNet ILSVRC 2012 annotation file 下載到這個資料集的標註檔。若只是想測試一下整個 POT 工作流程,不想大費周章,這裡幫大家準備了一個從上述資料摘錄出來的超迷你影像分類用資料集和標註檔(只有 100 張影像)方便測試使用,請勿移作其它用途。下載網址如下,再將其解壓縮至/home//Models下即可。 https://github.com/OmniXRI/OpenVINO_POT_Test_Data 4. IR 格式原始精度模型的準確度驗證 在 /home//Models 路徑下建立準確度檢查器(Accuracy Checker) 組態檔案 mobilenet_v2.yaml,內容如下。其中 datasets 下的 data_source 即為準備好的資料集路徑,而 annotation_file 則為標註檔案路徑及名稱,要手動修改為自己準備好的路徑,其它更進一步相關參數設定可參考:Deep Learning accuracy validation framework。 models: - name: mobilenet-v2 launchers: - framework: dlsdk device: CPU adapter: classification datasets: - name: classification_dataset data_source: ./MiniImageNet annotation_conversion: converter: imagenet annotation_file: ./MiniImageNet/val.txt reader: pillow_imread preprocessing: - type: resize size: 256 aspect_ratio_scale: greater use_pillow: True - type: crop size: 224 use_pillow: True - type: bgr_to_rgb metrics: - name: accuracy@top1 type: accuracy top_k: 1 ###draft_code_symbol_lessthen###ul> ###draft_code_symbol_lessthen###li>name: accuracy@top5 type: accuracy top_k: 5 接著就能以下列命令執行準確度評估了。 accuracy_check -c mobilenet_v2.yaml -m ./public/mobilenet-v2/FP32/ 結果如下所示。 100 objects processed in 1.328 seconds accuracy@top1: 73.00% accuracy@top5: 92.00% 5. 模型量化 在 /home//Models 路徑下建立訓練後優化工具組態(POT Configuration) 組態檔案 mobilenet_v2_int8.json,內容如下。其中 model 下的 model 和 weights 指定的是原始(FP32)數值精度的 IR 格式模型(.xml)及權重檔(.bin),而 engine 下的 config 則是指定上一步驟產生的 mobilenet_v2.yaml,最後指定模型INT8量化演算法類型,即為 compression 下 algorithms 下 name 下的 DefaultQuantization。這裡 name 亦可選擇 ”AccuracyAwareQuantization”,但要在 params 下新增一項 ”maximal_drop”: 0.01,來指定優化時最大容許準確率下降幅度。 { "model": { "model_name": "mobilenet-v2", "model": "./public/mobilenet-v2/FP32/mobilenet-v2.xml", "weights": "./public/mobilenet-v2/FP32/mobilenet-v2.bin" }, "engine": { "config": "./mobilenet_v2.yaml" }, "compression": { "algorithms": [ { "name": "DefaultQuantization", "params": { "preset": "performance", "stat_subset_size": 300 } } ] } } 接著就能以下列命令執行訓練後優化工具,產生 INT8 格式的模型及權重了。 pot -c mobilenet_v2_int8.json -e 執行後會產新的路徑 /results/mobilenetv2_DefaultQuantization//optimized,而結果會置放於此,其中為執行當下時間,重複執行時會產生不同時間(目錄名稱),結果顯示如下所示。 100 objects processed in 1.164 seconds INFO:compression.engines.ac_engine:Inference finished INFO:app.run:accuracy@top1 : 0.69 INFO:app.run:accuracy@top5 : 0.94 若想更了解 POT 組態設定,可參考 Post-Training Optimization Best Practices。 6. 執行模型量化後性能基準比較 最後執行下面指令來確認 INT8 量化(優化)後得到的效果。這裡要注意 須為上一步驟產生的路徑。 python3 /opt/intel/openvino_2021/deployment_tools/tools/benchmark_tool/benchmark_app.py -m /home//Models/results/mobilenet-v2_DefaultQuantization//optimized/mobilenet-v2.xml 執行結果如下所示。感覺上和前面以 DL Workbench 執行 ssd-mobilenet_v2-coco 效果差滿多的,在推論速度部份只有提升約 9.8%,Top 1 準確度還不錯只掉了約 1%,模型(xml) 檔案則因增加許多 Fake Quantization 層描述,所以變大一些,但權重(bin)部份則減到剩原來的 26.7%,相當於減去 3/4 的檔案大小,對於記憶體的需求減輕不少壓力。 經測試多種模型後得知,速度提升可能從 0.01 倍到 3 倍多,會隨模型開發框架(如 Caffe, TensorFlow, ONNX…)、搭配資料集結構(如 ImageNet, VOC, COCO…)、模型應用類型(如影像分類、物件偵測、影像分割、骨架關鍵點偵測等…)及電腦運算時的系統資源(CPU, RAM…)配置不同,可能都會得到差異頗大結果,因此想快速找出最優解,則利用 DL Workbench 圖形化介面來操作會更加便利。最後補充一個 INTEL 官方的 POT 介紹影片(Post Training Optimization Tool | OpenVINO™ toolkit | Ep. 68 | Intel Software),方便大家更進一步了解這項工具。 小結 一般 AI 工程師最苦惱的推論速度、準確度及模型大小,經過 Intel OpenVINO 的訓練後優化工具(Post-Training Optimizztion Tool, POT) 處理後,不用寫半行程式,就能馬上讓模型縮小到原有 1/2 甚至 1/3,推論速度提高 1.1 到 3 倍,準確度還只掉一點點。若再搭配 OpenVINO DL Workbench 圖形化介面使用,工作效率就更高了。話說回來,這麼好用的工具千萬不要讓老板知道,工程師只能自己偷偷用,不然工作就做不完了。 詳細內容 小孩才作選擇,AI推論速度及準確度我全都要 ─ OpenVINO Post-Training Optimization Tool簡介 - 引領創新的科技實作社群媒體身為人工智慧(AI)從業人員,如何兼顧模型的速度和準確度是一大挑戰。利用INTEL OpenVINO推出的「P...makerpro.cc