prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  support for validate with batch size > 1
  Hi, glad to know we could run the inference with batch size > 1, any plan to support validation during training with batch size > 1? According to 
  https://github.com/open-mmlab/mmdetection/blob/c8511649550834ea168f610411a47a39cf194767/mmdet/apis/train.py#L113-L120
  batch size is set to 1 for validation.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mmdet/apis/train.py`
  Content:
  ```
  1 import random
  2 
  3 import numpy as np
  4 import torch
  5 from mmcv.parallel import MMDataParallel, MMDistributedDataParallel
  6 from mmcv.runner import (HOOKS, DistSamplerSeedHook, EpochBasedRunner,
  7                          Fp16OptimizerHook, OptimizerHook, build_optimizer)
  8 from mmcv.utils import build_from_cfg
  9 
  10 from mmdet.core import DistEvalHook, EvalHook
  11 from mmdet.datasets import build_dataloader, build_dataset
  12 from mmdet.utils import get_root_logger
  13 
  14 
  15 def set_random_seed(seed, deterministic=False):
  16     """Set random seed.
  17 
  18     Args:
  19         seed (int): Seed to be used.
  20         deterministic (bool): Whether to set the deterministic option for
  21             CUDNN backend, i.e., set `torch.backends.cudnn.deterministic`
  22             to True and `torch.backends.cudnn.benchmark` to False.
  23             Default: False.
  24     """
  25     random.seed(seed)
  26     np.random.seed(seed)
  27     torch.manual_seed(seed)
  28     torch.cuda.manual_seed_all(seed)
  29     if deterministic:
  30         torch.backends.cudnn.deterministic = True
  31         torch.backends.cudnn.benchmark = False
  32 
  33 
  34 def train_detector(model,
  35                    dataset,
  36                    cfg,
  37                    distributed=False,
  38                    validate=False,
  39                    timestamp=None,
  40                    meta=None):
  41     logger = get_root_logger(cfg.log_level)
  42 
  43     # prepare data loaders
  44     dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]
  45     if 'imgs_per_gpu' in cfg.data:
  46         logger.warning('"imgs_per_gpu" is deprecated in MMDet V2.0. '
  47                        'Please use "samples_per_gpu" instead')
  48         if 'samples_per_gpu' in cfg.data:
  49             logger.warning(
  50                 f'Got "imgs_per_gpu"={cfg.data.imgs_per_gpu} and '
  51                 f'"samples_per_gpu"={cfg.data.samples_per_gpu}, "imgs_per_gpu"'
  52                 f'={cfg.data.imgs_per_gpu} is used in this experiments')
  53         else:
  54             logger.warning(
  55                 'Automatically set "samples_per_gpu"="imgs_per_gpu"='
  56                 f'{cfg.data.imgs_per_gpu} in this experiments')
  57         cfg.data.samples_per_gpu = cfg.data.imgs_per_gpu
  58 
  59     data_loaders = [
  60         build_dataloader(
  61             ds,
  62             cfg.data.samples_per_gpu,
  63             cfg.data.workers_per_gpu,
  64             # cfg.gpus will be ignored if distributed
  65             len(cfg.gpu_ids),
  66             dist=distributed,
  67             seed=cfg.seed) for ds in dataset
  68     ]
  69 
  70     # put model on gpus
  71     if distributed:
  72         find_unused_parameters = cfg.get('find_unused_parameters', False)
  73         # Sets the `find_unused_parameters` parameter in
  74         # torch.nn.parallel.DistributedDataParallel
  75         model = MMDistributedDataParallel(
  76             model.cuda(),
  77             device_ids=[torch.cuda.current_device()],
  78             broadcast_buffers=False,
  79             find_unused_parameters=find_unused_parameters)
  80     else:
  81         model = MMDataParallel(
  82             model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)
  83 
  84     # build runner
  85     optimizer = build_optimizer(model, cfg.optimizer)
  86     runner = EpochBasedRunner(
  87         model,
  88         optimizer=optimizer,
  89         work_dir=cfg.work_dir,
  90         logger=logger,
  91         meta=meta)
  92     # an ugly workaround to make .log and .log.json filenames the same
  93     runner.timestamp = timestamp
  94 
  95     # fp16 setting
  96     fp16_cfg = cfg.get('fp16', None)
  97     if fp16_cfg is not None:
  98         optimizer_config = Fp16OptimizerHook(
  99             **cfg.optimizer_config, **fp16_cfg, distributed=distributed)
  100     elif distributed and 'type' not in cfg.optimizer_config:
  101         optimizer_config = OptimizerHook(**cfg.optimizer_config)
  102     else:
  103         optimizer_config = cfg.optimizer_config
  104 
  105     # register hooks
  106     runner.register_training_hooks(cfg.lr_config, optimizer_config,
  107                                    cfg.checkpoint_config, cfg.log_config,
  108                                    cfg.get('momentum_config', None))
  109     if distributed:
  110         runner.register_hook(DistSamplerSeedHook())
  111 
  112     # register eval hooks
  113     if validate:
  114         val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))
  115         val_dataloader = build_dataloader(
  116             val_dataset,
  117             samples_per_gpu=1,
  118             workers_per_gpu=cfg.data.workers_per_gpu,
  119             dist=distributed,
  120             shuffle=False)
  121         eval_cfg = cfg.get('evaluation', {})
  122         eval_hook = DistEvalHook if distributed else EvalHook
  123         runner.register_hook(eval_hook(val_dataloader, **eval_cfg))
  124 
  125     # user-defined hooks
  126     if cfg.get('custom_hooks', None):
  127         custom_hooks = cfg.custom_hooks
  128         assert isinstance(custom_hooks, list), \
  129             f'custom_hooks expect list type, but got {type(custom_hooks)}'
  130         for hook_cfg in cfg.custom_hooks:
  131             assert isinstance(hook_cfg, dict), \
  132                 'Each item in custom_hooks expects dict type, but got ' \
  133                 f'{type(hook_cfg)}'
  134             hook_cfg = hook_cfg.copy()
  135             priority = hook_cfg.pop('priority', 'NORMAL')
  136             hook = build_from_cfg(hook_cfg, HOOKS)
  137             runner.register_hook(hook, priority=priority)
  138 
  139     if cfg.resume_from:
  140         runner.resume(cfg.resume_from)
  141     elif cfg.load_from:
  142         runner.load_checkpoint(cfg.load_from)
  143     runner.run(data_loaders, cfg.workflow, cfg.total_epochs)
  144
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/mmdet/apis/train.py b/mmdet/apis/train.py
  --- a/mmdet/apis/train.py
  +++ b/mmdet/apis/train.py
  @@ -8,7 +8,8 @@
   from mmcv.utils import build_from_cfg
   
   from mmdet.core import DistEvalHook, EvalHook
  -from mmdet.datasets import build_dataloader, build_dataset
  +from mmdet.datasets import (build_dataloader, build_dataset,
  +                            replace_ImageToTensor)
   from mmdet.utils import get_root_logger
   
   
  @@ -111,10 +112,16 @@
   
       # register eval hooks
       if validate:
  +        # Support batch_size > 1 in validation
  +        val_samples_per_gpu = cfg.data.val.pop('samples_per_gpu', 1)
  +        if val_samples_per_gpu > 1:
  +            # Replace 'ImageToTensor' to 'DefaultFormatBundle'
  +            cfg.data.val.pipeline = replace_ImageToTensor(
  +                cfg.data.val.pipeline)
           val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))
           val_dataloader = build_dataloader(
               val_dataset,
  -            samples_per_gpu=1,
  +            samples_per_gpu=val_samples_per_gpu,
               workers_per_gpu=cfg.data.workers_per_gpu,
               dist=distributed,
               shuffle=False)
  
