open-mmlab / mmocr

OpenMMLab Text Detection, Recognition and Understanding Toolbox
https://mmocr.readthedocs.io/en/dev-1.x/
Apache License 2.0
4.27k stars 743 forks source link

[Bug] ‘MultiDatasetsEvaluator‘ is not in the metric registry. #1915

Open willow-hu opened 1 year ago

willow-hu commented 1 year ago

Prerequisite

Task

I'm using the official example scripts/configs for the officially supported tasks/models/datasets.

Branch

main branch https://github.com/open-mmlab/mmocr

Environment

The environment is built following the official documentation. (conda, pip)

The message of collect_env.py:

sys.platform: linux
Python: 3.8.16 (default, Mar  2 2023, 03:21:46) [GCC 11.2.0]
CUDA available: True
numpy_random_seed: 2147483648
GPU 0: NVIDIA GeForce RTX 3090
CUDA_HOME: /usr/local/cuda
NVCC: Cuda compilation tools, release 11.6, V11.6.124
GCC: gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
PyTorch: 1.10.1
PyTorch compiling details: PyTorch built with:
  - GCC 7.3
  - C++ Version: 201402
  - Intel(R) oneAPI Math Kernel Library Version 2021.4-Product Build 20210904 for Intel(R) 64 architecture applications
  - Intel(R) MKL-DNN v2.2.3 (Git Hash 7336ca9f055cf1bfa13efb658fe15dc9b41f0740)
  - OpenMP 201511 (a.k.a. OpenMP 4.5)
  - LAPACK is enabled (usually provided by MKL)
  - NNPACK is enabled
  - CPU capability usage: AVX2
  - CUDA Runtime 11.3
  - NVCC architecture flags: -gencode;arch=compute_37,code=sm_37;-gencode;arch=compute_50,code=sm_50;-gencode;arch=compute_60,code=sm_60;-gencode;arch=compute_61,code=sm_61;-gencode;arch=compute_70,code=sm_70;-gencode;arch=compute_75,code=sm_75;-gencode;arch=compute_80,code=sm_80;-gencode;arch=compute_86,code=sm_86;-gencode;arch=compute_37,code=compute_37
  - CuDNN 8.2
  - Magma 2.5.2
  - Build settings: BLAS_INFO=mkl, BUILD_TYPE=Release, CUDA_VERSION=11.3, CUDNN_VERSION=8.2.0, CXX_COMPILER=/opt/rh/devtoolset-7/root/usr/bin/c++, CXX_FLAGS= -Wno-deprecated -fvisibility-inlines-hidden -DUSE_PTHREADPOOL -fopenmp -DNDEBUG -DUSE_KINETO -DUSE_FBGEMM -DUSE_QNNPACK -DUSE_PYTORCH_QNNPACK -DUSE_XNNPACK -DSYMBOLICATE_MOBILE_DEBUG_HANDLE -DEDGE_PROFILER_USE_KINETO -O2 -fPIC -Wno-narrowing -Wall -Wextra -Werror=return-type -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-unused-local-typedefs -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-stringop-overflow -Wno-psabi -Wno-error=pedantic -Wno-error=redundant-decls -Wno-error=old-style-cast -fdiagnostics-color=always -faligned-new -Wno-unused-but-set-variable -Wno-maybe-uninitialized -fno-math-errno -fno-trapping-math -Werror=format -Wno-stringop-overflow, LAPACK_INFO=mkl, PERF_WITH_AVX=1, PERF_WITH_AVX2=1, PERF_WITH_AVX512=1, TORCH_VERSION=1.10.1, USE_CUDA=ON, USE_CUDNN=ON, USE_EXCEPTION_PTR=1, USE_GFLAGS=OFF, USE_GLOG=OFF, USE_MKL=ON, USE_MKLDNN=ON, USE_MPI=OFF, USE_NCCL=ON, USE_NNPACK=ON, USE_OPENMP=ON, 

TorchVision: 0.11.2
OpenCV: 4.7.0
MMEngine: 0.7.3
MMOCR: 1.0.0+d7c59f3

Reproduces the problem - code sample

The config file I used:

_base_ = [
    '../_base_/datasets/mjsynth.py',
    '../_base_/datasets/synthtext.py',
    '../_base_/datasets/cute80.py',
    '../_base_/datasets/iiit5k.py',
    '../_base_/datasets/svt.py',
    '../_base_/datasets/svtp.py',
    '../_base_/datasets/icdar2013.py',
    '../_base_/datasets/icdar2015.py',
    '../_base_/default_runtime.py',
    '../_base_/schedules/schedule_adam_base.py',
    '_base_abinet.py',
]

load_from = 'https://download.openmmlab.com/mmocr/textrecog/abinet/abinet_pretrain-45deac15.pth'  # noqa

optim_wrapper = dict(optimizer=dict(lr=1e-4))
train_cfg = dict(max_epochs=20)
# learning policy
param_scheduler = [
    dict(
        type='LinearLR', end=2, start_factor=0.001,
        convert_to_iter_based=True),
    dict(type='MultiStepLR', milestones=[16, 18], end=20),
]

# dataset settings
train_list = [
    _base_.mjsynth_textrecog_train, _base_.synthtext_an_textrecog_train
]
test_list = [
    _base_.cute80_textrecog_test, _base_.iiit5k_textrecog_test,
    _base_.svt_textrecog_test, _base_.svtp_textrecog_test,
    _base_.icdar2013_textrecog_test, _base_.icdar2015_textrecog_test
]

