1 系统环境
硬件环境(Ascend/GPU/CPU): Ascend910
MindSpore版本: mindspore=2.1.0
执行模式(PyNative/ Graph): 不限
Python版本: Python=3.7
操作系统平台: linux
2 报错信息
2.1 问题描述
在Modelarts里面的训练作业里面训练yolov5,出现报错。使用的代码:https://gitee.com/mindspore/models/blob/master/official/cv/YOLOv5
2.2 报错信息
在default_config.yaml文件里面enable_modelarts参数是False的时候出现如下报错:
FileNotFoundError:[Error 2] No such file or directory:’/cache/data/annotations/instances_train2017.json’
但是在enable_modelarts为False的时候,在notbook环境下,是可以正常跑通训练的。把enable_modelarts改为True的时候,在训练界面,就可以找到路径了,但是会报下面的错误。
TypeError: modelarts_pre_process() missing 1 required positional argument:’args’
并且把enable_modelarts改为True的时候,在notbook环境下,也会报和上述相同的错误。
3 根因分析
1.default_config.yaml文件里面enable_modelarts参数是False 报FileNotFoundError:[Error 2] No such file or directory:’/cache/data/annotations/instances_train2017.json’
这个报错是因为代码走到了训练流程里面,因为环境里面没数据集导致。这个只要在对应位置放置数据集就行。
2.enable_modelarts改为True 报
TypeError: modelarts_pre_process() missing 1 required positional argument:’args’其实这里还没走到训练流程,这个是前置流程。
train.py 128行代码定义了moxing_wrapper这个装饰器
@moxing_wrapper(pre_process=modelarts_pre_process, post_process=modelarts_post_process, pre_args=[config])
def run_train():
这个装饰器定义在 official/cv/YOLOv5/model_utils/moxing_adapter.py
def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
"""
Moxing wrapper to download dataset and upload outputs.
"""
def wrapper(run_func):
@functools.wraps(run_func)
def wrapped_func(*args, **kwargs):
# Download data from data_url
if config.enable_modelarts:
if config.data_url:
sync_data(config.data_url, config.data_path)
print("Dataset downloaded: ", os.listdir(config.data_path))
if config.checkpoint_url:
sync_data(config.checkpoint_url, config.load_path)
print("Preload downloaded: ", os.listdir(config.load_path))
if config.train_url:
sync_data(config.train_url, config.output_path)
print("Workspace downloaded: ", os.listdir(config.output_path))
mindspore.set_context(save_graphs_path=os.path.join(config.output_path, str(get_rank_id())))
config.device_num = get_device_num()
config.device_id = get_device_id()
if not os.path.exists(config.output_path):
os.makedirs(config.output_path)
if pre_process:
if "pre_args" in kwargs.keys():
pre_process(*kwargs["pre_args"])
else:
pre_process()
# Run the main function
run_func(*args, **kwargs)
# Upload data to train_url
if config.enable_modelarts:
if post_process:
if "post_args" in kwargs.keys():
post_process(*kwargs["post_args"])
else:
post_process()
if config.train_url:
print("Start to copy output directory")
sync_data(config.output_path, config.train_url)
return wrapped_func
return wrapper
出问题的是modelarts_pre_process 这个函数,该函数有一个参数,但是调用的时候并没有参数传递过去。
也就是下面的代码走到了else分支。
if "pre_args" in kwargs.keys():
pre_process(*kwargs["pre_args"])
else:
pre_process()
为什么传递给装饰器的kwargs一开始是有值的,但是变成了空呢?
问题出在了official/cv/YOLOv5/model_utils/moxing_adapter.py
第136行
def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
第142行
def wrapped_func(*args, **kwargs):
以及162行
if "pre_args" in kwargs.keys():
def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
"""
Moxing wrapper to download dataset and upload outputs.
"""
def wrapper(run_func):
@functools.wraps(run_func)
def wrapped_func(*args, **kwargs):
...
if pre_process:
if "pre_args" in kwargs.keys():
pre_process(*kwargs["pre_args"])
else:
pre_process()
外层的moxing_wrapper和内层的wrapped_func都使用了kwargs这个参数名。
而if “pre_args” in kwargs.keys():这个判断明显的判断外层的装饰器输入的参数,而不是内层的被装饰的函数。
4 解决方案
修改文件 official/cv/YOLOv5/model_utils/moxing_adapter.py
修改重名的 kwargs ,另外一个可以用其他的名称代替。这里内部函数修改为wrap_kwargs
def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
"""
Moxing wrapper to download dataset and upload outputs.
"""
def wrapper(run_func):
@functools.wraps(run_func)
def wrapped_func(*args, **wrap_kwargs):
# Download data from data_url
if config.enable_modelarts:
if config.data_url:
sync_data(config.data_url, config.data_path)
print("Dataset downloaded: ", os.listdir(config.data_path))
if config.checkpoint_url:
sync_data(config.checkpoint_url, config.load_path)
print("Preload downloaded: ", os.listdir(config.load_path))
if config.train_url:
sync_data(config.train_url, config.output_path)
print("Workspace downloaded: ", os.listdir(config.output_path))
mindspore.set_context(save_graphs_path=os.path.join(config.output_path, str(get_rank_id())))
config.device_num = get_device_num()
config.device_id = get_device_id()
if not os.path.exists(config.output_path):
os.makedirs(config.output_path)
if pre_process:
if "pre_args" in kwargs.keys():
pre_process(*kwargs["pre_args"])
else:
pre_process()
# Run the main function
run_func(*args, **wrap_kwargs)
# Upload data to train_url
if config.enable_modelarts:
if post_process:
if "post_args" in kwargs.keys():
post_process(*kwargs["post_args"])
else:
post_process()
if config.train_url:
print("Start to copy output directory")
sync_data(config.output_path, config.train_url)
return wrapped_func
return wrapper

