博客專(zhuān)欄

EEPW首頁(yè) > 博客 > ONNX 淺析:如何加速深度學(xué)習(xí)算法工程化?

ONNX 淺析:如何加速深度學(xué)習(xí)算法工程化?

發(fā)布人:計(jì)算機(jī)視覺(jué)工坊 時(shí)間:2021-12-15 來(lái)源:工程師 發(fā)布文章

以下文章來(lái)源于拍樂(lè)云Pano ,作者拍樂(lè)云視頻專(zhuān)家

AlphaGo擊敗圍棋世界冠軍李世石以來(lái),關(guān)于人工智能和深度學(xué)習(xí)的研究呈現(xiàn)井噴之勢(shì)。

各種新的算法和網(wǎng)絡(luò)模型層出不窮,令人眼花繚亂。與之相隨的,深度學(xué)習(xí)的訓(xùn)練和推理框架也在不斷的推陳出新,比較著名的有:微軟的CNTK、Google的TensorFlow、Facebook的PyTorch、Apple的CoreML、Intel 的OpenVINO、英偉達(dá)的cuDNN和TensorRT、騰訊的TNN和NCNN、阿里的MNN等等。

這些框架都有相似之處,他們的輸入是一個(gè)或者一組多維數(shù)據(jù),數(shù)據(jù)經(jīng)過(guò)多層運(yùn)算單元之后輸出運(yùn)算結(jié)果。訓(xùn)練框架支持BackPropogation等訓(xùn)練方法,可以自動(dòng)調(diào)整模型參數(shù),用于算法設(shè)計(jì)。推理框架則是單純只能用于模型推理運(yùn)算,不能調(diào)整模型本身,用于算法部署落地。

這些框架中,Google的TensorFlow的這個(gè)名字尤其具有美感。多維數(shù)據(jù)是為張量(Tensor),數(shù)據(jù)在多層運(yùn)算單元中的運(yùn)算和傳遞是為流(FLow),看到這個(gè)詞就仿佛看到了一個(gè)數(shù)據(jù)和運(yùn)算的圖(Computation Graph),真可謂妙手偶得之佳作。這些框架都需要構(gòu)建算子,并且將這些算子按照一定的次序連接起來(lái),可以稱(chēng)之為網(wǎng)絡(luò)模型。

01 Why ONNX?

每個(gè)深度學(xué)習(xí)框架都有自己獨(dú)有的格式來(lái)解釋和存儲(chǔ)網(wǎng)絡(luò)模型,并且這些框架的側(cè)重點(diǎn)不同,有些用于訓(xùn)練學(xué)習(xí),有些用于部署推理。在深度學(xué)習(xí)算法開(kāi)發(fā)中,在不同的階段會(huì)選擇不同的框架,所以模型描述格式的不同,在客觀上造成了深度學(xué)習(xí)算法開(kāi)發(fā)和落地的困難。

筆者之前曾開(kāi)發(fā)深度神經(jīng)網(wǎng)絡(luò)算法,當(dāng)時(shí)選擇的訓(xùn)練框架是Caffe,需要落地部署到Linux、iOS、Android等多個(gè)平臺(tái)。Linux選擇的是Nvidia的cuDNN;iOS選擇的是CoreML;Android選擇的是NNAPI,Caffe的模型描述格式是caffemodel。

