Skip to content

tools for model exporting and converting #639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 16, 2024

Conversation

horcham
Copy link
Collaborator

@horcham horcham commented Dec 21, 2023

Thank you for your contribution to the MindOCR repo.
Before submitting this PR, please make sure:

Motivation

  1. 提供原生模型转换工具,用户终于可以无痛转模型了。支持以下功能

    • 三种转换模式:exportconvertexport+convert
    • 支持动静态
    • 支持下载
    • 支持指定模型,或模型全量转换
    • 支持convert后使用benchmark检验
    • 输出转换指令与转换报告,方便检验与复现
    • 保存转换日志,方便问题定位
  2. 使用例子:

# 全量模型,下载+转换,export+convert,动态
python export_convert_tool.py --task export_convert --model_name all --is_dynamic True --force True

# 指定模型,下载,export,静态
python export_convert_tool.py --task export --model_name crnn_vgg7 --is_dynamic False --force True

# 指定模型。指定mindir,convert,动态
python export_convert_tool.py --task convert--model_name crnn_vgg7  --input_file="crnn_vgg7.mindir" --is_dynamic True --force True
  1. 输出指定与报告

指定模型,运行后输出操作指令与报告

  • 例1:运行export,得到如下指令和报告

     python export_convert_tool.py --model_name dbnetpp_resnet50 --task export --is_dynamic true --input_file dbnetpp_resnet50-068166c2.ckpt
    Export Command: python export.py --model_name_or_config dbnetpp_resnet50 --save_dir output_folder/export_folder --local_ckpt_path dbnetpp_resnet50-068166c2.ckpt --is_dynamic_shape True --model_type det
    Export Success: output_folder/export_folder/dbnetpp_resnet50.mindir
    +----------------------+----------------+
    | Export Dynamic Model | Dynamic Export |
    +----------------------+----------------+
    |   dbnetpp_resnet50   |    Success     |
    +----------------------+----------------+
    
  • 例2:运行convert,得到如下指令和报告

     python export_convert_tool.py --model_name dbnetpp_resnet50 --task export --is_dynamic true --input_file dbnetpp_resnet50-068166c2.ckpt
    Convert Command: converter_lite --fmk=MINDIR --modelFile=output_folder/export_folder/dbnetpp_resnet50.mindir --outputFile=output_folder/convert_folder/dbnetpp_resnet50_lite_dynamic --optimize=ascend_oriented --configFile=output_folder/convert_folder/convert_dynamic_dbnetpp_resnet50.txt
    Convert Success: output_folder/convert_folder/dbnetpp_resnet50_lite_dynamic.mindir
    Benchmark Command: benchmark --modelFile=output_folder/convert_folder/dbnetpp_resnet50_lite_dynamic.mindir --device=Ascend --inputShapes=1,3,1152,2048 --loopCount=100 --warmUpLoopCount=10
    Infer Dynamic Shape Success 
    Benchmark Command: benchmark --modelFile=output_folder/convert_folder/dbnetpp_resnet50_lite_dynamic.mindir --device=Ascend --inputShapes=1,3,1120,2080 --loopCount=100 --warmUpLoopCount=10
    Infer Dynamic Shape Success 
    
    +--------------------------------------------+-----------------+---------------+---------------+
    | Convert Dynamic Model From Exported Mindir | Dynamic Convert | Infer Shape 0 | Infer Shape 1 |
    +--------------------------------------------+-----------------+---------------+---------------+
    |              dbnetpp_resnet50              |     Success     | 1,3,1152,2048 | 1,3,1120,2080 |
    +--------------------------------------------+-----------------+---------------+---------------+
    
  • 例3:运行export_convert,全量动态转换,得到如下指令和报告

     python export_convert_tool.py --task export_convert --model_name all --is_dynamic True --force True
    Exporting model:abinet, 1/24
    output_folder/export_folder/abinet.mindir exists and it will be overwritten if exported successfully.
    Export Command: python export.py --model_name_or_config abinet --save_dir output_folder/export_folder --is_dynamic_shape True --model_type rec
    Export Success: output_folder/export_folder/abinet.mindir
    Exporting model:master_resnet31, 2/24
    output_folder/export_folder/master_resnet31.mindir exists and it will be overwritten if exported successfully.
    Export Command: python export.py --model_name_or_config master_resnet31 --save_dir output_folder/export_folder --is_dynamic_shape True --model_type rec
    Export Success: output_folder/export_folder/master_resnet31.mindir
    Exporting model:cls_mobilenet_v3_small_100_model, 3/24
    output_folder/export_folder/cls_mobilenet_v3_small_100_model.mindir exists and it will be overwritten if exported successfully.
    Export Command: python export.py --model_name_or_config cls_mobilenet_v3_small_100_model --save_dir output_folder/export_folder --is_dynamic_shape True --model_type cls
    Export Success: output_folder/export_folder/cls_mobilenet_v3_small_100_model.mindir
    ...
    Exporting model:visionlan_resnet45, 23/24
    output_folder/export_folder/visionlan_resnet45.mindir exists and it will be overwritten if exported successfully.
    Export Command: python export.py --model_name_or_config visionlan_resnet45 --save_dir output_folder/export_folder --is_dynamic_shape True --model_type rec
    Export Success: output_folder/export_folder/visionlan_resnet45.mindir
    Exporting model:robustscanner_resnet31, 24/24
    output_folder/export_folder/robustscanner_resnet31.mindir exists and it will be overwritten if exported successfully.
    Export Command: python export.py --model_name_or_config robustscanner_resnet31 --save_dir output_folder/export_folder --is_dynamic_shape True --model_type rec
    Export Success: output_folder/export_folder/robustscanner_resnet31.mindir
    +----------------------------------+----------------+
    |       Export Dynamic Model       | Dynamic Export |
    +----------------------------------+----------------+
    |              abinet              |    Success     |
    |         master_resnet31          |    Success     |
    | cls_mobilenet_v3_small_100_model |    Success     |
    |          crnn_resnet34           |    Success     |
    |         crnn_resnet34_ch         |    Success     |
    |            crnn_vgg7             |    Success     |
    |        dbnet_mobilenetv3         |    Success     |
    |          dbnet_resnet18          |    Success     |
    |          dbnet_resnet50          |    Success     |
    |       dbnet_resnet50_ch_en       |    Success     |
    |         dbnetpp_resnet50         |    Success     |
    |      dbnetpp_resnet50_ch_en      |    Success     |
    |         east_mobilenetv3         |    Success     |
    |          east_resnet50           |    Success     |
    |         fcenet_resnet50          |     Failed     |
    |        psenet_mobilenetv3        |    Success     |
    |         psenet_resnet50          |    Success     |
    |         psenet_resnet152         |    Success     |
    |          rare_resnet34           |    Success     |
    |         rare_resnet34_ch         |    Success     |
    |            svtr_tiny             |    Success     |
    |           svtr_tiny_ch           |    Success     |
    |        visionlan_resnet45        |    Success     |
    |      robustscanner_resnet31      |    Success     |
    +----------------------------------+----------------+
    Converting model:abinet, 1/24
    Convert Command: converter_lite --fmk=MINDIR --modelFile=all_output/export_folder/abinet.mindir --outputFile=all_output/convert_folder_lite_dynamic --optimize=ascend_oriented --configFile=all_output/convert_folder/temp_config.txt
    Convert Failed 
    
    Converting model:master_resnet31, 2/24
    Convert Command: converter_lite --fmk=MINDIR --modelFile=all_output/export_folder/master_resnet31.mindir --outputFile=all_output/conveer/master_resnet31_lite_dynamic --optimize=ascend_oriented --configFile=all_output/convert_folder/temp_config.txt
    Convert Failed 
    
    Converting model:cls_mobilenet_v3_small_100_model, 3/24
    Convert Command: converter_lite --fmk=MINDIR --modelFile=all_output/export_folder/cls_mobilenet_v3_small_100_model.mindir --outputFiletput/convert_folder/cls_mobilenet_v3_small_100_model_lite_dynamic --optimize=ascend_oriented --configFile=all_output/convert_folder/teig.txt
    Convert Success: all_output/convert_folder/cls_mobilenet_v3_small_100_model_lite_dynamic.mindir
    Benchmark Command: benchmark --modelFile=all_output/convert_folder/cls_mobilenet_v3_small_100_model_lite_dynamic.mindir --device=AscenutShapes=1,3,48,192 --loopCount=100 --warmUpLoopCount=10
    Infer Dynamic Shape Success 
    ...
    Converting model:visionlan_resnet45, 23/24
    Convert Command: converter_lite --fmk=MINDIR --modelFile=all_output/export_folder/visionlan_resnet45.mindir --outputFile=all_output/coolder/visionlan_resnet45_lite_dynamic --optimize=ascend_oriented --configFile=all_output/convert_folder/temp_config.txt
    Convert Failed 
    
    Converting model:robustscanner_resnet31, 24/24
    Convert Command: converter_lite --fmk=MINDIR --modelFile=all_output/export_folder/robustscanner_resnet31.mindir --outputFile=all_outpurt_folder/robustscanner_resnet31_lite_dynamic --optimize=ascend_oriented --configFile=all_output/convert_folder/temp_config.txt
    Convert Failed 
    
    +--------------------------------------------+-----------------+---------------+---------------+
    | Convert Dynamic Model From Exported Mindir | Dynamic Convert | Infer Shape 0 | Infer Shape 1 |
    +--------------------------------------------+-----------------+---------------+---------------+
    |                   abinet                   |      Failed     |               |               |
    |              master_resnet31               |      Failed     |               |               |
    |      cls_mobilenet_v3_small_100_model      |     Success     |   1,3,48,192  |               |
    |                 crnn_vgg7                  |     Success     |   1,3,32,100  |   1,3,32,132  |
    |               crnn_resnet34                |     Success     |   1,3,32,100  |   1,3,32,132  |
    |              crnn_resnet34_ch              |     Success     |   1,3,32,320  |   1,3,32,352  |
    |             dbnet_mobilenetv3              |     Success     |  1,3,736,1280 |  1,3,704,1211 |
    |               dbnet_resnet18               |     Success     |  1,3,736,1280 |  1,3,704,1211 |
    |               dbnet_resnet50               |     Success     |  1,3,736,1280 |  1,3,704,1211 |
    |            dbnet_resnet50_ch_en            |     Success     |  1,3,736,1280 |  1,3,704,1211 |
    |              dbnetpp_resnet50              |     Success     | 1,3,1152,2048 | 1,3,1120,2080 |
    |           dbnetpp_resnet50_ch_en           |     Success     | 1,3,1152,2048 | 1,3,1120,2080 |
    |              east_mobilenetv3              |     Success     |  1,3,720,1280 |  1,3,816,1211 |
    |               east_resnet50                |     Success     |  1,3,720,1280 |  1,3,816,1211 |
    |              fcenet_resnet50               |      Failed     |               |               |
    |             psenet_mobilenetv3             |     Success     |  1,3,736,1280 |  1,3,704,1211 |
    |              psenet_resnet50               |     Success     |  1,3,736,1280 |  1,3,704,1211 |
    |              psenet_resnet152              |     Success     | 1,3,1472,2624 | 1,3,1376,1307 |
    |               rare_resnet34                |     Success     |   1,3,32,100  |   1,3,32,132  |
    |              rare_resnet34_ch              |     Success     |   1,3,32,320  |   1,3,32,352  |
    |                 svtr_tiny                  |     Success     |   1,3,64,256  |   1,3,64,288  |
    |                svtr_tiny_ch                |     Success     |   1,3,32,320  |   1,3,32,352  |
    |             visionlan_resnet45             |      Failed     |               |               |
    |           robustscanner_resnet31           |      Failed     |               |               |
    +--------------------------------------------+-----------------+---------------+---------------+
    
    
    
5. xxx

## Test Plan

(How should this PR be tested? Do you require special setup to run the test or repro the fixed bug?)

## Related Issues and PRs

(Is this PR part of a group of changes? Link the other relevant PRs and Issues here. Use https://help.github.com/en/articles/closing-issues-using-keywords for help on GitHub syntax)

@horcham horcham changed the title [WIP] 模型转换与导出工具与测试 [WIP] tools for model exporting and converting Dec 24, 2023
@horcham horcham force-pushed the tools_bash branch 8 times, most recently from ca54557 to 1c82279 Compare December 26, 2023 10:21
@horcham horcham changed the title [WIP] tools for model exporting and converting tools for model exporting and converting Dec 26, 2023
"infer_shape_list": ["1,3,736,1280", "1,3,704,1211"],
"var": "args0",
},
# "dbnet_resnet50_ch_en": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此处注释是存在bug不支持吗?是否需要加TODO信息说明一下缘由?

"infer_shape_list": ["1,3,1152,2048", "1,3,1120,2080"],
"var": "args0",
},
# "dbnetpp_resnet50_ch_en": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此处注释是存在bug不支持吗?是否需要加TODO信息说明一下缘由?

Copy link
Collaborator Author

@horcham horcham Jan 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此处由于缺少dbnetpp_resnet50_ch_endbnet_resnet50_ch_en的ckpt自动下载。疑似dbnet_resnet50dbnetpp_resnet50错写为dbnet_resnet50_ch_endbnetpp_resnet50_ch_en的ckpt下载路径。请查看该PR中mindocr/models/det_dbnet.py的修改。修改之后该注释取消。


if __name__ == "__main__":
# not support export on Ascend 310P
# test_export_static_model(output_path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此处为何大部分都要注释掉:

  1. 如依赖硬件,可考虑用npu-smi info判断本地ascend设备型号后,执行对应用例;
  2. 或者用注释说明,用户应选用哪些用例。

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新建完文件夹了以后最好删掉,可以参照下面的代码写个装饰器:

def vfl_data_test(func): @wraps(func) def wrap_test(*args, **kwargs): try: stop_fl_process() clean_fl_temp_files() mkdir("temp") mkdir("temp/leader") mkdir("temp/follower") generate_random_data() func(*args, **kwargs) except Exception: logger.error("VFL data test catch exception") raise finally: logger.info("VFl data test begin to clear") stop_fl_process() clean_fl_temp_files() logger.info("VFl data test end clear") return wrap_test

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不知道咋调github缩进,参照下面那个链接吧
https://gitee.com/mindspore/federated/blob/master/tests/ut/python/tests/common.py

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI的启停机制是怎么样的,代码涉及网络和多进程,最好加上超时报错和退出时清空进程

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI的启停机制是怎么样的,代码涉及网络和多进程,最好加上超时报错和退出时清空进程

CI中执行tests/uttests/st中的用例,并不会执行该文件

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

