您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關如何解析Pytorch轉ONNX的理論分析,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
(1)Pytorch轉ONNX的意義
一般來說轉ONNX只是一個手段,在之后得到ONNX模型后還需要再將它做轉換,比如轉換到TensorRT上完成部署,或者有的人多加一步,從ONNX先轉換到caffe,再從caffe到tensorRT。原因是Caffe對tensorRT更為友好,這里關于友好的定義后面會談。
因此在轉ONNX工作開展之前,首先必須明確目標后端。ONNX只是一個格式,就和json一樣。只要你滿足一定的規則,都算是合法的,因此單純從Pytorch轉成一個ONNX文件很簡單。但是不同后端設備接受的onnx是不一樣的,因此這才是坑的來源。
Pytorch自帶的torch.onnx.export轉換得到的ONNX,ONNXRuntime需要的ONNX,TensorRT需要的ONNX都是不同的。
這里面舉一個最簡單的Maxpool的例:
Maxunpool可以被看作Maxpool的逆運算,咱們先來看一個Maxpool的例子,假設有如下一個C*H*W的tensor(shape[2, 3, 3]),其中每個channel的二維矩陣都是一樣的,如下所示
在這種情況下,如果我們在Pytorch對它調用MaxPool(kernel_size=2, stride=1,pad=0)
那么會得到兩個輸出,第一個輸出是Maxpool之后的值:
另一個是Maxpool的Idx,即每個輸出對應原來的哪個輸入,這樣做反向傳播的時候就可以直接把輸出的梯度傳給對應的輸入:
細心的同學會發現其實Maxpool的Idx還可以有另一種寫法:
,
即每個channel的idx放到一起,并不是每個channel單獨從0開始。這兩種寫法都沒什么問題,畢竟只要反向傳播的時候一致就可以。
但是當我在支持OpenMMEditing的時候,會涉及到Maxunpool,即Maxpool的逆運算:輸入MaxpoolId和Maxpool的輸出,得到Maxpool的輸入。
Pytorch的MaxUnpool實現是接收每個channel都從0開始的Idx格式,而Onnxruntime則相反。因此如果你希望用Onnxruntime跑一樣的結果,那么必須對輸入的Idx(即和Pytorch一樣的輸入)做額外的處理才可以。換言之,Pytorch轉出來的神經網絡圖和ONNXRuntime需要的神經網絡圖是不一樣的。
(2)ONNX與Caffe
主流的模型部署有兩種路徑,以TensorRT為例,一種是Pytorch->ONNX->TensorRT,另一種是Pytorch->Caffe->TensorRT。個人認為目前后者更為成熟,這主要是ONNX,Caffe和TensorRT的性質共同決定的
上面的表列了ONNX和Caffe的幾點區別,其中最重要的區別就是op的粒度。舉個例子,如果對Bert的Attention層做轉換,ONNX會把它變成MatMul,Scale,SoftMax的組合,而Caffe可能會直接生成一個叫做Multi-Head Attention的層,同時告訴CUDA工程師:“你去給我寫一個大kernel“(很懷疑發展到最后會不會把ResNet50都變成一個層。。。)
tensor i = funcA();
if(i==0)
j = funcB(i);
else
j = funcC(i);
funcD(j);
tensor i = funcA();
coarse_func(tensor i) {
if(i==0) return funcB(i);
else return funcC(i);
}
funcD(coarse_func(i))
以上就是如何解析Pytorch轉ONNX的理論分析,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。