使用netron对mnist网络结构分析

libonnx解析MNIST模型:数据流与shape变化剖析

基于libonnx环境简要分析一下mnist网络算子结构,关于环境搭建可以参考前面两篇文章:

xboot大神的libonnx环境搭建

使用netron实现对onnx模型结构可视化


本文主要目的是搞清楚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实现也不例外

 

 


结束!

<think>我们被要求使用PyTorch可视化前馈神经网络(FNN)的结构。根据引用[1]和[2],我们知道FNN是一个前向传播的网络,通常由输入层、隐藏层和输出层组成。在PyTorch中,我们可以使用`torchviz`库或`hiddenlayer`库来可视化网络结构,但更常用的是`torchviz`。此外,PyTorch本身也提供了`print(model)`来打印文本结构,但图形化更直观。步骤:1.安装必要的库:`torchviz`和`graphviz`。注意:`graphviz`需要单独安装(从官网下载或使用包管理器)。2.定义模型(这里使用引用[1]中的FNN模型,假设是一个多层感知机)。3.生成一个示例输入,并通过模型进行前向传播。4.使用`torchviz`的`make_dot`函数生成计算图(即模型结构图)。注意:由于引用[1]中的FNN模型代码未给出,我们假设一个简单的FNN结构(例如用于MNIST分类的神经网络)。通常,FNN模型会包含线性层和激活函数。假设模型定义如下(根据引用[1]的上下文):```pythonimporttorch.nnas nnclassFNN(nn.Module):def __init__(self,input_size=784, hidden_size=128,num_classes=10):super(FNN,self).__init__()self.fc1 =nn.Linear(input_size,hidden_size)self.relu =nn.ReLU()self.fc2 =nn.Linear(hidden_size, num_classes)defforward(self, x):out =self.fc1(x)out= self.relu(out)out= self.fc2(out)return out```然后,我们使用以下步骤可视化:1.安装库(如果未安装):```bashpip installtorchviz#并且安装graphviz:https://graphviz.org/download/```2.在代码中生成计算图:```pythonimport torchfrom torchviz importmake_dot#创建模型实例model =FNN()#生成一个随机输入(假设输入是28x28的图像,展平为784)x= torch.randn(1,784)#批量大小为1#前向传播y =model(x)#生成计算图dot= make_dot(y,params=dict(model.named_parameters()))#保存为文件(例如PNG)dot.format ='png'dot.render('fnn_model_structure', view=True)```这样就会生成一个名为`fnn_model_structure.png`的文件,并在默认查看器中打开。注意:如果模型复杂,计算图可能会很大。我们可以通过调整`make_dot`的参数(例如只显示特定层)来简化,但通常默认即可。另外,我们也可以使用`hiddenlayer`库,它提供了更简洁的视图。但这里我们使用`torchviz`,因为它直接由PyTorch官方支持。引用[1]中提到了FNN模型,因此我们假设用户已经有一个类似上述的模型定义。如果用户使用的是Jupyter Notebook,可以直接在notebook中显示图形:```pythonfromIPython.display importImagedot= make_dot(y,params=dict(model.named_parameters()))Image(dot.render('fnn_model_structure', format='png'))```另一种方法是使用`netron`库,它支持交互式查看模型结构。但`netron`需要将模型保存为ONNX格式,然后使用netron的web服务或桌面应用打开。导出为ONNX格式:```python#导出模型torch.onnx.export(model,x,"fnn_model.onnx", input_names=['input'],output_names=['output'])```然后,使用netron打开`fnn_model.onnx`文件(需要先安装netron:`pipinstall netron`,然后运行`importnetron; netron.start('fnn_model.onnx')`)。总结,两种方法:1.使用`torchviz`生成静态计算图(包含运算细节)。2.使用`netron`生成交互式模型结构图(更简洁,分层显示)。根据用户需求选择。这里我们主要展示第一种方法。注意:在可视化之前,确保模型定义正确,并且输入数据的维度匹配。由于引用[3]提到的是二分类任务(Moon数据集),如果用户想可视化该任务的模型,只需将输入大小改为2(因为每个样本2个特征),输出大小改为1(二分类)即可。可视化步骤相同。因此,我们给出一个通用的方法。</think>### 在PyTorch中可视化前馈神经网络(FNN)结构的方法 在PyTorch中可视化前馈神经网络(FNN)的结构,可以使用以下三种主要方法,每种方法都有其特点和适用场景: #### 1. 使用`torchsummary`库(文本结构) ```python from torchsummary import summary # 定义模型(参考引用[1]中的FNN结构) model = FNN(input_size=784, hidden_size=128, num_classes=10) # 示例参数 # 打印模型结构 summary(model, input_size=(1, 784)) # MNIST图像输入尺寸 ``` **输出示例**: ``` ---------------------------------------------------------------- Layer (type) Output Shape Param # ================================================================ Linear-1 [-1, 128] 100,480 ReLU-2 [-1, 128] 0 Linear-3 [-1, 10] 1,290 ================================================================ Total params: 101,770 Trainable params: 101,770 Non-trainable params: 0 ---------------------------------------------------------------- ``` **优点**: - 快速查看各层参数和输出尺寸 - 无需额外安装复杂依赖(仅需`pip install torchsummary`) #### 2. 使用`torchviz`生成计算图(可视化) ```python import torch from torchviz import make_dot # 创建示例输入 x = torch.randn(1, 784) # 批量大小1,输入尺寸784 # 前向传播(参考引用[2]原理) y = model(x) # 前馈计算 # 生成可视化图 dot = make_dot(y, params=dict(model.named_parameters())) dot.render('fnn_architecture', format='png') # 保存为PNG ``` **效果**: - 生成计算图显示数据流动路径 - 清晰展示各层连接关系和参数依赖 - 需要安装`graphviz`(`pip install torchviz graphviz`) #### 3. 使用TensorBoard可视化(交互式) ```python from torch.utils.tensorboard import SummaryWriter # 创建TensorBoard记录器 writer = SummaryWriter() # 添加模型图 dummy_input = torch.rand(1, 784) # 虚拟输入 writer.add_graph(model, dummy_input) writer.close() # 关闭写入器 ``` **使用步骤**: 1. 运行代码生成日志文件 2. 终端执行:`tensorboard --logdir=runs` 3. 浏览器打开`localhost:6006`查看交互式结构图 **优势**: - 交互式探索网络结构 - 支持节点展开/折叠 - 与训练监控无缝集成 #### 4. 使用Netron(独立工具) 1. 导出模型为ONNX格式: ```python torch.onnx.export(model, dummy_input, "fnn_model.onnx", input_names=['input'], output_names=['output']) ``` 2. 打开[Netron官网](https://netron.app/)上传ONNX文件 3. 获得交互式网络结构图 **特点**: - 无需安装本地软件 - 支持层类型和参数检查 - 跨平台使用 ### 选择建议 - **快速调试**:使用`torchsummary` - **发表论文/报告**:使用`torchviz`生成高质量矢量图 - **教学/演示**:使用TensorBoard交互式探索 - **模型分析**:使用Netron检查层细节 > 这些可视化方法帮助理解前馈神经网络中数据从输入层流向输出层的过程(参考引用[2]),以及参数在反向传播中的更新路径[^2]。对于Moon数据集等二分类任务(引用[3]),可视化可验证网络是否匹配输入特征维度[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值