非CI可以不用加超时报错或者退出清空,忽略我上面的那些评论

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不涉及CI

def test_convert_static_model_from_download_mindir(output_path):
convert_tool = "converter_lite"
benchmark_tool = "benchmark"
save_path = f"{output_path}/convert_static_from_download"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

构造路径时,需要考虑OS差异,建议使用:

file_path = os.getcwd() + os.sep + file_name 
file_path = os.path.join(os.getcwd(), file_name)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改



if __name__ == "__main__":
output_path = "./output"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是否需要判断路径是否存在,然后尝试新建文件夹?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已更新为parser传入,并加入路径判断,与是否文件覆盖选项

from tools.export_convert_tool import ExportDynamicModel # noqa
from tools.export_convert_tool import ExportStaticModel # noqa

output_path = "./output"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是否需要判断路径是否存在,然后尝试新建文件夹?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已更新为parser传入,并加入路径判断,与是否文件覆盖选项


if __name__ == "__main__":
# not support export on Ascend 310P
# test_export_static_model(output_path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新建完文件夹了以后最好删掉,可以参照下面的代码写个装饰器:

def vfl_data_test(func): @wraps(func) def wrap_test(*args, **kwargs): try: stop_fl_process() clean_fl_temp_files() mkdir("temp") mkdir("temp/leader") mkdir("temp/follower") generate_random_data() func(*args, **kwargs) except Exception: logger.error("VFL data test catch exception") raise finally: logger.info("VFl data test begin to clear") stop_fl_process() clean_fl_temp_files() logger.info("VFl data test end clear") return wrap_test


if __name__ == "__main__":
# not support export on Ascend 310P
# test_export_static_model(output_path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不知道咋调github缩进,参照下面那个链接吧
https://gitee.com/mindspore/federated/blob/master/tests/ut/python/tests/common.py


if __name__ == "__main__":
# not support export on Ascend 310P
# test_export_static_model(output_path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI的启停机制是怎么样的,代码涉及网络和多进程,最好加上超时报错和退出时清空进程

convert_tool = "converter_lite" # path to converter_lite
benchmark_tool = "benchmark" # path to benchmark
save_path = f"{output_path}/convert_static_from_exported" # path to save converted static model
exported_path = "path/to/exported/path" # path to exported model
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported_path是不是没用到

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已更新

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不涉及CI

convert_tool = "converter_lite" # path to converter_lite
benchmark_tool = "benchmark" # path to benchmark
save_path = f"{output_path}/convert_dynamic_from_exported" # path to save converted dynamic model
exported_path = "path/to/exported/path" # path to exported model
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported_path是不是没用到

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已更新

self.log_handle.write(f"Export Success: {exported_model_path}")
return True
else:
print("\033[31mExport Failed \033[0m")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

日志中添加失败原因


subprocess.call(f"echo Export Command: {command}".split(), stdout=self.log_handle, stderr=self.log_handle)
print(f"\033[34mExport Command\033[0m: {command}")
subprocess.call(command.split(), stdout=self.log_handle, stderr=self.log_handle)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种方式启动好像是非阻塞的?最好加个锁,然后校验下导出文件

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

非CI可以不用加,忽略我上面的评论


if __name__ == "__main__":
# not support export on Ascend 310P
# test_export_static_model(output_path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

非CI可以不用加超时报错或者退出清空,忽略我上面的那些评论


subprocess.call(f"echo Export Command: {command}".split(), stdout=self.log_handle, stderr=self.log_handle)
print(f"\033[34mExport Command\033[0m: {command}")
subprocess.call(command.split(), stdout=self.log_handle, stderr=self.log_handle)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

非CI可以不用加,忽略我上面的评论

@horcham horcham force-pushed the tools_bash branch 5 times, most recently from 633c97d to 6e2f016 Compare January 12, 2024 04:50
@horcham horcham force-pushed the tools_bash branch 2 times, most recently from 482ce08 to 20e09ad Compare January 12, 2024 08:08
@horcham horcham force-pushed the tools_bash branch 7 times, most recently from 9d0996e to 770473d Compare January 15, 2024 06:12
@panshaowu panshaowu merged commit 4bca517 into mindspore-lab:main Jan 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants