You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

README_CN.md 20 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. # MindConverter教程
  2. [Switch to English version](./README.md)
  3. <!-- TOC -->
  4. - [MindConverter教程](#mindconverter教程)
  5. - [概述](#概述)
  6. - [安装](#安装)
  7. - [用法](#用法)
  8. - [PyTorch模型脚本迁移](#pytorch模型脚本迁移)
  9. - [TensorFlow模型脚本迁移](#tensorflow模型脚本迁移)
  10. - [ONNX模型文件迁移](#onnx模型文件迁移)
  11. - [使用场景](#使用场景)
  12. - [使用示例](#使用示例)
  13. - [基于AST的脚本转换示例](#基于ast的脚本转换示例)
  14. - [基于图结构的脚本生成示例](#基于图结构的脚本生成示例)
  15. - [PyTorch模型脚本生成示例](#pytorch模型脚本生成示例)
  16. - [TensorFlow模型脚本生成示例](#tensorflow模型脚本生成示例)
  17. - [ONNX模型文件生成示例](#onnx模型文件生成示例)
  18. - [注意事项](#注意事项)
  19. - [AST方案不支持场景](#ast方案不支持场景)
  20. - [场景1](#场景1)
  21. - [场景2](#场景2)
  22. - [三方库依赖](#三方库依赖)
  23. - [常见问题](#常见问题)
  24. - [附录](#附录)
  25. - [TensorFlow Pb模型导出](#tensorflow-pb模型导出)
  26. - [MindConverter错误码速查表](#mindconverter错误码速查表)
  27. <!-- /TOC -->
  28. ## 概述
  29. MindConverter是一款用于将PyTorch、TensorFlow脚本或者ONNX文件转换到MindSpore脚本的工具。结合转换报告的信息,用户只需对转换后的脚本进行微小的改动,即可快速将PyTorch、TensorFlow框架的模型脚本或者ONNX文件迁移到MindSpore。
  30. ## 安装
  31. 此工具为MindInsight的子模块,安装MindInsight后,即可使用MindConverter,MindInsight安装请参考该[安装文档](https://www.mindspore.cn/install/)。
  32. ## 用法
  33. MindConverter提供命令行(Command-line interface, CLI)的使用方式,命令如下。
  34. ```bash
  35. usage: mindconverter [-h] [--version] [--in_file IN_FILE]
  36. [--model_file MODEL_FILE] [--shape SHAPE [SHAPE ...]]
  37. [--input_nodes INPUT_NODES [INPUT_NODES ...]]
  38. [--output_nodes OUTPUT_NODES [OUTPUT_NODES ...]]
  39. [--output OUTPUT] [--report REPORT]
  40. [--project_path PROJECT_PATH]
  41. optional arguments:
  42. -h, --help show this help message and exit
  43. --version show program version number and exit
  44. --in_file IN_FILE Specify path for script file to use AST schema to do
  45. script conversation.
  46. --model_file MODEL_FILE
  47. PyTorch(.pth), Tensorflow(.pb) or ONNX(.onnx) model
  48. file path is expected to do script generation based on
  49. graph schema. When `--in_file` and `--model_file` are
  50. both provided, use AST schema as default.
  51. --shape SHAPE [SHAPE ...]
  52. Optional, expected input tensor shape of
  53. `--model_file`. It is required when use graph based
  54. schema. Both order and number should be consistent
  55. with `--input_nodes`. Usage: --shape 1,512 1,512
  56. --input_nodes INPUT_NODES [INPUT_NODES ...]
  57. Optional, input node(s) name of `--model_file`. It is
  58. required when use TensorFlow and ONNX model. Both
  59. order and number should be consistent with `--shape`.
  60. Usage: --input_nodes input_1:0 input_2:0
  61. --output_nodes OUTPUT_NODES [OUTPUT_NODES ...]
  62. Optional, output node(s) name of `--model_file`. It is
  63. required when use TensorFlow and ONNX model. Usage:
  64. --output_nodes output_1:0 output_2:0
  65. --output OUTPUT Optional, specify path for converted script file
  66. directory. Default output directory is `output` folder
  67. in the current working directory.
  68. --report REPORT Optional, specify report directory. Default is
  69. converted script directory.
  70. --project_path PROJECT_PATH
  71. Optional, PyTorch scripts project path. If PyTorch
  72. project is not in PYTHONPATH, please assign
  73. `--project_path` when use graph based schema. Usage:
  74. --project_path ~/script_file/
  75. ```
  76. ### PyTorch模型脚本迁移
  77. #### MindConverter提供两种PyTorch模型脚本迁移方案:
  78. 1. **基于抽象语法树(Abstract syntax tree, AST)的脚本转换**:指定`--in_file`的值,将使用基于AST的脚本转换方案;
  79. 2. **基于图结构的脚本生成**:指定`--model_file`与`--shape`将使用基于图结构的脚本生成方案。
  80. > 若同时指定了`--in_file`,`--model_file`将默认使用AST方案进行脚本迁移。
  81. 当使用基于图结构的脚本生成方案时,要求必须指定`--shape`的值;当使用基于AST的脚本转换方案时,`--shape`会被忽略。
  82. 其中,`--output`与`--report`参数可省略。若省略,MindConverter将在当前工作目录(Working directory)下自动创建`output`目录,将生成的脚本、转换报告、权重文件、权重映射表输出至该目录。
  83. 另外,当使用基于图结构的脚本生成方案时,请确保原PyTorch项目已在Python包搜索路径中,可通过CLI进入Python交互式命令行,通过import的方式判断是否已满足;若未加入,可通过`--project_path`
  84. 命令手动将项目路径传入,以确保MindConverter可引用到原PyTorch脚本。
  85. > 假设用户项目目录为`/home/user/project/model_training`,用户可通过如下命令手动将项目添加至包搜索路径中:`export PYTHONPATH=/home/user/project/model_training:$PYTHONPATH`;
  86. > 此处MindConverter需要引用原PyTorch脚本,是因为PyTorch模型反向序列化过程中会引用原脚本。
  87. PyTorch(.pth)模型转换仅支持单输入、单输出的PyTorch模型,如需转换多输入、多输出模型,建议转换为ONNX之后,使用ONNX进行转换。
  88. ### TensorFlow模型脚本迁移
  89. **MindConverter提供基于图结构的脚本生成方案**:指定`--model_file`、`--shape`、`--input_nodes`、`--output_nodes`进行脚本迁移。
  90. > AST方案不支持TensorFlow模型脚本迁移,TensorFlow脚本迁移仅支持基于图结构的方案。
  91. ### ONNX模型文件迁移
  92. **MindConverter提供基于图结构的脚本生成方案**:指定`--model_file`、`--shape`、`--input_nodes`、`--output_nodes`进行脚本迁移。
  93. > AST方案不支持ONNX模型文件迁移,ONNX文件迁移仅支持基于图结构的方案。
  94. ## 使用场景
  95. MindConverter提供两种技术方案,以应对不同脚本迁移场景:
  96. 1. 用户希望迁移后脚本保持原脚本结构(包括变量、函数、类命名等与原脚本保持一致)。
  97. 2. 用户希望迁移后脚本保持较高的转换率,尽量少的修改、甚至不需要修改,即可实现迁移后模型脚本的执行。
  98. 对于上述第一种场景,推荐用户使用基于AST的方案进行转换(AST方案仅支持PyTorch脚本转换),AST方案通过对原PyTorch脚本的抽象语法树进行解析、编辑,将其替换为MindSpore的抽象语法树,再利用抽象语法树生成代码。理论上,AST方案支持任意模型脚本迁移,但语法树解析操作受原脚本用户编码风格影响,可能导致同一模型的不同脚本最终的转换率存在一定差异。
  99. 对于上述第二种场景,推荐用户使用基于图结构的脚本生成方案,计算图作为一种标准的模型描述语言,可以消除用户代码风格多样导致的脚本转换率不稳定的问题。在已支持算子的情况下,该方案可提供优于AST方案的转换率。
  100. 目前已基于典型图像分类网络对图结构的脚本转换方案进行测试。
  101. > 1. 基于图结构的脚本生成方案,由于要加载PyTorch、TensorFlow模型,会导致转换后网络中Dropout算子丢失,需要用户手动补齐。
  102. > 2. 基于图结构的脚本生成方案持续优化中。
  103. [支持的模型列表(如下模型已基于x86 Ubuntu发行版,PyTorch 1.5.0以及TensorFlow 1.15.0测试通过)](./docs/supported_model_list_cn.md)。
  104. ## 使用示例
  105. ### 基于AST的脚本转换示例
  106. 若用户希望使用基于AST的方案进行脚本迁移,假设原PyTorch脚本路径为`/home/user/model.py`,希望将脚本输出至`/home/user/output`,转换报告输出至`/home/user/output/report`
  107. ,则脚本转换命令为:
  108. ```bash
  109. mindconverter --in_file /home/user/model.py \
  110. --output /home/user/output \
  111. --report /home/user/output/report
  112. ```
  113. 转换报告中,对于未转换的代码行形式为如下,其中x,
  114. y指明的是原PyTorch脚本中代码的行、列号。对于未成功转换的算子,可参考[MindSporeAPI映射查询功能](https://www.mindspore.cn/doc/note/zh-CN/master/index.html#operator_api)
  115. 手动对代码进行迁移。对于工具无法迁移的算子,会保留原脚本中的代码。
  116. ```text
  117. line x:y: [UnConvert] 'operator' didn't convert. ...
  118. ```
  119. 转换报告示例如下所示:
  120. ```text
  121. [Start Convert]
  122. [Insert] 'import mindspore.ops.operations as P' is inserted to the converted file.
  123. line 1:0: [Convert] 'import torch' is converted to 'import mindspore'.
  124. ...
  125. line 157:23: [UnConvert] 'nn.AdaptiveAvgPool2d' didn't convert. Maybe could convert to mindspore.ops.operations.ReduceMean.
  126. ...
  127. [Convert Over]
  128. ```
  129. 对于部分未成功转换的算子,报告中会提供修改建议,如`line 157:23`,MindConverter建议将`torch.nn.AdaptiveAvgPool2d`
  130. 替换为`mindspore.ops.operations.ReduceMean`。
  131. ### 基于图结构的脚本生成示例
  132. #### PyTorch模型脚本生成示例
  133. 若用户已将PyTorch模型保存为.pth格式,假设模型绝对路径为`/home/uer/model.pth`,该模型期望的输入shape为(1, 3, 224, 224)
  134. ,原PyTorch脚本位于`/home/user/project/model_training`,希望将脚本、权重文件和权重映射表输出至`/home/user/output`
  135. ,转换报告输出至`/home/user/output/report`
  136. 。<br /> 则脚本生成命令为:
  137. ```bash
  138. mindconverter --model_file /home/user/model.pth --shape 1,3,224,224 \
  139. --output /home/user/output \
  140. --report /home/user/output/report \
  141. --project_path /home/user/project/model_training
  142. ```
  143. 执行该命令,MindSpore代码文件、权重文件、权重映射表和转换报告生成至相应目录。
  144. 基于图结构的脚本生成方案产生的转换报告格式与AST方案相同。然而,由于基于图结构方案属于生成式方法,转换过程中未参考原PyTorch脚本,因此生成的转换报告中涉及的代码行、列号均指生成后脚本。
  145. 另外对于未成功转换的算子,在代码中会相应的标识该节点输入、输出Tensor的shape(以`input_shape`, `output_shape`
  146. 标识),便于用户手动修改。以Reshape算子为例(暂不支持Reshape),将生成如下代码:
  147. ```python
  148. class Classifier(nn.Cell):
  149. def __init__(self):
  150. super(Classifier, self).__init__()
  151. ...
  152. self.reshape = onnx.Reshape(input_shape=(1, 1280, 1, 1),
  153. output_shape=(1, 1280))
  154. ...
  155. def construct(self, x):
  156. ...
  157. # Suppose input of `reshape` is x.
  158. reshape_output = self.reshape(x)
  159. ...
  160. ```
  161. 通过`input_shape`、`output_shape`参数,用户可以十分便捷地完成算子替换,替换结果如下:
  162. ```python
  163. from mindspore.ops import operations as P
  164. ...
  165. class Classifier(nn.Cell):
  166. def __init__(self):
  167. super(Classifier, self).__init__()
  168. ...
  169. self.reshape = P.Reshape(input_shape=(1, 1280, 1, 1),
  170. output_shape=(1, 1280))
  171. ...
  172. def construct(self, x):
  173. ...
  174. # Suppose input of `reshape` is x.
  175. reshape_output = self.reshape(x, (1, 1280))
  176. ...
  177. ```
  178. > 其中`--output`与`--report`参数可省略,若省略,该命令将在当前工作目录(Working directory)下自动创建`output`目录,将生成的脚本、权重文件、权重映射表、转换报告输出至该目录。
  179. 权重映射表示例如下所示:
  180. ```json
  181. {
  182. "resnet50": [
  183. {
  184. "converted_weight": {
  185. "name": "conv2d_0.weight",
  186. "shape": [
  187. 64,
  188. 3,
  189. 7,
  190. 7
  191. ],
  192. "data_type": "Float32"
  193. },
  194. "source_weight": {
  195. "name": "conv1.weight",
  196. "shape": [
  197. 64,
  198. 3,
  199. 7,
  200. 7
  201. ],
  202. "data_type": "float32"
  203. }
  204. }
  205. ]
  206. }
  207. ```
  208. 映射表中分别保存算子在MindSpore中的权重信息(`converted_weight`)和在原始框架中的权重信息(`source_weight`)。
  209. #### TensorFlow模型脚本生成示例
  210. 使用TensorFlow模型脚本迁移,需要先将TensorFlow模型导出为pb格式,并且获取模型输入节点、输出节点名称。TensorFlow pb模型导出可参考[TensorFlow Pb模型导出](#tensorflow-pb模型导出)
  211. 假设输入节点名称为`input_1:0`、输出节点名称为`predictions/Softmax:0`,模型输入样本尺寸为`1,224,224,3`,则可使用如下命令进行脚本生成:
  212. ```bash
  213. mindconverter --model_file /home/user/xxx/frozen_model.pb --shape 1,224,224,3 \
  214. --input_nodes input_1:0 \
  215. --output_nodes predictions/Softmax:0 \
  216. --output /home/user/output \
  217. --report /home/user/output/report
  218. ```
  219. 执行该命令,MindSpore代码文件、权重文件、权重映射表和转换报告生成至相应目录。
  220. 由于基于图结构方案属于生成式方法,转换过程中未参考原TensorFlow脚本,因此生成的转换报告中涉及的代码行、列号均指生成后脚本。
  221. 另外,对于未成功转换的算子,在代码中会相应的标识该节点输入、输出Tensor的shape(以`input_shape`、`output_shape`标识),便于用户手动修改,示例见**PyTorch模型脚本生成示例**。
  222. #### ONNX模型文件生成示例
  223. 使用ONNX模型文件迁移,需要先从.onnx文件中获取模型输入节点、输出节点名称。获取ONNX模输入、输出节点名称,可使用 [Netron](https://github.com/lutzroeder/netron) 工具查看。
  224. 假设输入节点名称为`input_1:0`、输出节点名称为`predictions/Softmax:0`,模型输入样本尺寸为`1,3,224,224`,则可使用如下命令进行脚本生成:
  225. ```bash
  226. mindconverter --model_file /home/user/xxx/model.onnx --shape 1,3,224,224 \
  227. --input_nodes input_1:0 \
  228. --output_nodes predictions/Softmax:0 \
  229. --output /home/user/output \
  230. --report /home/user/output/report
  231. ```
  232. 执行该命令,MindSpore代码文件、权重文件、权重映射表和转换报告生成至相应目录。
  233. 由于基于图结构方案属于生成式方法,转换过程中未参考ONNX文件,因此生成的转换报告中涉及的代码行、列号均指生成后脚本。
  234. 另外,对于未成功转换的算子,在代码中会相应的标识该节点输入、输出Tensor的shape(以`input_shape`、`output_shape`标识),便于用户手动修改,示例见**PyTorch模型脚本生成示例**。
  235. ## 注意事项
  236. 1. PyTorch、TensorFlow不作为MindInsight明确声明的依赖库。若想使用基于图结构的脚本生成工具,需要用户手动安装与生成PyTorch模型版本一致的PyTorch库(MindConverter使用PyTorch
  237. 1.5.0进行测试,不支持PyTorch 1.4.x; PyTorch 1.6.x、PyTorch 1.7.x未进行测试。),或TensorFlow。
  238. 2. 脚本转换工具本质上为算子驱动,对于MindConverter未维护的PyTorch或ONNX算子与MindSpore算子映射,将会出现相应的算子无法转换的问题,对于该类算子,用户可手动修改,或基于MindConverter实现映射关系,向MindInsight仓库贡献。
  239. 3. 在使用基于计算图的迁移时,MindConverter会根据`--shape`参数将模型输入的批次大小(batch size)、句子长度(sequence length)、图片尺寸(image shape)等尺寸相关参数固定下来,用户需要保证基于MindSpore重训练、推理时输入shape与转换时一致;若需要调整输入尺寸,请重新指定`--shape`进行转换或修改转换后脚本中涉及张量尺寸变更操作相应的操作数。
  240. 4. 脚本文件、权重文件和权重映射表输出于同一个目录下。
  241. ## AST方案不支持场景
  242. ### 场景1
  243. 部分类和方法目前无法转换:
  244. 1. 使用`torch.Tensor`的`shape`,`ndim`和`dtype`成员;
  245. 2. `torch.nn.AdaptiveXXXPoolXd`和`torch.nn.functional.adaptive_XXX_poolXd()`;
  246. 3. `torch.nn.functional.Dropout`;
  247. 4. `torch.unsqueeze()`和`torch.Tensor.unsqueeze()`;
  248. 5. `torch.chunk()`和`torch.Tensor.chunk()`。
  249. ### 场景2
  250. 继承的父类是nn.Module的子类。
  251. 例如:(如下代码片段摘自torchvision.models.mobilenet)
  252. ```python
  253. from torch import nn
  254. class ConvBNReLU(nn.Sequential):
  255. def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1):
  256. padding = (kernel_size - 1) // 2
  257. super(ConvBNReLU, self).__init__(
  258. nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False),
  259. nn.BatchNorm2d(out_planes),
  260. nn.ReLU6(inplace=True)
  261. )
  262. ```
  263. ## 三方库依赖
  264. 用户在使用MindConverter时,下列三方库未在MindInsight依赖列表(requirements.txt)中声明。用户除安装可满足模型加载、训练、推理的TensorFlow或PyTorch外,还需要安装(pip
  265. install)如下依赖库(PyTorch模型脚本转MindSpore的用户无需安装tf2onnx):
  266. ```text
  267. onnx>=1.8.0
  268. tf2onnx>=1.7.1
  269. onnxruntime>=1.5.2
  270. onnxoptimizer>=0.1.2
  271. ```
  272. 对于个别模型,若在转换过程中出现onnx或tf2onnx错误信息,请尝试更新环境中onnx或tf2onnx或onnxoptimizer至最新版本。
  273. ## 常见问题
  274. Q1. `terminate called after throwing an instance of 'std::system_error', what(): Resource temporarily unavailable, Aborted (core dumped)`:
  275. > 答: 该问题由TensorFlow导致。脚本转换时,需要通过TensorFlow库加载TensorFlow的模型文件,此时TensorFlow会申请相关资源进行初始化,若申请资源失败(可能由于系统进程数超过Linux最大进程数限制),TensorFlow C/C++层会出现Core Dumped问题。详细信息请参考TensorFlow官方ISSUE,如下ISSUE仅供参考:[TF ISSUE 14885](https://github.com/tensorflow/tensorflow/issues/14885), [TF ISSUE 37449](https://github.com/tensorflow/tensorflow/issues/37449)
  276. Q2. MindConverter是否可以在ARM平台运行?
  277. > 答:MindConverter同时支持X86、ARM平台,若在ARM平台运行需要用户自行安装模型所需的依赖包和运行环境。
  278. Q3. PyTorch模型转换时为什么提示`Error detail: [NodeInputMissing] ...`?
  279. > 答:对于PyTorch模型,若网络中存在`torch.nn.functional.xxx`, `torch.xxx`, `torch.Tensor.xxx`层算子,可能存在节点解析失败的情况,需要用户手动替换为torch.nn层算子。
  280. Q4. 为什么使用MindConverter进行模型转换需要很长时间(超过十分钟),而模型并不大?
  281. > 答:MindConverter进行转换时,需要使用Protobuf对模型文件进行反序列化,请确保Python环境中安装的Protobuf采用C++后端实现,检查方法如下,若输出为python,则需要安装采用C++实现的Python Protobuf(下载Protobuf源码并进入源码中的python子目录,使用python setup.py install --cpp_implementation进行安装);若输出为cpp,转换过程仍耗时较长,请在转换前使用添加环境变量`export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp`。
  282. ```python
  283. from google.protobuf.internal import api_implementation
  284. print(api_implementation.Type())
  285. ```
  286. ## 附录
  287. ### TensorFlow Pb模型导出
  288. 使用Keras构建模型的用户,可尝试[如下方法](./docs/tensorflow_model_exporting_cn.md)进行导出。
  289. ### MindConverter错误码速查表
  290. MindConverter错误码定义,请参考[链接](./docs/error_code_definition_cn.md)。