323 Star 984 Fork 98

MindSpore / mindinsight

Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
Clone or download
README_CN.md 17.54 KB
Copy Edit Web IDE Raw Blame History

MindConverter教程

Switch to English version

概述

MindConverter是一款用于将PyTorch、TensorFlow脚本或者ONNX文件转换到MindSpore脚本的工具。结合转换报告的信息,用户只需对转换后的脚本进行微小的改动,即可快速将PyTorch、TensorFlow框架的模型脚本或者ONNX文件迁移到MindSpore。

安装

此工具为MindInsight的子模块,安装MindInsight后,即可使用MindConverter,MindInsight安装请参考该安装文档

三方库依赖

下列三方库未在MindInsight依赖列表(requirements.txt)中声明。用户除安装可满足模型加载、训练、推理的TensorFlow外,还需要安装(pip install)如下依赖库(ONNX模型文件转MindSpore的用户无需安装tf2onnx):

onnx>=1.8.0
tf2onnx>=1.7.1
onnxruntime>=1.5.2
onnxoptimizer>=0.1.2

对于个别模型,若在转换过程中出现onnx或tf2onnx错误信息,请尝试更新环境中onnx或tf2onnx或onnxoptimizer至最新版本。

用法

MindConverter提供命令行(Command-line interface, CLI)的使用方式,命令如下。

usage: mindconverter [-h] [--version] [--in_file IN_FILE]
                     [--model_file MODEL_FILE] [--shape SHAPE [SHAPE ...]]
                     [--input_nodes INPUT_NODES [INPUT_NODES ...]]
                     [--output_nodes OUTPUT_NODES [OUTPUT_NODES ...]]
                     [--output OUTPUT] [--report REPORT]

optional arguments:
  -h, --help            show this help message and exit
  --version             show program version number and exit
  --in_file IN_FILE     Specify path for script file to use AST schema to do
                        script conversation.
  --model_file MODEL_FILE
                        Tensorflow(.pb) or ONNX(.onnx) model file path is
                        expected to do script generation based on graph
                        schema. When `--in_file` and `--model_file` are both
                        provided, use AST schema as default.
  --shape SHAPE [SHAPE ...]
                        Expected input tensor shape of `--model_file`. It is
                        required when use graph based schema. Both order and
                        number should be consistent with `--input_nodes`.
                        Given that (1,128) and (1,512) are shapes of input_1
                        and input_2 separately. Usage: --shape 1,128 1,512
  --input_nodes INPUT_NODES [INPUT_NODES ...]
                        Input node(s) name of `--model_file`. It is required
                        when use graph based schema. Both order and number
                        should be consistent with `--shape`. Given that both
                        input_1 and input_2 are inputs of model. Usage:
                        --input_nodes input_1 input_2
  --output_nodes OUTPUT_NODES [OUTPUT_NODES ...]
                        Output node(s) name of `--model_file`. It is required
                        when use graph based schema. Given that both output_1
                        and output_2 are outputs of model. Usage:
                        --output_nodes output_1 output_2
  --output OUTPUT       Optional, specify path for converted script file
                        directory. Default output directory is `output` folder
                        in the current working directory.
  --report REPORT       Optional, specify report directory. Default is
                        converted script directory.

PyTorch模型脚本迁移

MindConverter仅提供使用AST进行PyTorch模型脚本迁移方案:

基于抽象语法树(Abstract syntax tree, AST)的脚本转换:指定--in_file的值,将使用基于AST的脚本转换方案;

若同时指定了--in_file--model_file将默认使用AST方案进行脚本迁移。

其中,--output--report参数可省略。若省略,MindConverter将在当前工作目录(Working directory)下自动创建output目录,将生成的脚本、转换报告输出至该目录。

若需要基于图模式进行PyTorch模型脚本迁移,建议将PyTorch模型转换为ONNX之后,使用ONNX文件进行模型模型脚本迁移,详情见 PyTorch使用说明

TensorFlow模型脚本迁移

MindConverter提供基于图结构的脚本生成方案:指定--model_file--shape--input_nodes--output_nodes进行脚本迁移。

AST方案不支持TensorFlow模型脚本迁移,TensorFlow脚本迁移仅支持基于图结构的方案。

若省略--output--report参数,MindConverter将在当前工作目录(Working directory)下自动创建output目录,将生成的脚本、转换报告、权重文件、权重映射表输出至该目录。

ONNX模型文件迁移

MindConverter提供基于图结构的脚本生成方案:指定--model_file--shape--input_nodes--output_nodes进行脚本迁移。

AST方案不支持ONNX模型文件迁移,ONNX文件迁移仅支持基于图结构的方案。

若省略--output--report参数,MindConverter将在当前工作目录(Working directory)下自动创建output目录,将生成的脚本、转换报告、权重文件、权重映射表输出至该目录。

使用场景

MindConverter提供两种技术方案,以应对不同脚本迁移场景:

  1. 用户希望迁移后脚本保持原脚本结构(包括变量、函数、类命名等与原脚本保持一致)。
  2. 用户希望迁移后脚本保持较高的转换率,尽量少的修改、甚至不需要修改,即可实现迁移后模型脚本的执行。

对于上述第一种场景,推荐用户使用基于AST的方案进行转换(AST方案仅支持PyTorch脚本转换),AST方案通过对原PyTorch脚本的抽象语法树进行解析、编辑,将其替换为MindSpore的抽象语法树,再利用抽象语法树生成代码。理论上,AST方案支持任意模型脚本迁移,但语法树解析操作受原脚本用户编码风格影响,可能导致同一模型的不同脚本最终的转换率存在一定差异。

对于上述第二种场景,推荐用户使用基于图结构的脚本生成方案,计算图作为一种标准的模型描述语言,可以消除用户代码风格多样导致的脚本转换率不稳定的问题。在已支持算子的情况下,该方案可提供优于AST方案的转换率。

目前已基于典型图像分类网络对图结构的脚本转换方案进行测试。

  1. 基于图结构的脚本生成方案,由于要以推理模式加载ONNX,TensorFlow模型,会导致转换后网络中Dropout算子丢失,需要用户手动补齐。
  2. 基于图结构的脚本生成方案持续优化中。

支持的模型列表(如下模型已基于x86 Ubuntu发行版,PyTorch 1.5.0以及TensorFlow 1.15.0测试通过)

使用示例

基于AST的脚本转换示例

若用户希望使用基于AST的方案进行脚本迁移,假设原PyTorch脚本路径为/home/user/model.py,希望将脚本输出至/home/user/output,转换报告输出至/home/user/output/report ,则脚本转换命令为:

mindconverter --in_file /home/user/model.py \
              --output /home/user/output \
              --report /home/user/output/report

转换报告中,对于未转换的代码行形式为如下,其中x, y指明的是原PyTorch脚本中代码的行、列号。对于未成功转换的算子,可参考MindSporeAPI映射查询功能 手动对代码进行迁移。对于工具无法迁移的算子,会保留原脚本中的代码。

line x:y: [UnConvert] 'operator' didn't convert. ...

转换报告示例如下所示:

 [Start Convert]
 [Insert] 'import mindspore.ops.operations as P' is inserted to the converted file.
 line 1:0: [Convert] 'import torch' is converted to 'import mindspore'.
 ...
 line 157:23: [UnConvert] 'nn.AdaptiveAvgPool2d' didn't convert. Maybe could convert to mindspore.ops.operations.ReduceMean.
 ...
 [Convert Over]

对于部分未成功转换的算子,报告中会提供修改建议,如line 157:23,MindConverter建议将torch.nn.AdaptiveAvgPool2d 替换为mindspore.ops.operations.ReduceMean

基于图结构的脚本生成示例

TensorFlow模型脚本生成示例

使用TensorFlow模型脚本迁移,需要先将TensorFlow模型导出为pb格式,并且获取模型输入节点、输出节点名称。TensorFlow pb模型导出可参考TensorFlow Pb模型导出

假设输入节点名称为input_1:0、输出节点名称为predictions/Softmax:0,模型输入样本尺寸为1,224,224,3,模型绝对路径为/home/user/xxx/frozen_model.pb,希望将脚本、权重文件输出至/home/user/output,转换报告以及权重映射表输出至/home/user/output/report,则脚本生成命令为:

mindconverter --model_file /home/user/xxx/frozen_model.pb --shape 1,224,224,3 \
              --input_nodes input_1:0 \
              --output_nodes predictions/Softmax:0 \
              --output /home/user/output \
              --report /home/user/output/report

执行该命令,MindSpore代码文件、权重文件、权重映射表和转换报告生成至相应目录。

由于基于图结构方案属于生成式方法,转换过程中未参考原TensorFlow脚本,因此生成的转换报告中涉及的代码行、列号均指生成后脚本。

另外对于未成功转换的算子,在代码中会相应的标识该节点输入、输出Tensor的shape(以input_shape, output_shape 标识),便于用户手动修改。以Reshape算子为例,将生成如下代码:

class Classifier(nn.Cell):

    def __init__(self):
        super(Classifier, self).__init__()
        ...
        self.reshape = onnx.Reshape(input_shape=(1, 1280, 1, 1),
                                    output_shape=(1, 1280))
        ...

    def construct(self, x):
        ...
        # Suppose input of `reshape` is x.
        reshape_output = self.reshape(x)
        ...

通过input_shapeoutput_shape参数,用户可以十分便捷地完成算子替换,替换结果如下:

from mindspore.ops import operations as P

...


class Classifier(nn.Cell):

    def __init__(self):
        super(Classifier, self).__init__()
        ...
        self.reshape = P.Reshape(input_shape=(1, 1280, 1, 1),
                                 output_shape=(1, 1280))
        ...

    def construct(self, x):
        ...
        # Suppose input of `reshape` is x.
        reshape_output = self.reshape(x, (1, 1280))
        ...

其中--output--report参数可省略,若省略,该命令将在当前工作目录(Working directory)下自动创建output目录,将生成的脚本、权重文件、权重映射表、转换报告输出至该目录。

权重映射表示例如下所示:

{
  "resnet50": [
    {
      "converted_weight": {
        "name": "conv2d_0.weight",
        "shape": [
          64,
          3,
          7,
          7
        ],
        "data_type": "Float32"
      },
      "source_weight": {
        "name": "conv1.weight",
        "shape": [
          64,
          3,
          7,
          7
        ],
        "data_type": "float32"
      }
    }
  ]
}

映射表中分别保存算子在MindSpore中的权重信息(converted_weight)和在原始框架中的权重信息(source_weight)。

ONNX模型文件生成示例

使用ONNX模型文件迁移,需要先从.onnx文件中获取模型输入节点、输出节点名称。获取ONNX模输入、输出节点名称,可使用 Netron 工具查看。

假设输入节点名称为input_1:0、输出节点名称为predictions/Softmax:0,模型输入样本尺寸为1,3,224,224,则可使用如下命令进行脚本生成:

mindconverter --model_file /home/user/xxx/model.onnx --shape 1,3,224,224 \
              --input_nodes input_1:0 \
              --output_nodes predictions/Softmax:0 \
              --output /home/user/output \
              --report /home/user/output/report

执行该命令,MindSpore代码文件、权重文件、权重映射表和转换报告生成至相应目录。

由于基于图结构方案属于生成式方法,转换过程中未参考ONNX文件,因此生成的转换报告中涉及的代码行、列号均指生成后脚本。

另外,对于未成功转换的算子,在代码中会相应的标识该节点输入、输出Tensor的shape(以input_shapeoutput_shape标识),便于用户手动修改,示例见TensorFlow模型脚本生成示例

注意事项

  1. TensorFlow不作为MindInsight明确声明的依赖库。若想使用基于图结构的脚本生成工具,需要用户手动安装TensorFlow。
  2. 脚本转换工具本质上为算子驱动,对于MindConverter未维护的ONNX算子与MindSpore算子映射,将会出现相应的算子无法转换的问题,对于该类算子,用户可手动修改,或基于MindConverter实现映射关系,向MindInsight仓库贡献。
  3. 在使用基于计算图的迁移时,MindConverter会根据--shape参数将模型输入的批次大小(batch size)、句子长度(sequence length)、图片尺寸(image shape)等尺寸相关参数固定下来,用户需要保证基于MindSpore重训练、推理时输入shape与转换时一致;若需要调整输入尺寸,请重新指定--shape进行转换或修改转换后脚本中涉及张量尺寸变更操作相应的操作数。
  4. 脚本文件和权重文件输出于同一个目录下,转换报告和权重映射表输出于同一个目录下。
  5. 模型文件的安全性与一致性请用户自行保证。

AST方案不支持场景

场景1

部分类和方法目前无法转换:

  1. 使用torch.Tensorshapendimdtype成员;
  2. torch.nn.AdaptiveXXXPoolXdtorch.nn.functional.adaptive_XXX_poolXd()
  3. torch.nn.functional.Dropout
  4. torch.unsqueeze()torch.Tensor.unsqueeze()
  5. torch.chunk()torch.Tensor.chunk()

场景2

继承的父类是nn.Module的子类。

例如:(如下代码片段摘自torchvision.models.mobilenet)

from torch import nn


class ConvBNReLU(nn.Sequential):
    def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1):
        padding = (kernel_size - 1) // 2
        super(ConvBNReLU, self).__init__(
            nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False),
            nn.BatchNorm2d(out_planes),
            nn.ReLU6(inplace=True)
        )

常见问题

Q1. terminate called after throwing an instance of 'std::system_error', what(): Resource temporarily unavailable, Aborted (core dumped):

答: 该问题由TensorFlow导致。脚本转换时,需要通过TensorFlow库加载TensorFlow的模型文件,此时TensorFlow会申请相关资源进行初始化,若申请资源失败(可能由于系统进程数超过Linux最大进程数限制),TensorFlow C/C++层会出现Core Dumped问题。详细信息请参考TensorFlow官方ISSUE,如下ISSUE仅供参考:TF ISSUE 14885, TF ISSUE 37449

Q2. MindConverter是否可以在ARM平台运行?

答:MindConverter同时支持X86、ARM平台,若在ARM平台运行需要用户自行安装模型所需的依赖包和运行环境。

Q3. 为什么使用MindConverter进行模型转换需要很长时间(超过十分钟),而模型并不大?

答:MindConverter进行转换时,需要使用Protobuf对模型文件进行反序列化,请确保Python环境中安装的Protobuf采用C++后端实现,检查方法如下,若输出为python,则需要安装采用C++实现的Python Protobuf(下载Protobuf源码并进入源码中的python子目录,使用python setup.py install --cpp_implementation进行安装);若输出为cpp,转换过程仍耗时较长,请在转换前使用添加环境变量export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp

from google.protobuf.internal import api_implementation

print(api_implementation.Type())

附录

TensorFlow Pb模型导出

使用Keras构建模型的用户,可尝试如下方法进行导出。

MindConverter错误码速查表

MindConverter错误码定义,请参考链接

Python
1
https://gitee.com/mindspore/mindinsight.git
git@gitee.com:mindspore/mindinsight.git
mindspore
mindinsight
mindinsight
master

Search