1. 【pytorch轉onnx】YOLOv3網路pt->onnx
在另外一篇博客中已經寫了,只是在旭日3開發板上實操時用的是另外一個程序,故在此重新記錄一下,詳細轉換過程參考如下鏈接
其中 from nets.yolo import YoloBody 可見 參考鏈接
2. Matlab能導出onnx格式嗎
Matlab能導出onnx格式。
首先打開電腦上的「matlab」軟體,此處以下圖中的代碼為例,繪制出一個三維圖像。meshgrid函數用於生成網格點。可以使用自己喜歡的例子來製作動畫。
在matlab工作輸入:% 11是你保存時的文件名,需要加單引號,否則打不開。特別注意最好將這個文件復制到matlab工作文件夾。
如果你不知道是哪個文件夾,可以看看matlab左邊的窗口,或者按下組合鍵Ctrl+O,或者打開菜單欄上面的Home->open。
優勢特點:
(1) 高效的數值計算及符號計算功能,能使用戶從繁雜的數學運算分析中解脫出來。
(2) 具有完備的圖形處理功能,實現計算結果和編程的可視化。
(3) 友好的用戶界面及接近數學表達式的自然化語言,使學者易於學習和掌握。
(4) 功能豐富的應用工具箱(如信號處理工具箱、通信工具箱等) ,為用戶提供了大量方便實用的處理工具。
3. ONNX簡介
Open Neural Network Exchange(ONNX,開放神經網路交換)格式,是一個用於表示深度學習模型的標准,可使模型在不同框架之間進行轉移。
假設一個場景:現在某組織因為主要開發用TensorFlow為基礎的框架,現在有一個深度演算法,需要將其部署在移動設備上,以觀測變現。傳統地我們需要用caffe2重新將模型寫好,然後再訓練參數;試想下這將是一個多麼耗時耗力的過程。
此時,ONNX便應運而生,Caffe2,PyTorch,Microsoft Cognitive Toolkit,Apache MXNet等主流框架都對ONNX有著不同程度的支持。這就便於了我們的演算法及模型在不同的框架之間的遷移。
開放式神經網路交換(ONNX)是邁向開放式生態系統的第一步,它使AI開發人員能夠隨著項目的發展選擇合適的工具。 ONNX為AI模型提供開源格式。 它定義了可擴展的計算圖模型,以及內置運算符和標准數據類型的定義。 最初的ONNX專注於推理(評估)所需的功能。 ONNX解釋計算圖的可移植,它使用graph的序列化格式。 它不一定是框架選擇在內部使用和操作計算的形式。 例如,如果在優化過程中操作更有效,則實現可以在存儲器中以不同方式表示模型。
ONNX是一個開放式規范,由以下組件組成:
可擴展計算圖模型的定義
標准數據類型的定義
內置運算符的定義
4. ONNX一個溝通各大AI框架的橋梁
ONNX全稱Open Neural Network Exchange,是微軟設計的一個開放式深度學習神經網路模型的格式。旨在通過一個統一的模型格式標准,建立一個強大的人工智慧生態。
深度神經網路的實現是通過數據流圖實現的,數據(張量等)從輸入,流過一個個集選節點,最終在輸出結點得到推理結果。不同的框架實現數據流圖的的方式不盡相同,有的使用靜態圖,有的在運行的過程中動態創建。但是不管哪種方式,最終都會得到一個神經網路模型的結構圖以及權重。通常,神經網路模型的結構、權重等信息不會一直在內存里,通常需要將它們保存到文件中,用於部署、轉換等。而每一種框架都有他們自己的一套專有的模型表示方法,擁有自己的一套標准去操作、運行他們自己的模型。由於AI 研究正在迅猛發展當中,每種框架都有自己的側重點,比如有的框架特別適合於做研究,能夠快速的搭建驗證模型;而有的框架則最特定硬體做了大量性能優化,特別適合生產部署。
這時候,一個通用的模型格式標准應運而生,它就是ONNX。有了這樣一個統一的模型格式標准,你就可以使用能夠快速的框架去驗證你的模型,然後將模型導出到ONNX格式,再用有特殊優化的推理引擎進行推理或者轉換到可以在移動端進行推理的特殊格式。
ONNX還有另一個變種,ONNX-ML,它額外增加了一些傳統的標准機器學習操作。
ONNX是一個開放的標准,這個標准主要有以下三部分組成:
版本號有兩種表示方法:簡單數字表示和語義表示,用8個位元組存儲版本信息。
簡單數字表示全部位元組用於表示一個數,表現形式為XXX,如 0x0000000000000001 表示數字1;語義表示則將這八個位元組分開,最高位兩個位元組表示主版本號,次高位兩個位元組表示此版本好,剩下四個位元組表示補丁、編譯等版本號,最終的表現形式為MAJOR.MINOR.PATCH,例如 0x0001000200000003 表示主版本號為1,此版本號為2,補丁版本號等為3。兩種表示方法的區分方法是查看最高四個位元組內容,如果最高四個位元組為0,則使用的是簡單數字表示;如果最高四個位元組不為零,則使用的是語義表示。例如 0x0000000000000001 最高四個位元組為0,所以表示這個版本號是用簡單數字表示;而 0x000000010000000 最高四個位元組不為0,則表示這是語義版本號。
值得注意的是,ONNX標准中規定,IR和OP的版本號必須用簡單數字來表示,版本數值單調遞增,而對於模型版本,並未作出規定,可以隨意二選一。
處於模型結構頂層的是一個被稱為Model的結構,它的主要目的是將一個包含模型所有執行元素的圖和它的元數據關聯起來。元數據可以在模型被讀取的時候告訴讀取方一些重要信息,比如版本、執行該模型所需要的操作集(Operators Set)等信息,讀取方根據這些信息決定下一步是繼續執行該模型還是選擇報錯等操作。另外,有些工具,例如模型查看工具等可以根據元數據告訴人們模型的信息和模型的作用等。Model的組成結構如下:
每個Model都必須指定它所屬機構的域名,使用類似Java包結構的反向域名表示。此外,Model的 metadata_props 欄位可以用於定義其他額外的元數據信息,例如下表定義了一些額外的元數據屬性:
每個模型必須明確的指出它所以來的操作集,操作集定義了可用的操作以及他們的版本。模型通過他們的域定義了需要導入的操作集,如果沒有特別指定,模型將默認導入默認的ONNX操作集。
操作集的屬性如下:
圖(Graph)中的任何一個操作(Operator)都必須是在模型導入了的操作集中有明確聲明了的。
操作的屬性如下:
圖用於表示一個計算過程,它由元數據欄位、模型參數以及計算結點三部分組成。計算結點按照一定拓撲結構組成了一個有向無環圖,每個結點表示一個操作。每個結點可以有0到多個輸入以及至少一個輸出。
圖的屬性如下:
計算節點由結點名字、這個結點的操作的名字、輸入的名字、輸出的名字以及一系列屬性組成。結點的輸入輸出和操作的輸入輸出通過位置相關聯,例如第一個輸入是上一個結點的輸出,第二個輸入是權重,第三個輸入是偏置等,結點屬性名字和操作屬性通過名字相關聯。
結點屬性如下:
ONNX有兩個變種:ONNX和ONNX-ML。ONNX只識別張量,ONNX-ML除了張量還能識別序列以及字典。
總的來說,ONNX就是定義了一套標准,這套標准使得不同機器學習框架的數據流圖有了一個統一的表示。
它定義了如何將一個內存的模型序列化到磁碟,也定義了如何去讀取這個序列化的模型進入內存。
[1] Open Neural Network Exchange - ONNX
5. Pytorch導出ONNX踩坑指南
相對與ONNX模型,Pytorch模型經常較為鬆散,API的限制也往往較為寬松。因此,在導出的過程中,不可避免地會遇到導出失敗的問題。可以預見到,這塊API可能在不久的將來會發生變化。
ONNX導出的基本操作比較簡單。官網上的例子是:
可惜真要這么容易就好了
支持Batching需要制定Dynamic Axes,即可變的維度。
案例:
keep_initializers_as_inputs 這個參數是False的情況下,在Caffe2中報錯:IndexError: _Map_base::at. 參考 https://github.com/onnx/onnx/issues/2458
問題比較復雜。貌似tensorflow也有類似問題。導出時添加參數do_constant_folding=True或許可以解決。
參考 https://github.com/NVIDIA/triton-inference-server/issues/1080
定長list會導出為一個tuple
Pytorch 1.4,ONNX 9不支持變長List的導出。之後的Pytorch版本有支持,需要更高版本的ONNX
Pytorch中,Expand未改動的dim可以指定為-1,導出到ONNX中時,需要手動指定每個dim的值。如:
Pytorch中,Squeeze一個不為1維的dim不會有任何效果。ONNX會報錯
6. ONNX 開始
給出些 ONNX 模型使用的示例方法。
此為修改模型的。如果要修改某節點的,見參考 onnx_cut.py 的 _onnx_specify_shapes() 。
指明模型輸入維度後,可自動推理後續節點的維度。
輔助找出指定名稱的圖屬性。
輔助找出指定輸入名稱的節點列表。輸出同樣。
輔助找出圖某屬性所在列表位置。
輔助找出某區間的節點字典。
替換或修改某個節點的過程。
模型運行推理,得到輸出的過程。