train_dataset = dict(
    type='ConcatDataset', datasets=train_list, pipeline=_base_.train_pipeline)
test_dataset = dict(
    type='ConcatDataset', datasets=test_list, pipeline=_base_.test_pipeline)

train_dataloader = dict(
    batch_size=192,
    num_workers=32,
    persistent_workers=True,
    sampler=dict(type='DefaultSampler', shuffle=True),
    dataset=train_dataset)

test_dataloader = dict(
    batch_size=1,
    num_workers=4,
    persistent_workers=True,
    drop_last=False,
    sampler=dict(type='DefaultSampler', shuffle=False),
    dataset=test_dataset)

val_dataloader = test_dataloader

val_evaluator = dict(
    dataset_prefixes=['CUTE80', 'IIIT5K', 'SVT', 'SVTP', 'IC13', 'IC15'])
test_evaluator = val_evaluator

auto_scale_lr = dict(base_batch_size=192 * 8)

Reproduces the problem - command or script

The script I wrote:

CUDA_VISIBLE_DEVICES=0 python tools/test.py \
configs/textrecog/abinet/abinet_20e_st-an_mj.py \
weights/abinet_20e_st-an_mj_20221005_012617-ead8c139.pth \
--work-dir results/str/abinet-test \
--save-preds

Reproduces the problem - error message

Traceback (most recent call last):
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/registry/build_functions.py", line 122, in build_from_cfg
    obj = obj_cls(**args)  # type: ignore
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/runner/loops.py", line 413, in __init__
    self.evaluator = runner.build_evaluator(evaluator)  # type: ignore
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/runner/runner.py", line 1297, in build_evaluator
    return Evaluator(evaluator)  # type: ignore
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/evaluator/evaluator.py", line 25, in __init__
    self.metrics.append(METRICS.build(metric))
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/registry/registry.py", line 548, in build
    return self.build_func(cfg, *args, **kwargs, registry=self)
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/registry/build_functions.py", line 100, in build_from_cfg
    raise KeyError(
KeyError: 'MultiDatasetsEvaluator is not in the metric registry. Please check whether the value of `MultiDatasetsEvaluator` is correct or it was registered as expected. More details can be found at https://mmengine.readthedocs.io/en/latest/advanced_tutorials/config.html#import-the-custom-module'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tools/test.py", line 141, in <module>
    main()
  File "tools/test.py", line 137, in main
    runner.test()
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/runner/runner.py", line 1760, in test
    self._test_loop = self.build_test_loop(self._test_loop)  # type: ignore
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/runner/runner.py", line 1563, in build_test_loop
    loop = LOOPS.build(
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/registry/registry.py", line 548, in build
    return self.build_func(cfg, *args, **kwargs, registry=self)
  File "/data/project/users/wenzhehu/envs/mmocr-str/lib/python3.8/site-packages/mmengine/registry/build_functions.py", line 144, in build_from_cfg
    raise type(e)(
KeyError: "class `TestLoop` in mmengine/runner/loops.py: 'MultiDatasetsEvaluator is not in the metric registry. Please check whether the value of `MultiDatasetsEvaluator` is correct or it was registered as expected. More details can be found at https://mmengine.readthedocs.io/en/latest/advanced_tutorials/config.html#import-the-custom-module'"

Additional information

I downloaded the datasets via scripts provided by your repo. And I downloaded the model from the link you provided. It seems that the 'registry' in mmocr is not passed to mmengine?

hatimwen commented 1 year ago

This issue occurs when we use the flag --save-preds and MultiDatasetsEvaluator simultaneously. It appears that these two components are not compatible with each other. You can simply remove --save-preds when running test code for several datasets.

However, if you want to obtain performance results and save pkl files for each dataset individually, you can use the --save-preds flag. In this case, avoid using the MultiDatasetsEvaluator type and instead utilize the Metric type, as shown below:

val_evaluator = [
    dict(type='WordMetric', mode=['exact', 'ignore_case', 'ignore_case_symbol']),
    dict(type='CharMetric')
]

Here, I have a useful but somewhat inelegant solution that you may find helpful:

Modify the following lines in the file mmocr/tools/test.py (lines 114 to 125 in version d7c59f3):

https://github.com/open-mmlab/mmocr/blob/d7c59f3325aaf4cbf6ddd3ec69f03230bc582d19/tools/test.py#L114-L125

Replace it with:

    # save predictions
    if args.save_preds:
        dump_metric = dict(
            type='DumpResults',
            out_file_path=osp.join(
                cfg.work_dir,
                f'{osp.basename(args.checkpoint)}_predictions.pkl'))
        if isinstance(cfg.test_evaluator, dict) and cfg.test_evaluator['type'] == 'MultiDatasetsEvaluator':
            cfg.test_evaluator['metrics'].append(dump_metric)
            if isinstance(cfg.test_evaluator['dataset_prefixes'], str):
                cfg.test_evaluator['dataset_prefixes'] = [cfg.test_evaluator['dataset_prefixes']]
        elif isinstance(cfg.test_evaluator, (list, tuple)):
            cfg.test_evaluator = list(cfg.test_evaluator)
            cfg.test_evaluator.append(dump_metric)
        else:
            cfg.test_evaluator = [cfg.test_evaluator, dump_metric]