verification_info: {"golden_diff": "diff --git a/mmdet/apis/train.py b/mmdet/apis/train.py\n--- a/mmdet/apis/train.py\n+++ b/mmdet/apis/train.py\n@@ -8,7 +8,8 @@\n from mmcv.utils import build_from_cfg\n \n from mmdet.core import DistEvalHook, EvalHook\n-from mmdet.datasets import build_dataloader, build_dataset\n+from mmdet.datasets import (build_dataloader, build_dataset,\n+                            replace_ImageToTensor)\n from mmdet.utils import get_root_logger\n \n \n@@ -111,10 +112,16 @@\n \n     # register eval hooks\n     if validate:\n+        # Support batch_size > 1 in validation\n+        val_samples_per_gpu = cfg.data.val.pop('samples_per_gpu', 1)\n+        if val_samples_per_gpu > 1:\n+            # Replace 'ImageToTensor' to 'DefaultFormatBundle'\n+            cfg.data.val.pipeline = replace_ImageToTensor(\n+                cfg.data.val.pipeline)\n         val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n         val_dataloader = build_dataloader(\n             val_dataset,\n-            samples_per_gpu=1,\n+            samples_per_gpu=val_samples_per_gpu,\n             workers_per_gpu=cfg.data.workers_per_gpu,\n             dist=distributed,\n             shuffle=False)\n", "issue": "support for validate with batch size > 1\nHi, glad to know we could run the inference with batch size > 1, any plan to support validation during training with batch size > 1? According to \r\nhttps://github.com/open-mmlab/mmdetection/blob/c8511649550834ea168f610411a47a39cf194767/mmdet/apis/train.py#L113-L120\r\nbatch size is set to 1 for validation.\n", "before_files": [{"content": "import random\n\nimport numpy as np\nimport torch\nfrom mmcv.parallel import MMDataParallel, MMDistributedDataParallel\nfrom mmcv.runner import (HOOKS, DistSamplerSeedHook, EpochBasedRunner,\n                         Fp16OptimizerHook, OptimizerHook, build_optimizer)\nfrom mmcv.utils import build_from_cfg\n\nfrom mmdet.core import DistEvalHook, EvalHook\nfrom mmdet.datasets import build_dataloader, build_dataset\nfrom mmdet.utils import get_root_logger\n\n\ndef set_random_seed(seed, deterministic=False):\n    \"\"\"Set random seed.\n\n    Args:\n        seed (int): Seed to be used.\n        deterministic (bool): Whether to set the deterministic option for\n            CUDNN backend, i.e., set `torch.backends.cudnn.deterministic`\n            to True and `torch.backends.cudnn.benchmark` to False.\n            Default: False.\n    \"\"\"\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    if deterministic:\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n\n\ndef train_detector(model,\n                   dataset,\n                   cfg,\n                   distributed=False,\n                   validate=False,\n                   timestamp=None,\n                   meta=None):\n    logger = get_root_logger(cfg.log_level)\n\n    # prepare data loaders\n    dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]\n    if 'imgs_per_gpu' in cfg.data:\n        logger.warning('\"imgs_per_gpu\" is deprecated in MMDet V2.0. '\n                       'Please use \"samples_per_gpu\" instead')\n        if 'samples_per_gpu' in cfg.data:\n            logger.warning(\n                f'Got \"imgs_per_gpu\"={cfg.data.imgs_per_gpu} and '\n                f'\"samples_per_gpu\"={cfg.data.samples_per_gpu}, \"imgs_per_gpu\"'\n                f'={cfg.data.imgs_per_gpu} is used in this experiments')\n        else:\n            logger.warning(\n                'Automatically set \"samples_per_gpu\"=\"imgs_per_gpu\"='\n                f'{cfg.data.imgs_per_gpu} in this experiments')\n        cfg.data.samples_per_gpu = cfg.data.imgs_per_gpu\n\n    data_loaders = [\n        build_dataloader(\n            ds,\n            cfg.data.samples_per_gpu,\n            cfg.data.workers_per_gpu,\n            # cfg.gpus will be ignored if distributed\n            len(cfg.gpu_ids),\n            dist=distributed,\n            seed=cfg.seed) for ds in dataset\n    ]\n\n    # put model on gpus\n    if distributed:\n        find_unused_parameters = cfg.get('find_unused_parameters', False)\n        # Sets the `find_unused_parameters` parameter in\n        # torch.nn.parallel.DistributedDataParallel\n        model = MMDistributedDataParallel(\n            model.cuda(),\n            device_ids=[torch.cuda.current_device()],\n            broadcast_buffers=False,\n            find_unused_parameters=find_unused_parameters)\n    else:\n        model = MMDataParallel(\n            model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)\n\n    # build runner\n    optimizer = build_optimizer(model, cfg.optimizer)\n    runner = EpochBasedRunner(\n        model,\n        optimizer=optimizer,\n        work_dir=cfg.work_dir,\n        logger=logger,\n        meta=meta)\n    # an ugly workaround to make .log and .log.json filenames the same\n    runner.timestamp = timestamp\n\n    # fp16 setting\n    fp16_cfg = cfg.get('fp16', None)\n    if fp16_cfg is not None:\n        optimizer_config = Fp16OptimizerHook(\n            **cfg.optimizer_config, **fp16_cfg, distributed=distributed)\n    elif distributed and 'type' not in cfg.optimizer_config:\n        optimizer_config = OptimizerHook(**cfg.optimizer_config)\n    else:\n        optimizer_config = cfg.optimizer_config\n\n    # register hooks\n    runner.register_training_hooks(cfg.lr_config, optimizer_config,\n                                   cfg.checkpoint_config, cfg.log_config,\n                                   cfg.get('momentum_config', None))\n    if distributed:\n        runner.register_hook(DistSamplerSeedHook())\n\n    # register eval hooks\n    if validate:\n        val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n        val_dataloader = build_dataloader(\n            val_dataset,\n            samples_per_gpu=1,\n            workers_per_gpu=cfg.data.workers_per_gpu,\n            dist=distributed,\n            shuffle=False)\n        eval_cfg = cfg.get('evaluation', {})\n        eval_hook = DistEvalHook if distributed else EvalHook\n        runner.register_hook(eval_hook(val_dataloader, **eval_cfg))\n\n    # user-defined hooks\n    if cfg.get('custom_hooks', None):\n        custom_hooks = cfg.custom_hooks\n        assert isinstance(custom_hooks, list), \\\n            f'custom_hooks expect list type, but got {type(custom_hooks)}'\n        for hook_cfg in cfg.custom_hooks:\n            assert isinstance(hook_cfg, dict), \\\n                'Each item in custom_hooks expects dict type, but got ' \\\n                f'{type(hook_cfg)}'\n            hook_cfg = hook_cfg.copy()\n            priority = hook_cfg.pop('priority', 'NORMAL')\n            hook = build_from_cfg(hook_cfg, HOOKS)\n            runner.register_hook(hook, priority=priority)\n\n    if cfg.resume_from:\n        runner.resume(cfg.resume_from)\n    elif cfg.load_from:\n        runner.load_checkpoint(cfg.load_from)\n    runner.run(data_loaders, cfg.workflow, cfg.total_epochs)\n", "path": "mmdet/apis/train.py"}], "after_files": [{"content": "import random\n\nimport numpy as np\nimport torch\nfrom mmcv.parallel import MMDataParallel, MMDistributedDataParallel\nfrom mmcv.runner import (HOOKS, DistSamplerSeedHook, EpochBasedRunner,\n                         Fp16OptimizerHook, OptimizerHook, build_optimizer)\nfrom mmcv.utils import build_from_cfg\n\nfrom mmdet.core import DistEvalHook, EvalHook\nfrom mmdet.datasets import (build_dataloader, build_dataset,\n                            replace_ImageToTensor)\nfrom mmdet.utils import get_root_logger\n\n\ndef set_random_seed(seed, deterministic=False):\n    \"\"\"Set random seed.\n\n    Args:\n        seed (int): Seed to be used.\n        deterministic (bool): Whether to set the deterministic option for\n            CUDNN backend, i.e., set `torch.backends.cudnn.deterministic`\n            to True and `torch.backends.cudnn.benchmark` to False.\n            Default: False.\n    \"\"\"\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    if deterministic:\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n\n\ndef train_detector(model,\n                   dataset,\n                   cfg,\n                   distributed=False,\n                   validate=False,\n                   timestamp=None,\n                   meta=None):\n    logger = get_root_logger(cfg.log_level)\n\n    # prepare data loaders\n    dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]\n    if 'imgs_per_gpu' in cfg.data:\n        logger.warning('\"imgs_per_gpu\" is deprecated in MMDet V2.0. '\n                       'Please use \"samples_per_gpu\" instead')\n        if 'samples_per_gpu' in cfg.data:\n            logger.warning(\n                f'Got \"imgs_per_gpu\"={cfg.data.imgs_per_gpu} and '\n                f'\"samples_per_gpu\"={cfg.data.samples_per_gpu}, \"imgs_per_gpu\"'\n                f'={cfg.data.imgs_per_gpu} is used in this experiments')\n        else:\n            logger.warning(\n                'Automatically set \"samples_per_gpu\"=\"imgs_per_gpu\"='\n                f'{cfg.data.imgs_per_gpu} in this experiments')\n        cfg.data.samples_per_gpu = cfg.data.imgs_per_gpu\n\n    data_loaders = [\n        build_dataloader(\n            ds,\n            cfg.data.samples_per_gpu,\n            cfg.data.workers_per_gpu,\n            # cfg.gpus will be ignored if distributed\n            len(cfg.gpu_ids),\n            dist=distributed,\n            seed=cfg.seed) for ds in dataset\n    ]\n\n    # put model on gpus\n    if distributed:\n        find_unused_parameters = cfg.get('find_unused_parameters', False)\n        # Sets the `find_unused_parameters` parameter in\n        # torch.nn.parallel.DistributedDataParallel\n        model = MMDistributedDataParallel(\n            model.cuda(),\n            device_ids=[torch.cuda.current_device()],\n            broadcast_buffers=False,\n            find_unused_parameters=find_unused_parameters)\n    else:\n        model = MMDataParallel(\n            model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)\n\n    # build runner\n    optimizer = build_optimizer(model, cfg.optimizer)\n    runner = EpochBasedRunner(\n        model,\n        optimizer=optimizer,\n        work_dir=cfg.work_dir,\n        logger=logger,\n        meta=meta)\n    # an ugly workaround to make .log and .log.json filenames the same\n    runner.timestamp = timestamp\n\n    # fp16 setting\n    fp16_cfg = cfg.get('fp16', None)\n    if fp16_cfg is not None:\n        optimizer_config = Fp16OptimizerHook(\n            **cfg.optimizer_config, **fp16_cfg, distributed=distributed)\n    elif distributed and 'type' not in cfg.optimizer_config:\n        optimizer_config = OptimizerHook(**cfg.optimizer_config)\n    else:\n        optimizer_config = cfg.optimizer_config\n\n    # register hooks\n    runner.register_training_hooks(cfg.lr_config, optimizer_config,\n                                   cfg.checkpoint_config, cfg.log_config,\n                                   cfg.get('momentum_config', None))\n    if distributed:\n        runner.register_hook(DistSamplerSeedHook())\n\n    # register eval hooks\n    if validate:\n        # Support batch_size > 1 in validation\n        val_samples_per_gpu = cfg.data.val.pop('samples_per_gpu', 1)\n        if val_samples_per_gpu > 1:\n            # Replace 'ImageToTensor' to 'DefaultFormatBundle'\n            cfg.data.val.pipeline = replace_ImageToTensor(\n                cfg.data.val.pipeline)\n        val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n        val_dataloader = build_dataloader(\n            val_dataset,\n            samples_per_gpu=val_samples_per_gpu,\n            workers_per_gpu=cfg.data.workers_per_gpu,\n            dist=distributed,\n            shuffle=False)\n        eval_cfg = cfg.get('evaluation', {})\n        eval_hook = DistEvalHook if distributed else EvalHook\n        runner.register_hook(eval_hook(val_dataloader, **eval_cfg))\n\n    # user-defined hooks\n    if cfg.get('custom_hooks', None):\n        custom_hooks = cfg.custom_hooks\n        assert isinstance(custom_hooks, list), \\\n            f'custom_hooks expect list type, but got {type(custom_hooks)}'\n        for hook_cfg in cfg.custom_hooks:\n            assert isinstance(hook_cfg, dict), \\\n                'Each item in custom_hooks expects dict type, but got ' \\\n                f'{type(hook_cfg)}'\n            hook_cfg = hook_cfg.copy()\n            priority = hook_cfg.pop('priority', 'NORMAL')\n            hook = build_from_cfg(hook_cfg, HOOKS)\n            runner.register_hook(hook, priority=priority)\n\n    if cfg.resume_from:\n        runner.resume(cfg.resume_from)\n    elif cfg.load_from:\n        runner.load_checkpoint(cfg.load_from)\n    runner.run(data_loaders, cfg.workflow, cfg.total_epochs)\n", "path": "mmdet/apis/train.py"}]}