神经网络模型结构和参数可视化
- 一、前言
- 二、Netron
- 2.1Netron简介
- 2.2TensorFlow、Keras、Caffe模型文件实测结果
- 2.3PyTorch、scikit-learn模型文件实测结果
- 三、NN-SVG
- 四、Netscope
- 五、PlotNeuralNet
- 六、Graphviz
- 七、总结
- 参考文档
一、前言
在神经网络的某些应用场景中,需要将设计的网络模型结构绘制出来进行展示,或需要查看训练完成后的模型权重、偏置等参数,而由于使用训练架构的不同某些架构不提供模型可视化功能,这时就需要寻找一些工具达到可视化的目的。
这些工具大体上可分为两种,
(1)能够读取已训练好的神经网络模型,加载模型后会自动显示出模型结构、参数等信息;
(2)无法读取模型文件,需要额外提供如网络结构、权重数值等参数才能绘制出相应的模型结构,显然此种只能用于绘制结构而无法查看模型参数。
二、Netron
2.1Netron简介
Netron属于第一种能够直接读取模型文件的可视化工具,工具提供网页版和客户端版,支持Linux和Windows,网页版地址为https://netron.app/,客户端版地址为https://github.com/lutzroeder/netron/releases,目前最新版为7.6.8。
源码地址为https://github.com/lutzroeder/netron,经页面介绍可知,Netron支持大部分训练架构导出的模型格式,包括以下几种:
2.2TensorFlow、Keras、Caffe模型文件实测结果
经过实际测试,Netron可以正常显示TensorFlow、Keras、Caffe模型结构和参数,模型图如下:
TensorFlow模型文件:
Keras模型文件:
Caffe模型文件:
2.3PyTorch、scikit-learn模型文件实测结果
打开PyTorch模型文件,可以查看参数,但结构信息无法完全显示,模型图如下:
打开scikit-learn模型文件,可以查看参数,但是不显示结构信息,模型图如下:
综合来看,Netron功能强大,支持查看大多数类型的模型文件参数,但在模型结构可视化上还存在些不足。
三、NN-SVG
NN-SVG属于第二种工具,无法加载模型文件,只能通过设置一些参数实现模型结构的绘制。NN-SVG只有网页版,地址为https://alexlenail.me/NN-SVG/,没有客户端版。源码地址为https://github.com/alexlenail/NN-SVG。
NN-SVG支持绘制FCNN、LeNet、AlexNet三种模型结构,结构参数通过界面而非代码设置,较其他同类工具操作更为便捷。
四、Netscope
Netscope与NN-SVG类似,同属第二种工具,但不同的是网络结构由代码进行定义,所以支持多种网络结构。Netscope通过网页提供服务,可以在线使用,也可以下载源代码后本地部署网络服务使用,在线版地址为:https://dgschwend.github.io/netscope/quickstart.html,源代码地址为:https://github.com/cwlacewe/netscope。
进入在线版网页后,点击Launch Editor,在左上方输入代码。
绘制全连接神经网络结构代码如下:
name: "FCNN"layer {name: "input"type: "Input"top: "data"input_param { shape: { dim: 1 dim: 3 dim: 1 dim: 1} }
}layer {name: "fc1"type: "InnerProduct"bottom: "data"top: "fc1"inner_product_param { num_output: 10 }
}layer {name: "relu1"type: "ReLU"bottom: "fc1"top: "fc1"
}layer {name: "fc2"type: "InnerProduct"bottom: "fc1"top: "fc2"inner_product_param { num_output: 15 }
}layer {name: "relu2"type: "ReLU"bottom: "fc2"top: "fc2"
}layer {name: "fc3"type: "InnerProduct"bottom: "fc2"top: "fc3"inner_product_param { num_output: 5 }
}layer {name: "softmax"type: "Softmax"bottom: "fc3"top: "softmax"
}
全连接神经网络结构图如下:
Netscope还会给出关于网络模型的分析,如下图:
Netscope由于使用代码定义模型结构,所以能够描绘的网络模型种类多于NN-SVG,信息也更为详细,但采用简易的二维模块框进行模型结构绘制,美观度上似乎略低于NN-SVG。
五、PlotNeuralNet
PlotNeuralNet,属于第二种工具,工作原理为通过python代码生成LaTeX文档,再由MikTeX软件对文档进行解析生成PDF格式的模型结构图。
PlotNeuralNet源代码地址为:https://github.com/HarisIqbal88/PlotNeuralNet,
MikTeX软件地址为:https://miktex.org/download。
使用时先将源代码下载到本地,然后参照给出的示例编写模型结构定义代码,运行代码生成LaTeX文档,使用MikTeX软件解析文档生成模型结构图。
下面为绘制LeNet模型的代码:
import sys
sys.path.append('../')
from pycore.tikzeng import *def to_FullyConnected(name, s_filer, offset="(0,0,0)", to="(0,0,0)", width=1, height=1, depth=1, caption=" "):return to_Conv(name, s_filer, s_filer, offset, to, width, height, depth, caption)# Define the architecture
arch = [to_head('..'),to_cor(),to_begin(),# Input layerto_input("../examples/fcn8s/cats.jpg", width=6, height=6, name="input"),# Convolutional Layer 1to_Conv(name='conv1', s_filer=28, n_filer=6, offset="(0,0,0)", to="(0,0,0)", width=2, height=28, depth=28, caption="Conv1"),to_Pool(name="pool1", offset="(0,0,0)", to="(conv1-east)", width=1, height=14, depth=14, caption="Pool1"),# Convolutional Layer 2to_Conv(name='conv2', s_filer=10, n_filer=16, offset="(2,0,0)", to="(pool1-east)", width=3, height=10, depth=10, caption="Conv2"),to_Pool(name="pool2", offset="(0,0,0)", to="(conv2-east)", width=1, height=5, depth=5, caption="Pool2"),# Fully Connected Layersto_FullyConnected(name="fc1", s_filer=120, offset="(2,0,0)", to="(pool2-east)", width=1, height=5, depth=5, caption="FC1"),to_FullyConnected(name="fc2", s_filer=84, offset="(1.5,0,0)", to="(fc1-east)", width=1, height=4, depth=4, caption="FC2"),# Output Layerto_SoftMax(name="output", s_filer=10, offset="(2,0,0)", to="(fc2-east)", width=1, height=3, depth=3, caption="Output"),# Connectionsto_connection("conv1", "pool1"),to_connection("pool1", "conv2"),to_connection("conv2", "pool2"),to_connection("pool2", "fc1"),to_connection("fc1", "fc2"),to_connection("fc2", "output"),to_end()
]def main():namefile = str(sys.argv[0]).split('.')[0]to_generate(arch, namefile + '.tex')if __name__ == '__main__':main()
下图为LeNet模型图:
下图为NN-SVG生成的LeNet模型图:
与NN-SVG相比,PlotNeuralNet生成的图片为三维立体,颜色更为鲜艳,但使用代码进行模型结构定义,操作上不如NN-SVG直观,且无法绘制全连接型神经网络。
六、Graphviz
Graphviz (Graph Visualization Software) 是一个由AT&T实验室启动的开源工具包,使用dot语言描述图形结构,可以绘制有向图、无向图、流程图、组织结构图等图形。本文基于python使用graphviz工具包,Graphviz官网地址为:https://graphviz.org/,python-graphviz库源代码地址为:https://github.com/xflr6/graphviz。
使用方法如下:
首先使用pip命令安装graphviz库:
pip install graphviz
然后从Graphviz官网下载graphviz包,下载地址为https://graphviz.org/download/,本文下载的版本为Windows——graphviz-11.0.0 (64-bit) ZIP archive [sha256] (contains all tools and libraries)。下载后解压,然后将“解压路径/Graphviz-11.0.0-win64/bin”添加至环境变量中的path变量。
执行完上面两步,就可以编写python代码定义模型结构。
下面是绘制全连接神经网络的代码:
from graphviz import Digraph
def draw_FCNN():# 创建有向图对象dot = Digraph(engine='neato')# 定义神经网络层及其节点input_nodes = ['x1', 'x2', 'x3']hidden_nodes = ['h1', 'h2']output_nodes = ['o1']# 设置节点的位置input_positions = {'x1': '0,4!', 'x2': '0,2!', 'x3': '0,0!'}hidden_positions = {'h1': '2,3!', 'h2': '2,1!'}output_position = {'o1': '4,2!'}# 定义权重和阈值(示例)weights = {('x1', 'h1'): 0.2, ('x1', 'h2'): 0.4,('x2', 'h1'): 0.3, ('x2', 'h2'): 0.5,('x3', 'h1'): 0.1, ('x3', 'h2'): 0.2,('h1', 'o1'): 0.6, ('h2', 'o1'): 0.7}biases = {'h1': 0.1, 'h2': 0.2, 'o1': 0.3}# 添加节点并设置位置和标签for node, pos in input_positions.items():dot.node(node, label=node, shape='circle', width='1.0', style='filled', fillcolor='lightblue', pos=pos)for node, pos in hidden_positions.items():label = f'{node}\n(b={biases[node]})'dot.node(node, label=label, shape='circle', width='1.0', style='filled', fillcolor='lightgreen', pos=pos)for node, pos in output_position.items():label = f'{node}\n(b={biases[node]})'dot.node(node, label=label, shape='circle', width='1.0', style='filled', fillcolor='lightcoral', pos=pos)# 添加边及其权重for (start, end), weight in weights.items():dot.edge(start, end, label=f'w={weight}')# 渲染图表dot.render('simple_nn_pos', format='png', view=True)draw_FCNN()
下图为绘制的全连接神经网络结构图:
下面是绘制LeNet网络结构的代码:
from graphviz import Digraph
def draw_LeNet():# 创建一个有向图对象dot = Digraph()dot.attr(rankdir='LR')dot.attr('node', shape='box3d', style='filled', fillcolor='lightblue', fontname='Helvetica')dot.attr('edge', arrowhead='vee', color='blue')# 添加节点dot.node('I', 'Input Layer\n(28x28x1)')dot.node('C1', 'Conv Layer 1\n(24x24x6)\n5x5 kernels')dot.node('P1', 'Pool Layer 1\n(12x12x6)\n2x2 avg pool')dot.node('C2', 'Conv Layer 2\n(8x8x16)\n5x5 kernels')dot.node('P2', 'Pool Layer 2\n(4x4x16)\n2x2 avg pool')dot.node('F1', 'Fully Connected Layer 1\n(120)')dot.node('F2', 'Fully Connected Layer 2\n(84)')dot.node('O', 'Output Layer\n(10)')# 添加边dot.edge('I', 'C1')dot.edge('C1', 'P1')dot.edge('P1', 'C2')dot.edge('C2', 'P2')dot.edge('P2', 'F1')dot.edge('F1', 'F2')dot.edge('F2', 'O')# 保存并渲染图表,同时删除中间文件dot.render('lenet_structure', format='png', view=True, cleanup=True)draw_LeNet()
下图为LeNet网络结构图:
graphviz的参数释义可参照官网介绍,官网上内容较为详细,其中比较重要的一些参数如下:
1、布局引擎的指定
graphviz默认引擎为dot,在默认引擎下,会自动调整节点间距、连接线形状等参数,使用控制间距的nodesep参数起到的作用有限,当节点较多时可能会引起布局混乱。
可通过如下代码指定引擎为neato,在该引擎下可以进行节点精确定位
dot = Digraph(engine='neato')
2、pos
该参数用于指定节点的位置,但在默认引擎下不会起作用,要使该参数生效,可指定引擎为neato,此时单位为英寸。另外,如果pos设置后整体布局四周出现留白,那么引擎会自动消除留白使空间布局更加合理。
3、width、height
这两个参数指定节点的高度和宽度,单位为英寸。如果设置的过小,那么节点可能会显示为实际大小而非设置的大小。
4、dpi
该参数在graphviz中是指每英寸多少个像素,所以dpi设置的越大,得到的图像更清晰。
下面代码就是设置dpi为600。
dot.attr(dpi='600')
5、size
该参数是设置生成的图像的宽度和高度,单位为英寸。当图像的实际大小小于该参数时会按照实际大小保存,大于该参数时则会被缩放。
下面代码就是设置图像宽度为10英寸,高度为20英寸。
dot.attr(size='10,20')
对于绘制的全连接型神经网络,graphviz绘制的网络外观上优于NN-SVG,而且可以显示权重、偏置阈值,这个优点很突出。
对于绘制的LeNet模型,美观程度与NN-SVG各有优劣,但是略低于PlotNeuralNet。
七、总结
综合上述几种神经网络模型结构可视化工具的实际测试,汇总如下:
应用场景 | 适合工具 |
---|---|
查看模型内部参数 | Netron |
绘制全连接神经网络——要求显示权重等参数 | Graphviz |
绘制全连接神经网络——美观优先 | Graphviz>NN-SVG |
绘制全连接神经网络——速度优先 | NN-SVG>Graphviz |
绘制其他神经网络——美观优先 | PlotNeuralNet>NN-SVG>Graphviz>Netron>Netscope |
绘制其他神经网络——速度优先 | NN-SVG>Netron>Netscope>Graphviz>PlotNeuralNet |
参考文档
神经网络可视化(一)——Netron
一图抵千言 | 神经网络绘图篇!涵盖NN-SVG、PlotNeuralNet、Netron等软件!
PlotNeuralNet简单教程
如何画出漂亮的神经网络图?