它使用自定義的Protobuf (https://github.com/BVLC/caffe/tree/master/src/caffe/proto),但是顯然,無(wú)論是cuDNN、CoreML、NNAPI都無(wú)法直接使用caffemodel,CoreML的模型描述使用另一種定義 (https://apple.github.io/coremltools/mlmodel/index.html),cuDNN和NNAPI都是low-level的推理引擎,需要使用者將這個(gè)模型組裝起來(lái)。

對(duì)于CoreML來(lái)說(shuō),我們需要把caffemodel轉(zhuǎn)為coremlmodel格式,對(duì)于 cuDNN和NNAPI,我們需要解析caffemodel,然后自己組裝出完整的網(wǎng)絡(luò)模型。這個(gè)過(guò)程繁瑣而且容易出錯(cuò),當(dāng)時(shí)有強(qiáng)烈的沖動(dòng),希望定義一個(gè)統(tǒng)一的模型描述格式,所有的訓(xùn)練框架訓(xùn)練所得的網(wǎng)絡(luò)模型,都是用這個(gè)格式來(lái)描述,在設(shè)備上部署推理時(shí),相應(yīng)的推理引擎支持解析這個(gè)統(tǒng)一的描述格式,直接完成部署落地,豈不美哉。

當(dāng)然此事并不容易,要定義個(gè)統(tǒng)一的模型描述格式,不僅僅需要對(duì)機(jī)器學(xué)習(xí)技術(shù)有深入的理解,而且將之推廣成為事實(shí)上的行業(yè)標(biāo)準(zhǔn),更需要有很大的行業(yè)影響力,并不是如筆者這樣的無(wú)名小卒可以為之。所幸已經(jīng)有社區(qū)在做這個(gè)事情了,這就是Open Neural Network Exchange(ONNX)。

用ONNX自己的話(huà)來(lái)說(shuō),ONNX是一個(gè)對(duì)計(jì)算網(wǎng)絡(luò)(Computation Graph)的一個(gè)通用描述(Intermediate Representation)。它希望被設(shè)計(jì)成為開(kāi)放的網(wǎng)絡(luò)描述格式,減少開(kāi)發(fā)者在各個(gè)訓(xùn)練和推理框架間切換的代價(jià),可以讓開(kāi)發(fā)者專(zhuān)注于算法和優(yōu)化。雖然ONNX還處于比較早期的階段,不過(guò)已經(jīng)有約來(lái)越多的人開(kāi)始關(guān)注到它,未來(lái)會(huì)有機(jī)會(huì)得到更廣泛的應(yīng)用。

02 計(jì)算模型描述

ONNX有兩個(gè)分類(lèi):基礎(chǔ)的ONNX主要用于描述神經(jīng)網(wǎng)絡(luò)、ONNX-ML是對(duì)基礎(chǔ)ONNX的擴(kuò)展,增加了神經(jīng)網(wǎng)絡(luò)之外的其他機(jī)器學(xué)習(xí)算法的支持。本文不會(huì)涉及ONNX-ML,接下來(lái)的文字以一個(gè)簡(jiǎn)單的ONNX模型為例,介紹一下 ONNX是如何來(lái)描述一個(gè)計(jì)算網(wǎng)絡(luò)的。該模型可以在ONNX的Github上下載(https://github.com/onnx/models/blob/master/vision/classification/mobilenet/model/mobilenetv2-7.onnx).

ONNX的模型描述采用了Google的Protocol Buffer語(yǔ)言。最外層的結(jié)構(gòu)是ModelProto,它的定義如下:

message ModelProto {
  int64 ir_version = 1;
  repeated OperatorSetIdProto opset_import = 8;
  string producer_name = 2;
  string producer_version = 3;
  string domain = 4;
  int64 model_version = 5;
  string doc_string = 6;
  GraphProto graph = 7;
  repeated StringStringEntryProto metadata_props = 14;
  repeated TrainingInfoProto training_info = 20;
  repeated FunctionProto functions = 25;
}

比較重要的字段有:

lr_version : 當(dāng)前的ONNX模型文件的版本,目前發(fā)布的最新版本為IR_VERSION_2019_3_18 = 6. 發(fā)布于2019年,版本7還在制定中。

opset_import: 當(dāng)前的模型文件所依賴(lài)的算子domain和版本。

graph: 這個(gè)模型執(zhí)行的運(yùn)算圖,這個(gè)是最重要的字段。

GraphProto的定義如下:

message GraphProto {
  repeated NodeProto node = 1;
  string name = 2;   // namespace Graph
  repeated TensorProto initializer = 5;
  repeated SparseTensorProto sparse_initializer = 15;
  string doc_string = 10;
  repeated ValueInfoProto input = 11;
  repeated ValueInfoProto output = 12;
  repeated ValueInfoProto value_info = 13;
  repeated TensorAnnotation quantization_annotation = 14;
}

比較重要的字段有:

initializer : 模型的每一網(wǎng)絡(luò)層的參數(shù), 模型訓(xùn)練完成之后參數(shù)就被固定下來(lái)。

input : 模型的輸入格式。

output : 模型的輸出格式。

nodes : 定義了模型的所有運(yùn)算模塊, 依照推理的次序排布。

NodeProto的定義如下:

message NodeProto {
  repeated string input = 1;    // namespace Value
  repeated string output = 2;   // namespace Value
  string name = 3;     // namespace Node
  string op_type = 4;  // namespace Operator
  string domain = 7;   // namespace Domain
  repeated AttributeProto attribute = 5;
  string doc_string = 6;
}

比較重要的字段有:

input : 輸入?yún)?shù)的名字。

