大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
基于libonnx环境简要分析一下mnist网络算子结构,关于环境搭建可以参考前面两篇文章:
本文主要目的是搞清楚mnist各层之间数据shape的变化情况,关于什么是shape,引用一本书中的介绍:
“在tensorflow中,使用张量来表示计算图中的所有数据,张量在计算图的节点之间流动,张量可以看成N维数组,而数组的维数就是张量的阶数。因此,0阶张量对应标量数据,1阶张量对应一维数组,也就是向量。二阶张量对应二维数组,也就是矩阵,以此类推,N阶张量对应n维数组,例如,一张RGB图像可以表示为3阶张量,而多张RGB图构成的数据可以表示为4阶张量。shape(形状)代表的就是张量的一种属性,当然还有其他属性,比如数据类型等等”
再算子执行前面打断点,依次观察输入数据和输出数据的大小:
(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实现也不例外
结束!
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179595.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...