使用netron对mnist网络结构分析「建议收藏」
基于libonnx環境簡要分析一下mnist網絡算子結構,關于環境搭建可以參考前面兩篇文章:
xboot大神的libonnx環境搭建
使用netron實現對onnx模型結構可視化
本文主要目的是搞清楚mnist各層之間數據shape的變化情況,關于什么是shape,引用一本書中的介紹:
“在tensorflow中,使用張量來表示計算圖中的所有數據,張量在計算圖的節點之間流動,張量可以看成N維數組,而數組的維數就是張量的階數。因此,0階張量對應標量數據,1階張量對應一維數組,也就是向量。二階張量對應二維數組,也就是矩陣,以此類推,N階張量對應n維數組,例如,一張RGB圖像可以表示為3階張量,而多張RGB圖構成的數據可以表示為4階張量。shape(形狀)代表的就是張量的一種屬性,當然還有其他屬性,比如數據類型等等”
再算子執行前面打斷點,依次觀察輸入數據和輸出數據的大?。?/p>
(gdb) b 2124
Breakpoint 2 at 0x555555560ef8: file onnx.c, line 2124.
(gdb) display n->inputs[0]->ndata
(gdb) display n->outputs[0]->ndata
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 2560
2: n->outputs[0]->ndata = 2560
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 784
2: n->outputs[0]->ndata = 6272
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 6272
2: n->outputs[0]->ndata = 6272
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 6272
2: n->outputs[0]->ndata = 6272
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 6272
2: n->outputs[0]->ndata = 1568
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 1568
2: n->outputs[0]->ndata = 3136
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 3136
2: n->outputs[0]->ndata = 3136
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 3136
2: n->outputs[0]->ndata = 3136
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 3136
2: n->outputs[0]->ndata = 256
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 256
2: n->outputs[0]->ndata = 256
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 256
2: n->outputs[0]->ndata = 10
(gdb) c
Continuing.
Breakpoint 2, onnx_run (ctx=0x555555a501e0) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 10
2: n->outputs[0]->ndata = 10
(gdb) c
Continuing.
可以看出一個簡單的規律,就是前一級網絡的輸出size等于后一級網絡的輸入size.
對照網絡,可以完全對應的上:
將shape打印出(由dims表示),可以看出和上圖完全吻合。(圖中一維向量表示為1*N,也看成2維的shape).
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 2560
2: n->outputs[0]->ndata = 2560
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 2
(gdb) c
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 784
2: n->outputs[0]->ndata = 6272
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb) c
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 6272
2: n->outputs[0]->ndata = 6272
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb) c
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 6272
2: n->outputs[0]->ndata = 6272
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb) c
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 6272
2: n->outputs[0]->ndata = 1568
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb) c
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 1568
2: n->outputs[0]->ndata = 3136
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb)
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 3136
2: n->outputs[0]->ndata = 3136
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb)
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 3136
2: n->outputs[0]->ndata = 3136
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb)
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 3136
2: n->outputs[0]->ndata = 256
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 4
(gdb)
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 256
2: n->outputs[0]->ndata = 256
3: n->inputs[0]->ndim = 4
4: n->outputs[0]->ndim = 2
(gdb)
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 256
2: n->outputs[0]->ndata = 10
3: n->inputs[0]->ndim = 2
4: n->outputs[0]->ndim = 2
(gdb)
Continuing.
Breakpoint 3, onnx_run (ctx=0x5555559ff250) at onnx.c:2124
2124 n->operator(n);
1: n->inputs[0]->ndata = 10
2: n->outputs[0]->ndata = 10
3: n->inputs[0]->ndim = 2
4: n->outputs[0]->ndim = 2
(gdb)
Continuing.
然后再以ndim為上限,索引dims,還是以reshape為例:
可以看出和netron解析的圖中reshape模塊的shape完全吻合:
darknet網絡舉例:
netron不但可以解析onnx格式的模型文件,還支持darknet中 .cfg格式的文件,比如:
不過貌似N,C,W,H的排列有所差別,在上面mnist網絡中,順序是,個數X通道數X長度X高度
而darknet的cfg中,對于輸出數據,是WxHxC的方式,也即是寬X長X通道號,但是對于每個算子節點,則是CXNXWXH的方式,也即是通道數在前,之后依次是個數,寬和長. N是batch size.
從最后一層的模型看不出它的結構,實際上它是一個全連接層:
這一點可以通過芯原的模型轉換工具的轉換結果看出來,芯原的轉換工具,可以將ONNX模型轉換為芯原NPU吃的json文件模型,而netron是支持此類型的可視化輸出的。
以下模型是和上圖同一個模型文件,轉換為芯原格式的JSON模型文件后,通過NETRON分析得到的網絡模型結構,可以看到,最后一層是全連接。
lenet 模型都需要對吃進去的圖像做數據歸一化,libonnx實現也不例外
結束!
總結
以上是生活随笔為你收集整理的使用netron对mnist网络结构分析「建议收藏」的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAD自动保存的图形在哪里?怎么打开复原
- 下一篇: CSS 鼠标样式 cursor属性[通俗