Paddle Lite端側部署
端側推理引擎的由來
隨着深度學習的快速發展、特別是小型網絡模型的不斷成熟,原本應用到雲端的深度學習推理,就可以放到終端上來做,比如手機、手表、攝像頭、傳感器、音響,也就是端智能。此外,可用於深度學習計算的硬件也有井噴之勢,從Intel到Nvidia、ARM、Mali,再到國產的寒武紀等等。
相比服務端智能,端智能具有低延時、省雲端資源、保護數據隱私等優勢。目前端智能正逐漸變為趨勢,從業界來看,它已經在AI攝像、視覺特效等場景發揮了巨大價值。深度學習推理場景中,多樣的平台,不同的硬件,對推理庫的能力提出了更高的要求。端側模型的推理經常面臨算力和內存的限制,加上日趨異構化的硬件平台和復雜的端側使用狀況,導致端側推理引擎的架構能力頗受挑戰。
端側推理引擎是端智能應用的核心模塊,需要在有限算力、有限內存等限制下,高效地利用資源,快速完成推理。可以說,端側推理引擎實現的優劣,直接決定了算法模型能否在端側運行,決定了業務能否上線。因此,希望提供面向不同業務算法場景,不同訓練框架,不同部署環境的簡單、高效、安全的端側推理引擎。
圖2 支持多種硬件、操作系統和編程接口
Paddle Lite是什么
Paddle Lite是飛槳自研的新一代端側推理推理框架,支持PaddlePaddle/TensorFlow/Caffe/ONNX模型的推理部署,目前已經支持ARM CPU, Mali GPU, Adreno GPU, Huawei NPU等多種硬件,正在逐步增加X86 CPU, Nvidia GPU 等多款硬件,相關硬件性能業內領先。截止到現在,Paddle Lite已廣泛應用於搜索廣告、手機百度、百度地圖、全民小視頻等多個公司重點業務。
Paddle Lite具備以下幾個特點:
- 多平台:不同於其他的推理引擎,Paddle Lite依托飛槳訓練框架及其對應的豐富完整的算子庫,底層算子計算邏輯與訓練嚴格一致,模型完全兼容無風險。支持PaddlePaddle、TensorFlow、Caffe、ONNX等多種平台的主流模型格式;支持MobileNetV1、YoloV3、UNet、SqueezeNet等主流模型;對Int8量化模型有很好的支持。同時,可以支持端側多個平台,比如Android, iOS, ArmLinux等。
- 多硬件:目前支持 ARM CPU, Mali GPU, Adreno GPU, 華為NPU,X86 CPU, NVIDIA GPU、FPGA等多種硬件平台,是目前首個支持華為NPU在線編譯的深度學習推理框架。Paddle Lite可以完整承擔深度學習模型在不同硬件平台上的的推理部署需求,從而保障了硬件的支持能力。
- 高性能:通過底層計算模式的建模,增加了多種計算模式(硬件、量化方法、Data Layout)混合調度的完備性設計;對不同硬件進行針對性優化,充分挖掘硬件性能極致,在推理速度上全面超越業界。
- 輕量級:提供Model Optimize Tool對模型進行優化,其中包含諸如量化、融合、Kernel優選等優化手段,優化后的模型更輕量級,耗費資源更少,從而執行速度也更快。同時,Paddle Lite支持分析階段與執行階段分離,線下模型優化,線上模型部署,部署不依賴於任何第三方庫。
- 量化:可以分為靜態離線量化和動態離線量化。靜態離線量化是指使用少量校准數據計算量化因子,快速得到量化模型。使用該量化模型進行預測,可以減少計算量、降低計算內存、減小模型大小。動態離線量化是指將模型中特定OP的權重從FP32類型量化成INT8/16類型,減少模型的大小。
- 融合:將多個連續OP融合成單個等效OP,或者將專屬於某個硬件的OP融合為一個子圖,只有這部分子圖運行在指定的硬件上,減少數據交換並簡化圖結構。例如將NPU相關的op融合為一個子圖,這個子圖的計算都在NPU上進行,其它OP的計算在CPU或GPU上進行。
- Kernel優選:OP的具體實現需要依賴Kernel,每個OP基於不同的硬件或同一硬件不同版本可以選擇不同的Kernel。Paddle Lite可以基於策略優選合適的Kernel來進行計算。
- 簡單易用:支持C++、Java、Python多種編程語言的編程接口。
圖2 多種推理終端和多種推理硬件層出不窮
Paddle Lite推理流程
使用Paddle Lite對模型進行部署推理的流程分以下階段:
- 模型訓練階段:主要解決模型訓練,利用標注數據訓練出對應的模型文件。面向端側進行模型設計時,需要考慮模型大小和計算量。
- 模型部署階段:
a) 獲取模型:用戶可以直接使用飛槳訓練出的模型進行部署,也可以使用Caffe, TensorFlow或ONNX平台訓練的模型,需要使用X2Paddle工具將其它框架訓練的模型轉換到Paddle格式。
b) (可選)模型壓縮:主要優化模型大小,借助PaddleSlim提供的剪枝、量化等手段降低模型大小,以便在端上使用。
c) 通過Model Optimize Tool將模型轉換為Paddle lite的nb模型,然后開始部署。
d) 在終端上通過調用Paddle Lite提供的API接口(提供C++、Java、Python等API接口),完成推理相關的所有計算。
圖3 部署流程
Paddle Lite支持的模型
Paddle Lite目前已嚴格驗證28個模型的精度和性能,對視覺類模型做到了較為充分的支持,覆蓋分類、檢測、分割等多個領域,包含了特色的OCR模型的支持,並在不斷豐富中。其支持的list如下:
注意:
- 模型列表中 * 代表該模型鏈接來自PaddlePaddle/models,否則為推理模型的下載鏈接
- 支持平台列表中 NPU* 代表ARM+NPU異構計算,否則為NPU計算
Paddle Lite Demo
為用戶准備了多個完整的Paddle Lite Demo,方便用戶直接使用Demo調用Paddle Lite進行體驗,也可以發揮想象對Demo進行二次開發。Paddle Lite Demo覆蓋Android、iOS和Armlinux三大平台,涵蓋人臉識別、人像分割、圖像分類、目標檢測、基於視頻流的人臉檢測+口罩識別等多個應用場景。
1. 人臉識別
人臉識別是Paddle Lite提供的人臉識別Demo。在移動端上提供了高精度、實時的人臉檢測、人臉關鍵點定位等能力,能處理基於人臉檢測的業務場景。在移動端推理的效果圖如下:
2. 人像分割
人像分割是Paddle Lite 提供的圖像分割Demo。在移動端上提供了實時的人像分割能力,可以應用證件照自動摳圖、面積測量、智能交通(標記車道和交通標志)等場景。 在移動端推理的效果圖如下:
3. 圖像分類
圖像分類是Paddle Lite 提供的圖像處理Demo。在移動端上提供了實時的物體識別能力,可以應用到生產線自動分揀或質檢、識別醫療圖像、輔助醫生肉眼診斷等場景。在移動端推理的效果圖如下:
4. 目標檢測
目標檢測是Paddle Lite 提供的圖像識別Demo。在移動端上提供了檢測多個物體的位置、名稱、位置及數量的能力。可以應用到視頻監控(是否有違規物體或行為)、工業質檢(微小瑕疵的數量和位置)、醫療診斷(細胞計數、中葯識別)等場景。在移動端推理的效果圖如下:
5. 基於視頻流的人臉檢測+口罩識別
基於視頻流的人臉檢測+口罩識別是Paddle Lite 是在疫情期間提供的在戴口罩與否下人臉識別Demo。在移動端上提供了是否佩戴口罩識別、高精度和實時的人臉檢測等能力,能處理多種場景下人臉檢測業務,如戴口罩下人臉檢測。在移動端推理的效果圖如下:
Paddle Lite Demo在不同平台下的操作方法稍有不同,下面以目標檢測Demo為例,分別介紹如何在Android和iOS平台進行部署。
Android平台實戰
Android demo部署方法
以 目標檢測Demo(object_detection_demo) 為例,講解如何部署Android工程。將基於Paddle Lite推理庫的Android Demo部署到Android手機,實現目標檢測。
環境准備
- 一部Android手機(開啟USB調試模式)
- 一根數據線
- 已制作好的Paddle Lite Demo
- 電腦一台:安裝Android Studio
部署步驟
- 下載Paddle-Lite-Demo,存放地址為: Paddle-Lite-Demo\PaddleLite-android-demo\object_detection_demo。
- 用Android Studio 打開object_detection_demo工程 (本步驟需要聯網)。
- 手機連接電腦,打開USB調試和文件傳輸模式,在Android Studio上連接自己的手機設備(手機需要開啟允許從USB安裝軟件權限)。
4. 按下Run按鈕,自動編譯APP並安裝到手機。(該過程會自動下載Paddle Lite推理庫和模型,需要聯網)。成功后效果如下,左圖是APP安裝到手機,右圖是APP打開后的效果,會自動識別圖片中的物體並標記。
Android demo結構講解
Android demo的代碼結構如下所示:
- Predictor.java:推理代碼
# 位置:
object_detection_demo/app/src/main/java/com/baidu/paddle/lite/demo/object_detection/Predictor.java
- model.nb:模型文件 (opt 工具轉化后Paddle-Lite模型);pascalvoc_label_list:訓練模型時的labels文件
# 位置:
object_detection_demo/app/src/main/assets/models/ssd_mobilenet_v1_pascalvoc_for_cpu/model.nb
object_detection_demo/app/src/main/assets/labels/pascalvoc_label_list
- libpaddle_lite_jni.so、PaddlePredictor.jar: Paddle-Lite Java 推理庫與Jar包
# 位置
object_detection_demo/app/src/main/jniLibs/arm64-v8a/libpaddle_lite_jni.so
object_detection_demo/app/libs/PaddlePredictor.jar
- build.gradle:定義編譯過程的 gradle 腳本。(不用改動,定義了自動下載Paddle-Lite推理和模型的過程)
# 位置
object_detection_demo/app/build.gradle
Paddle Lite Java API使用指南
Android demo基於Java API開發,調用Paddle Lite Java API包括以下五步。更詳細的API描述參考:Paddle Lite Java API。
// 導入Java API
import com.baidu.paddle.lite.MobileConfig;
import com.baidu.paddle.lite.Tensor;
import com.baidu.paddle.lite.Predictor;
import com.baidu.paddle.lite.PowerMode;
// 1. 寫入配置:設置MobileConfig
MobileConfig config = new MobileConfig();
config.setModelFromFile(<modelPath>); // 設置Paddle Lite模型路徑
config.setPowerMode(PowerMode.LITE_POWER_NO_BIND); // 設置CPU運行模式
config.setThreads(4); // 設置工作線程數
// 2. 創建 PaddlePredictor
PaddlePredictor predictor = PaddlePredictor.createPaddlePredictor(config);
// 3. 設置輸入數據
long[] dims = {100, 100};
float[] inputBuffer = new float[10000];
for (int i = 0; i < 10000; ++i) {
inputBuffer[i] = i;
}
Tensor input = predictor.getInput(0);
input.resize(dims);
input.setData(inputBuffer);
// 4. 執行推理
predictor.run();
// 5. 獲取輸出數據
Tensor output = predictor.getOutput(0);
float[] output = result.getFloatData();
for (int i = 0; i < 1000; ++i) {
System.out.println(output[i]);
}
如何替換Android demo中的模型
本節詳細講解如何替換“目標檢測”demo中的模型(比如替換為“人臉檢測”模型),並將模型部署到Android demo。
替換簡述:替換demo中的模型和label文件,並修改推理代碼Predictor.java。
- 安裝paddle-lite 的opt python工具 Linux、Mac、Windows環境支持直接從pip安裝paddle-lite工具,安裝后可以在python 端調用paddlelite預測工具和模型轉換工具opt
pip install paddlelite
- 使用opt工具轉化模型。
在終端執行下面命令完成轉化。
# 假設模型在當前路徑下的`./ssd_mobilenet_v1_pascalvoc`。
paddle_lite_opt \
--model_dir=./ssd_mobilenet_v1_pascalvoc \
--optimize_out_type=naive_buffer \
--optimize_out=./ssd_mobilenet_v1_pascalvoc_opt \
--valid_targets=arm
轉化過程與結果如下圖所示:ssd_mobilenet_v1_pascalvoc_opt.nb為轉化結果
opt 參數說明:
- 替換模型和相應的label文件 用轉化后的model文件和label文件替換Android Demo中的對應位置。
- 修改predictor.java文件。一般需要修改代碼中的“模型名稱”和輸入的shape。
- 參考“Android Demo部署方法”,重新構建並運行Android demo。
如何替換Demo中的Paddle Lite推理庫
如果您想替換Demo中的Paddle Lite推理庫(如想修改推理庫版本),你可以在Paddle Lite relase界面下載指定版本的推理庫並替換。
1.下載Paddle Lite預編譯庫
推理庫下載界面位於Paddle Lite官方預編譯庫,可根據需求選擇合適版本。
以Android-ARMv8架構為例,可以下載以下版本。
**解壓后內容如下圖所示。
說明: libpaddle_lite_jni.so是Java推理庫文件,位於inference_lite_lib.android.armv8/java/so/libpaddle_lite_jni.so PaddlePredictor.jar是Java推理庫對應的Jar文件,位於inference_lite_lib.android.armv8/java/jar/PaddlePredictor.jar
- 用新下載的libpaddle_lite_jni.so 和PaddlePredictor.jar替換demo中的推理庫文件。
mkdir app/src/main/jniLibs/arm64-v8a
cp inference_lite_lib.android.armv8/java/so/libpaddle_lite_jni.so ./app/src/main/jniLibs/arm64-v8a
cp inference_lite_lib.android.armv8/java/jar/PaddlePredictor.jar ./app/libs/
iOS平台目標檢測實戰
iOS demo部署方法
以 目標檢測Demo(object_detection_demo) 為例,講解如何部署iOS工程。將基於Paddle Lite推理庫的iOS Demo部署到蘋果手機,實現目標檢測。
環境准備
- 一部iPhone手機(開啟USB調試模式)
- 一根數據線
- 已制作好的Paddle-Lite-Demo工程
- Mac電腦一台:安裝Xcode
部署步驟
- 目標檢測的iOS示例位於 Paddle-Lite-Demo\PaddleLite-ios-demo\object_detection_demo。
- 終端中執行 download_dependencies.sh腳本自動下載模型和Paddle-Lite推理庫。
cd PaddleLite-ios-demo # 終端中進入 Paddle-Lite-Demo\PaddleLite-ios-demo
sh download_dependencies.sh # 執行腳本下載依賴項 (需要聯網)
下載完成后會出現提示: Extract done
- 用Xcode打開object_detection_demo/detection_demo.xcodeproj文件,修改工程配置。 依次修改 General/Identity和Signing&Capabilities屬性,替換為自己的工程代號和團隊名稱。(必須修改,不然無法通過編譯)
- iPhone手機連接電腦,在Xcode中連接自己的手機 (第一次連接IPhone到電腦時,需要在IPhone的設置->通用->設備管理中選擇本電腦並信任)。
- 按下左上角的 Run按鈕,自動編譯APP並安裝到手機。在蘋果手機中設置信任該APP(進入設置->通用->設備管理,選中新安裝的APP並驗證該應用)。
成功后效果如下,左圖:APP安裝到手機 ,右圖: APP打開后的效果,會自動識別圖片中的物體並標記。
iOS demo結構講解
iOS 示例的代碼結構如下所示。
- mobilenetv1-ssd: 模型文件 (opt 工具轉化后Paddle-Lite模型)
# 位置:
ios-detection_demo/detection_demo/models/mobilenetv1-ssd
2.libpaddle_api_light_bundled.a、paddle_api.h : Paddle-Lite C++ 推理庫和頭文件
# 位置:
# iOS推理庫
ios-detection_demo/detection_demo/lib/libpaddle_api_light_bundled.a
# 推理庫頭文件
ios-detection_demo/detection_demo/include/paddle_api.h
ios-detection_demo/detection_demo/include/paddle_use_kernels.h
ios-detection_demo/detection_demo/include/paddle_use_ops.h
- ViewController.mm:主要推理代碼
# 位置
ios-detection_demo/detection_demo/ViewController.mm
Paddle-Lite C++ API使用指南
IOS Demo基於C++ API 開發,調用Paddle-Lite C++ API包括以下五步。更詳細的API 描述參考: Paddle Lite C++ API。
#include <iostream>
// 引入C++ API
#include "paddle_api.h"
// 1. 設置MobileConfig
MobileConfig config;
config.set_model_from_file(<modelPath>); // 設置NaiveBuffer格式模型路徑
config.set_power_mode(LITE_POWER_NO_BIND); // 設置CPU運行模式
config.set_threads(4); // 設置工作線程數
// 2. 創建PaddlePredictor
std::shared_ptr<PaddlePredictor> predictor = CreatePaddlePredictor<MobileConfig>(config);
// 3. 設置輸入數據
std::unique_ptr<Tensor> input_tensor(std::move(predictor->GetInput(0)));
input_tensor->Resize({1, 3, 224, 224});
auto* data = input_tensor->mutable_data<float>();
for (int i = 0; i < ShapeProduction(input_tensor->shape()); ++i) {
data[i] = 1;
}
// 4. 執行推理
predictor->run();
// 5. 獲取輸出數據
std::unique_ptr<const Tensor> output_tensor(std::move(predictor->GetOutput(0)));
std::cout << "Output shape " << output_tensor->shape()[1] << std::endl;
for (int i = 0; i < ShapeProduction(output_tensor->shape()); i += 100) {
std::cout << "Output[" << i << "]: " << output_tensor->data<float>()[i]
<< std::endl;
}
如何替換iOS demo 中的模型
- 替換推理庫 將預編譯庫中的libpaddle_api_light_bundled.a, 拷入到ios-detection_demo工程下的detection_demo/lib/文件夾。
說明:libpaddle_api_light_bundled.a是C++推理庫文件,位於inference_lite_lib.ios64.armv8/lib/libpaddle_api_light_bundled.a
可以手動復制也可以用下面命令在終端中執行:
# 終端中復制方法:假設`inference_lite_lib.ios64.armv8`為預編譯庫地址
cp inference_lite_lib.ios64.armv8/lib/libpaddle_api_light_bundled.a ./detection_demo/lib/
- 替換推理庫頭文件 將預編譯庫中的inference_lite_lib.ios64.armv8/include/下的所有.h文件, 拷入到ios-detection_demo工程下的paddle_lite文件夾下。
說明:inference_lite_lib.ios64.armv8/include/下的.h文件是C++ 推理庫的頭文件。
可以手動復制也可以用下面命令在終端中執行:
# 終端中復制方法:假設`inference_lite_lib.ios64.armv8為預編譯庫地址
cp inference_lite_lib.ios64.armv8/include/* detection_demo/paddle_lite/
- 替換模型 將轉化后的移動端模型ssd_mobilenet_v1_pascalvoc_opt.nb, 拷入到ios-detection_demo工程下的detection_demo/models/文件夾。
可以手動復制也可以用下面命令在終端中執行:
# 終端中復制方法:假設優化后的模型位置為`ssd_mobilenet_v1_pascalvoc_opt.nb`
cp ssd_mobilenet_v1_pascalvoc.nb ./detection_demo/models/
4.重新構建和運行構建iOS工程。