output : 輸出參數(shù)的名字,這里需要留意的是,每一個(gè)網(wǎng)絡(luò)層之間的連接使用輸入和輸出的名字來(lái)確立的。

op_type : 算子的類(lèi)型。

attributes : 算子的屬性, 其解析取決于算子的類(lèi)型。

ONNX中最復(fù)雜的部分就是關(guān)于各種算子的描述,這也可以理解,構(gòu)成神經(jīng)網(wǎng)絡(luò)的主體就是這些算子。attributes 就是算子的一組帶名字的屬性。

本文中,我們介紹一個(gè)在mobilenetv2-7.onnx使用最多的算子: conv。

卷積神經(jīng)網(wǎng)絡(luò)在語(yǔ)音,圖像,視頻等處理上獲得了巨大成功. ONNX關(guān)于卷積網(wǎng)絡(luò)層的屬性定義主要有:

dilations: 擴(kuò)展卷積,默認(rèn)為1,即普通卷積。其數(shù)學(xué)定義如下:

1.png

group: 分組卷積, 其定義見(jiàn)文獻(xiàn)14. 默認(rèn)為1, 即不分組。

kernel_shape: 定義了卷積核的大小。

pads: 定義了上下左右填充的像素?cái)?shù)。

strides: 定義了卷積運(yùn)算的步長(zhǎng)。

03 ONNX的支持情況

各家的訓(xùn)練和推理框架還在繼續(xù)發(fā)展,ONNX想成為行業(yè)標(biāo)準(zhǔn)顯然還為時(shí)尚早,但是目前尚沒(méi)有看到其他更好的通用模型描述格式,我們簡(jiǎn)單歸納一下現(xiàn)在的ONNX的支持情況(不完整):

2.png

參考文獻(xiàn)

[1] ONNX: https://github.com/onnx/onnx

[2] TENSORFLOW: https://www.tensorflow.org/

[3] CNTK: https://github.com/Microsoft/CNTK

[4] PYTORCH: https://pytorch.org/

[5] TNN: https://github.com/Tencent/TNN

[6] MNN: https://github.com/alibaba/MNN

[7] CUDNN: https://developer.nvidia.com/zh-cn/cudnn

[8] TENSORRT: https://developer.nvidia.com/zh-cn/tensorrt

[9] COREML: https://developer.apple.com/documentation/coreml

[10] NCNN: https://github.com/Tencent/ncnn

[11] NNAPI: https://developer.android.com/ndk/guides/neuralnetworks

[12] Protocol Buffers: https://developers.google.com/protocol-buffers

[13] Dilated Convolutions https://arxiv.org/abs/1511.07122

[14] Dynamic Group Convolutions https://arxiv.org/abs/2007.04242

*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



關(guān)鍵詞: 深度學(xué)習(xí)

相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