[Feature] Add EvalHook which will be used in downstream projects#739
[Feature] Add EvalHook which will be used in downstream projects#739ZwwWayne merged 18 commits intoopen-mmlab:masterfrom
Conversation
|
It can not be merged util #695 is merged since it uses |
|
A related discuss, open-mmlab/mmaction2#395 (comment). Maybe we need to create rather than symlink |
How about adding an option for such a case? By default, we create a symlink, but in some cases we can cp a new ckpt. And we should also ensure that only one symlink is created over the whole training time. |
178f84d to
c0fb2f8
Compare
Now I think open-mmlab/mmaction2#395 is a good proposal which cp the ckpt. Since mmcv hook has |
I am OK with that. |
|
Please enrich the PR message for this PR as this is a big refactoring for downstream tasks to allow more discussion and for future reference, including its intention, modification, and consequences. |
|
|
|
4148f60 to
97fc044
Compare
|
LGTM if the comments can all be resolved. |
Done |
|
See if @hellock have any comments. |
|
|
Validation has been done in mmcls and the performance remaines as it used to be. Thank you. |
|
Validation has been successfully done in mmdet3d with mmdet's PR: open-mmlab/mmdetection#4806 |
|
Validated in MMSeg. Thx! |
|
This PR is merged as many downstream repos have verified its correctness. Thanks the efforts of all. |
Overview
This PR adds
mmcv/runner/hooks/eval.pyfile andEvalHookandDistEvalHookto MMCV together with related unittest parts. Since those two hooks have been widely used in many MM repos, this PR implements and unifies common functions used in the evaluation part.Design
Model Evaluation performed in OpenMMLab uses
EvalHookandDistEvalHookduring training.In detail, the those hooks are commonly registered in
apis/train.pybyrunner.register_hook(eval_hook(val_dataloader, **eval_cfg)). Users can initialize their models with following steps:cfg.data.val, buildingval_datasetloaderEvalHookusingrunner.register_hook.Once registering it, runner will periodically call the evaluate function to perform evaluation in a fixed mode (by epoch or by iteration, etc.). The high-level workflow of
EvalHookin OpenMMLab is:register
EvalHook-> define evaluation setting (start,interval,by_epoch,save_best, comparison rules, etc.) -> perform evaluationafter_train_iterorafter_train_epoch-> (save the best checkpoint) -> loop back toafter_train_xxxAPIs
EvalHookis the base module, andDistEvalHookis a child class to it. They both inheritHook. Here is the APIs explanation forEvalHook.Initialization
dataloader: The PyTorch dataloader for evaluation. It can be built withbuild_dataloaderwith provided dataloader setting.start: Evaluation starting epoch. It enables evaluation before the training starts ifstart<= the resuming epoch. If set toNone, whether to evaluate is merely decided byinterval.interval: Evaluation interval.by_epoch: Determine whether to perform evaluation by epoch or by iteration. If set to True, it will perform by epoch. Otherwise, by iteration.save_best: If a metric is specified, it would measure the best checkpoint during evaluation. The information about best checkpoint would be save inrunner.meta['hook_msgs']. Options are the evaluation metrics to the validation dataset. e.g.,bbox_mAP,segm_mAPfor bbox detection and instance segmentation.AR@100for proposal recall. Ifsave_bestisauto, the first key of the returnedOrderedDictresult will be used. The interval ofCheckpointHookshould be divisible by that ofEvalHook.rule: Comparison rule for best score. If set toNone, it will infer a reasonable rule. Keys such asacc,top, etc. will be inferred bygreaterrule. Keys containlosswill be inferred bylessrule. Options aregreater,less,None.But Note: Since the rule for downstream repos are different, it may need to overwrite the
self.greater_keysandself.less_keyseval_kwargs: Key word arguments for dataset evaluate function (def evaluate), which will be fed into the evaluate function of the dataset.Other hardcoded inner variables:
rule_map,init_value_map,greater_keysandless_keys.Note that: Since the rule for downstream repos are different, it may need to overwrite these variable due to the specific task.
rule_map: A dict containing comparison function, default as{'greater': lambda x, y: x > y, 'less': lambda x, y: x < y}.init_value_map: The initialized value for comparison, default as{'greater': -inf, 'less': inf}.greater_keys: A list containing some rule keys applied for greater function, which means in these rulesEvalHookregards greater number as the better one. Note that: If a string is one of the rules' substring, it will be applied togreaterfunction. e.g., foracc:top1_acc,top5_acc,mean_accare all applied togreaterrule.less_keys: Similar togreater_keysbut it is forlessrules. e.g., forloss:bce_loss,bmn_lossare all applied tolessrule.before_run
This part is to initialize
runner.meta.hook_msgs, if users determine to save the best checkpoint.before_train_xxx
For
before_train_iterandbefore_train_epochpart. It is mainly to determine whether it is the right time to perform evaluation by examining:by_epochstartto perform evaluationAnd use
self.initial_flagto indicate whether theEvalHookgets into the normal evaluation loop. After getting into the normal evaluation loop,before_train_xxxwill be skipped.after_train_xxx
For
after_train_iterandafter_train_epochpart. It is mainly to inference the model and do evaluation, as well as save the best checkpoint ifsave_bestis specified. In detail, it will call_do_evaluate()and_save_best()._do_evaluate(): inference the model by callingsingle_gpu_test(), do evaluation and call_save_best()_save_best(): compare the score according to the rule, write info intorunner.meta['hook_msgs']and save the best checkpoint in the work_dirFor
DistEvalHook, besides the variable and function mentioned above, it inferences model by callingmulti_gpu_test()and assignstmpdir,gpu_collectformulti_gpu_test()Usages
Users adopt
EvalHookby typing in--validatefor training command, it will callEvalHookin training.Config
To use
EvalHookwith a specific setting, users need to modify theevaluationvariable in config files. like this:the key-value pairs in the dict are corresponding to
EvalHookAPI.Migration
Since the key for determine
greateranlessis related to the downstream task, downstream repos may need to overwrite theself.greater_keysandself.less_keys: