Netron研究
一、简介
Netron是微软lutzroeder开源的一款软件,是一种神经网络,深度学习和机器学习模型的可视化工具。
Netron支持部分主流深度学习框架的模型,如下所示:
- ONNX (.onnx, .pb, .pbtxt)
- Keras (.h5, .keras)
- Core ML (.mlmodel)
- Caffe (.caffemodel, .prototxt)
- Caffe2 (predict_net.pb)
- Darknet (.cfg)
- MXNet (.model, -symbol.json)
- Barracuda (.nn)
- ncnn (.param)
- Tengine (.tmfile)
- TNN (.tnnproto)
- UFF (.uff)
- TensorFlow Lite (.tflite)
实验性支持以下模型:
- TorchScript (.pt, .pth)
- PyTorch (.pt, .pth)
- Torch (.t7)
- Arm NN (.armnn)
- BigDL (.bigdl, .model)
- Chainer (.npz, .h5)
- CNTK (.model, .cntk)
- Deeplearning4j (.zip)
- MediaPipe (.pbtxt)
- ML.NET (.zip)
- MNN (.mnn)
- PaddlePaddle (.zip, model)
- OpenVINO (.xml)
- scikit-learn (.pkl)
- TensorFlow.js (model.json, .pb)
- TensorFlow (.pb, .meta, .pbtxt, .ckpt, .index)
二、问题和研究方向
本文以Pytroch框架的模型FeatherNet为例。
直接加载的FeatherNetB模型(模型文件中保存了模型结构和模型参数)可视化结果如图1,未展示出详细的模型结构。
图1
针对上述问题,我们从两个方向进行研究:1)在python代码中对Pytorch模型的可视化;2)通过Netron应用程序可视化Pytorch模型。
三、方向一:代码实现pytorch模型可视化
Netron代码可视化端口:http://localhost:8080。首先安装Netron:
pip install netron
3.1 直接加载模型
直接加载FeatherNetB模型,在就会得到上述图1的结果,加载代码如下:
import netron
model_path = './FeatherNetB_total.pth'
netron.start(file=model_path, log=False, browse=True, port=8080, host='localhost')
3.2 先转ONNX模型,再可视化
由于Netron支持ONNX模型,先将模型转为ONNX框架的模型,再进行可视化。如下是具体代码:
import torch
model = FeatherNetB()
d = torch.rand(1, 3, 224, 224)
o = model(d)
onnx_path = "./onnx_FeatherNetB.onnx"
torch.onnx.export(model, d, onnx_path)
import netron
netron.start(file=onnx_path, log=False, browse=True, port=8080, host='localhost')
运行结果如图2所示:
使用以上代码展示Pytorch模型时,注意避开torch.nn.DataParallel等操作(转换成ONNX模型时会报错,如下错误代码)。
ValueError: torch.nn.DataParallel is not supported by ONNX exporter, please use 'attribute' module to unwrap model from torch.nn.DataParallel. Try torch.onnx.export
四、方向二:研究Netron应用程序的源码可视化Pytorch模型
图3
4.1 Netron程序对Pytorch的解析支持较少
在一个神经网络中可能出现的操作有上百种,Netron中对Pytorch模型只简单的解析几种(如下代码),导致出现如图1的结果。
switch (type) {
case 'torch.nn.modules.container.Sequential':
groups.push(key);
inputs = this._loadModule(metadata, value, groups, inputs);
groups.pop(key);
break;
case 'torchvision.models.densenet._Transition':
case 'torchvision.models.resnet.Bottleneck':
case 'torchvision.models.densenet._DenseBlock':
case 'torchvision.models.densenet._DenseLayer':
case 'torchvision.models.inception.BasicConv2d':
case 'torchvision.models.inception.InceptionAux':
case 'torchvision.models.inception.InceptionA':
case 'torchvision.models.inception.InceptionB':
case 'torchvision.models.inception.InceptionC':
case 'torchvision.models.inception.InceptionD':
case 'torchvision.models.inception.InceptionE': {
groups.push(key);
const node = this._createNode(metadata, groups, key, value, inputs, this._littleEndian);
inputs = [ node.name ];
groups.pop(key);
break;
}
default: {
const node = this._createNode(metadata, groups, key, value, inputs);
inputs = [ node.name ];
break;
}
如图4是MobileNet_V1的直接导入可视化的部分结果。
图4
4.2 Pytorch模型文件难以解析
如下代码是FeatherNet模型文件中模型结构的部分内容,很难以键值的方式解析,这给Netron的解析带来很大的干扰。
FeatherNet
qXg D:/宸插畬鎴愰」鐩?韬唤璇佹枃鏈柟鍚戞娴?浠g爜/Face_Spoofing_FeatherNet_0114/OCR_Angle_deploy.pyqX? class FeatherNet(nn.Module):
def __init__(self, n_class=2, input_size=224, se=False, avgdown=False, width_mult=1.):
super(FeatherNet, self).__init__()
block = InvertedResidual
input_channel = 32
last_channel = 1024
self.se = se
self.avgdown = avgdown
interverted_residual_setting = [
# t, c, n, s
[1, 16, 1, 2],
[6, 32, 2, 2], # 56x56
[6, 48, 6, 2], # 14x14
[6, 64, 3, 2], # 7x7
]
# building first layer
assert input_size % 32 == 0
input_channel = int(input_channel * width_mult)
self.last_channel = int(last_channel * width_mult) if width_mult > 1.0 else last_channel
self.features = [conv_bn(3, input_channel, 2)]
# building inverted residual blocks
for t, c, n, s in interverted_residual_setting:
output_channel = int(c * width_mult)
如下为Caffe等的模型部分内容,键值内容清晰明了,方便解析。
name: "ResNet-50"
input: "data"
input_dim: 1
input_dim: 3
input_dim: 224
input_dim: 224
layer {
bottom: "data"
top: "conv1"
name: "conv1"
type: "Convolution"
convolution_param {
num_output: 64
kernel_size: 7
pad: 3
stride: 2
}
}
4.3 解决方案
使用以下代码把Pytorch模型结构转化为ONNX模型结构,并保存:
model = FeatherNetB()
d = torch.rand(1, 3, 224, 224)
o = model(d)
onnx_path = "./onnx_FeatherNetB.onnx"
torch.onnx.export(model, d, onnx_path)
接着使用Netron应用程序直接打开保存的ONNX模型,如图5是mobileNet_V1的通过此方法可视化部分结果。
图5
五、总结以及ailab上如何展示
针对Netron直接可视化Pytroch模型的问题,将Pytorch模型转为ONNX模型,接着使用代码或Netron程序直接可视化即可。
ailab上可视化需先安装Netron(pip install netron),方法:指定转换成的ONNX模型路径,直接使用如下代码可视化即可。实际使用情况需安装验证。
netron.start(file=model_path, log=False, browse=True, port=8080, host='localhost')
六、拓展
目前Caffe、tensorflow框架应用广泛,进行相关实验:
1)Caffe模型可直接可视化,方便好用
2)Netron直接可视化tensorflow模型文件时,花费的时间较长,可尝试将tensorflow转为ONNX、Caffe、ncnn等框架。