目录
💜💜1背景
mmseg工程修改变化检测任务时,设置config文件时,运行报错ValueError: Only one of `max_epochs` or `max_iters` can be set.
详细报错信息如下:
fatal: Not a git repository (or any parent up to mount point /data)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
Traceback (most recent call last):
File "/data/XX/anaconda3/envs/openmmlab/lib/python3.8/site-packages/mmcv/utils/registry.py", line 69, in build_from_cfg
return obj_cls(**args)
File "/data/XX/anaconda3/envs/openmmlab/lib/python3.8/site-packages/mmcv/runner/base_runner.py", line 136, in __init__
raise ValueError(
ValueError: Only one of `max_epochs` or `max_iters` can be set.
报错截图:
❤️ ❤️2分析
🔥2.1config查看
报错信息很明显就是说runner设置的有问题,通过打印出来的config信息看到:
runner = dict(type='EpochBasedRunner', max_iters=200, max_epochs=200)
这一句一看就不对,不能同时max_iters和max_epochs保留。
- 如果按照epoch来训练,删除掉max_iters=200即可;
- 如果按照inters来训练,删除掉max_epochs=200即可。
🔥2.2BaseRunner基类
mmcv中Runner类主要有三个:BaseRunner基类,以及继承于它的EpochBasedRunner类和IterBasedRunner类,顾名思义对应着Epoch和iter两种迭代方式。其中train、val、run、save_checkpoint方法由EpochBasedRunner和IterBasedRunner实现。
先快速看一下BaseRunner的构造函数:
def __init__(self,model,optimizer=None,work_dir=None,
logger=None,meta=None,max_iters=None,max_epochs=None):
………………
self.model = model
self.optimizer = optimizer
self.logger = logger
self.meta = meta
# create work_dir
if isinstance(work_dir,str):
self.work_dir = osp.abspath(work_dir)
mmcv.mkdir_or_exist(self.work_dir)
elif work_dir is None:
self.work_dir = None
else:
raise TypeError('"work_dir" must be a str or None')
if hasattr(self.model, 'module'): # 若经DataParallel包装,则获得内部的module名
self._model_name = self.model.module.__class__.__name__
else:
self._model_name = self.model.__class__.__name__
self.timestamp = utils.get_time_str() # 获得初始化时的时间戳
self.mode = None
self._hooks = [] # 就是保存hook类的list了
self._epoch = 0
# 表示经过多少次train epoch,每经过一次train_epoch加1,val_epoch不加
# 特别的IterBasedRunner也用IterLoader类维护了_epoch,每遍历完一次dataloader就加1
# 比如workflow为[('train':1000,'val':200)],len(traindataloader)为100,那么会将经历10个epoch
self._iter = 0
# 表示经过多少次train iter,每经过一次train_iter加1,val_iter不加
self._inner_iter = 0
# 表示一个val epoch 或者 train epoch内,iter的次数
# 经过一个val_iter或者train_iter都加1,经过一个epoch后就归零
if max_epochs is not None and max_iters is not None:
raise ValueError('Only one of `max_epochs` or `max_iters` can be set.') # 不能同时指定
self._max_epochs = max_epochs
# EpochBasedRunner看max_epochs,表示_epoch的最大值,即最多训练的epoch数量
# 比如max_epochs为50,workflow为[('train',2),('val',1)]。那么将经过50/2=25次workflow
self._max_iters = max_iters # IterBasedRunner看max_epochs
self.log_buffer = LogBuffer()
# 维护了一个字典,一到end of epoch 或者 经过n个iter,就把log_buffer写入日志,将由logger_hook处理
可以从BaseRunner的定义可以看到,如果同时指定max_iters和max_epochs,就会报错“Only one of `max_epochs` or `max_iters` can be set.”
if max_epochs is not None and max_iters is not None:
raise ValueError('Only one of `max_epochs` or `max_iters` can be set.') # 不能同时指定
因此找到了报错的源头,就能很好的解决了。跟我们发现的问题位置也是一样的,因此修改方案就是删除其中一种即可。
💚💚3解决
🔥3.1按照epoch
修改config文件为:
runner = dict(type='EpochBasedRunner', max_epochs=200) checkpoint_config = dict(by_epoch=True, interval=1)
这种epoch的计算方式表示总共的迭代轮数为200,保存模型是按照epoch进行模型保存,每1个epoch计算完保存一次模型。
这里要注意:如果你的baserunner定义为按照epoch计算的,那么下面的checkpoint_config最好也是按照epoch进行计算,每一轮或者每几轮都是通过interval参数进行设置的。如果baserunner定义为按照iters计算,那么最好checkpoint_config也与之保持一致。方便对比。
🔥3.2按照iters
或者修改为inters的计算方式。config代码如下:
runner = dict(type='ItersBasedRunner', max_epochs=20000) checkpoint_config = dict(by_epoch=False, interval=2000)
这种iters的计算方式表示总共的迭代次数为20000,保存模型是按照iters进行模型保存,每2000次迭代保存一次模型。
整理不易,欢迎一键三连!!!
送你们一条美丽的--分割线--
🌷🌷🍀🍀🌾🌾🍓🍓🍂🍂🙋🙋🐸🐸🙋🙋💖💖🍌🍌🔔🔔🍉🍉🍭🍭🍋🍋🍇🍇🏆🏆📸📸⛵⛵⭐⭐🍎🍎👍👍🌷🌷