Commit 95efda42 authored by zhangwenwei's avatar zhangwenwei
Browse files

Update tweaks in documentation

parent 219deef1
...@@ -71,22 +71,22 @@ roi_heads ...@@ -71,22 +71,22 @@ roi_heads
:members: :members:
roi_heads.bbox_heads roi_heads.bbox_heads
^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
.. automodule:: mmdet3d.models.roi_heads.bbox_heads .. automodule:: mmdet3d.models.roi_heads.bbox_heads
:members: :members:
roi_heads.mask_heads roi_heads.mask_heads
^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
.. automodule:: mmdet3d.models.roi_heads.mask_heads .. automodule:: mmdet3d.models.roi_heads.mask_heads
:members: :members:
roi_heads.roi_extractors roi_heads.roi_extractors
^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
.. automodule:: mmdet3d.models.roi_heads.roi_extractors .. automodule:: mmdet3d.models.roi_heads.roi_extractors
:members: :members:
fusion_layers fusion_layers
^^^^^^^^^^ ^^^^^^^^^^^^^
.. automodule:: mmdet3d.models.fusion_layers .. automodule:: mmdet3d.models.fusion_layers
:members: :members:
...@@ -96,11 +96,11 @@ losses ...@@ -96,11 +96,11 @@ losses
:members: :members:
middle_encoders middle_encoders
^^^^^^^^^^ ^^^^^^^^^^^^^^^
.. automodule:: mmdet3d.models.middle_encoders .. automodule:: mmdet3d.models.middle_encoders
:members: :members:
model_utils model_utils
^^^^^^^^^^ ^^^^^^^^^^^^^
.. automodule:: mmdet3d.models.model_utils .. automodule:: mmdet3d.models.model_utils
:members: :members:
...@@ -24,7 +24,7 @@ We compare our implementation of VoteNet with [votenet](https://github.com/faceb ...@@ -24,7 +24,7 @@ We compare our implementation of VoteNet with [votenet](https://github.com/faceb
+================+=====================+====================+========+ +================+=====================+====================+========+
| MMDetection3D | 358 | 17 | 35.8 | | MMDetection3D | 358 | 17 | 35.8 |
+----------------+---------------------+--------------------+--------+ +----------------+---------------------+--------------------+--------+
| votenet_ | 77 | 3 | 31.5 | | votenet | 77 | 3 | 31.5 |
+----------------+---------------------+--------------------+--------+ +----------------+---------------------+--------------------+--------+
``` ```
...@@ -47,13 +47,13 @@ performance on 3 classes. ...@@ -47,13 +47,13 @@ performance on 3 classes.
``` ```
```eval_rst ```eval_rst
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
| Implementation | Training (sample/s) | Testing (sample/s) | | Implementation | Training (sample/s) | Testing (sample/s) |
+================+=====================+====================+ +================+=====================+====================+
| MMDetection3D | 107 | 45 | | MMDetection3D | 107 | 45 |
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
| OpenPCDet | 44 | 25 | | OpenPCDet | 44 | 25 |
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
``` ```
### SECOND ### SECOND
...@@ -63,36 +63,36 @@ So we only compare with [OpenPCDet](https://github.com/open-mmlab/OpenPCDet/tree ...@@ -63,36 +63,36 @@ So we only compare with [OpenPCDet](https://github.com/open-mmlab/OpenPCDet/tree
condition following the KITTI benchmark and compare average AP over all classes on moderate condition for condition following the KITTI benchmark and compare average AP over all classes on moderate condition for
performance on 3 classes. performance on 3 classes.
```eval_rst ```eval_rst
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
| Implementation | Training (sample/s) | Testing (sample/s) | | Implementation | Training (sample/s) | Testing (sample/s) |
+================+=====================+====================+ +================+=====================+====================+
| MMDetection3D | 40 | 27 | | MMDetection3D | 40 | 27 |
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
| OpenPCDet | 30 | 32 | | OpenPCDet | 30 | 32 |
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
``` ```
### Part-A2 ### Part-A2
We benchmark Part-A2 with that in [OpenPCDet](https://github.com/open-mmlab/OpenPCDet/tree/b32fbddbe06183507bad433ed99b407cbc2175c2). We report the AP on moderate condition following the KITTI benchmark We benchmark Part-A2 with that in [OpenPCDet](https://github.com/open-mmlab/OpenPCDet/tree/b32fbddbe06183507bad433ed99b407cbc2175c2). We report the AP on moderate condition following the KITTI benchmark
and compare average AP over all classes on moderate condition for performance on 3 classes. and compare average AP over all classes on moderate condition for performance on 3 classes.
```eval_rst ```eval_rst
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
| Implementation | Training (sample/s) | Testing (sample/s) | | Implementation | Training (sample/s) | Testing (sample/s) |
+================+=====================+====================+ +================+=====================+====================+
| MMDetection3D | 17 | 11 | | MMDetection3D | 17 | 11 |
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
| OpenPCDet | 14 | 13 | | OpenPCDet | 14 | 13 |
+----------------+---------------------+--------------------+ +----------------+---------------------+--------------------+
``` ```
## Details of Comparison ## Details of Comparison
### Modification for Calculating Speed ### Modification for Calculating Speed
* __Det3D__: At commit 255c593 * __Det3D__: At commit [255c593]()
* __OpenPCDet__: At commit [b32fbddb](https://github.com/open-mmlab/OpenPCDet/tree/b32fbddbe06183507bad433ed99b407cbc2175c2) * __OpenPCDet__: At commit [b32fbddb](https://github.com/open-mmlab/OpenPCDet/tree/b32fbddbe06183507bad433ed99b407cbc2175c2)
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
# #
import os import os
import sys import sys
from m2r import MdInclude
from recommonmark.transform import AutoStructify
sys.path.insert(0, os.path.abspath('..')) sys.path.insert(0, os.path.abspath('..'))
...@@ -36,6 +38,7 @@ extensions = [ ...@@ -36,6 +38,7 @@ extensions = [
'sphinx.ext.viewcode', 'sphinx.ext.viewcode',
'recommonmark', 'recommonmark',
'sphinx_markdown_tables', 'sphinx_markdown_tables',
'sphinx.ext.autosectionlabel',
] ]
autodoc_mock_imports = [ autodoc_mock_imports = [
...@@ -46,6 +49,7 @@ autodoc_mock_imports = [ ...@@ -46,6 +49,7 @@ autodoc_mock_imports = [
'mmdet3d.ops.interpolate', 'mmdet3d.ops.roiaware_pool3d', 'mmdet3d.ops.interpolate', 'mmdet3d.ops.roiaware_pool3d',
'mmdet3d.ops.spconv', 'mmdet3d.ops.voxel.voxel_layer', 'mmdet3d.ops.iou3d' 'mmdet3d.ops.spconv', 'mmdet3d.ops.voxel.voxel_layer', 'mmdet3d.ops.iou3d'
] ]
autosectionlabel_prefix_document = True
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ['_templates']
...@@ -77,3 +81,16 @@ html_theme = 'sphinx_rtd_theme' ...@@ -77,3 +81,16 @@ html_theme = 'sphinx_rtd_theme'
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ['_static']
def setup(app):
app.add_config_value('no_underscore_emphasis', False, 'env')
app.add_config_value('m2r_parse_relative_links', False, 'env')
app.add_config_value('m2r_anonymous_references', False, 'env')
app.add_config_value('m2r_disable_inline_math', False, 'env')
app.add_directive('mdinclude', MdInclude)
app.add_config_value('recommonmark_config', {
'auto_toc_tree_section': 'Contents',
'enable_eval_rst': True,
}, True)
app.add_transform(AutoStructify)
\ No newline at end of file
...@@ -50,7 +50,7 @@ For `20e`, initial learning rate decays by a factor of 10 at the 16th and 19th e ...@@ -50,7 +50,7 @@ For `20e`, initial learning rate decays by a factor of 10 at the 16th and 19th e
Sometimes, you may set `_delete_=True` to ignore some of fields in base configs. Sometimes, you may set `_delete_=True` to ignore some of fields in base configs.
You may refer to [mmcv](https://mmcv.readthedocs.io/en/latest/utils.html#inherit-from-base-config-with-ignored-fields) for simple inllustration. You may refer to [mmcv](https://mmcv.readthedocs.io/en/latest/utils.html#inherit-from-base-config-with-ignored-fields) for simple inllustration.
In MMDetection, for example, to change the backbone of Mask R-CNN with the following config. In MMDetection or MMDetection3D, for example, to change the backbone of Mask R-CNN with the following config.
```python ```python
model = dict( model = dict(
......
...@@ -63,25 +63,28 @@ mmdetection3d ...@@ -63,25 +63,28 @@ mmdetection3d
``` ```
Download nuScenes V1.0 full dataset data [HERE]( https://www.nuscenes.org/download). Prepare nuscenes data by running Download nuScenes V1.0 full dataset data [HERE]( https://www.nuscenes.org/download). Prepare nuscenes data by running
```bash ```bash
python tools/create_data.py nuscenes --root-path ./data/nuscenes --out-dir ./data/nuscenes --extra-tag nuscenes python tools/create_data.py nuscenes --root-path ./data/nuscenes --out-dir ./data/nuscenes --extra-tag nuscenes
``` ```
Download KITTI 3D detection data [HERE](http://www.cvlibs.net/datasets/kitti/eval_object.php?obj_benchmark=3d). Prepare kitti data by running Download KITTI 3D detection data [HERE](http://www.cvlibs.net/datasets/kitti/eval_object.php?obj_benchmark=3d). Prepare kitti data by running
```bash ```bash
python tools/create_data.py kitti --root-path ./data/kitti --out-dir ./data/kitti --extra-tag kitti python tools/create_data.py kitti --root-path ./data/kitti --out-dir ./data/kitti --extra-tag kitti
``` ```
Download Lyft 3D detection data [HERE](https://www.kaggle.com/c/3d-object-detection-for-autonomous-vehicles/data). Prepare Lyft data by running Download Lyft 3D detection data [HERE](https://www.kaggle.com/c/3d-object-detection-for-autonomous-vehicles/data). Prepare Lyft data by running
```bash ```bash
python tools/create_data.py lyft --root-path ./data/lyft --out-dir ./data/lyft --extra-tag lyft --version v1.01 python tools/create_data.py lyft --root-path ./data/lyft --out-dir ./data/lyft --extra-tag lyft --version v1.01
``` ```
Note that we follow the original folder names for clear organization. Please rename the raw folders as shown above.
To prepare scannet data, please see [scannet](../data/scannet/README.md). Note that we follow the original folder names for clear organization. Please rename the raw folders as shown above.
To prepare sunrgbd data, please see [sunrgbd](../data/sunrgbd/README.md). To prepare scannet data, please see [scannet](https://github.com/open-mmlab/mmdetection3d/data/scannet/README.md).
To prepare sunrgbd data, please see [sunrgbd](https://github.com/open-mmlab/mmdetection3d/data/sunrgbd/README.md).
For using custom datasets, please refer to [Tutorials 2: Adding New Dataset](tutorials/new_dataset.md). For using custom datasets, please refer to [Tutorials 2: Adding New Dataset](tutorials/new_dataset.md).
...@@ -112,71 +115,70 @@ Optional arguments: ...@@ -112,71 +115,70 @@ Optional arguments:
- `--show`: If specified, detection results will be plotted in the silient mode. It is only applicable to single GPU testing and used for debugging and visualization. This should be used with `--show-dir`. - `--show`: If specified, detection results will be plotted in the silient mode. It is only applicable to single GPU testing and used for debugging and visualization. This should be used with `--show-dir`.
- `--show-dir`: If specified, detection results will be plotted on the `***_points.obj` and `***_pred.ply` files in the specified directory. It is only applicable to single GPU testing and used for debugging and visualization. You do NOT need a GUI available in your environment for using this option. - `--show-dir`: If specified, detection results will be plotted on the `***_points.obj` and `***_pred.ply` files in the specified directory. It is only applicable to single GPU testing and used for debugging and visualization. You do NOT need a GUI available in your environment for using this option.
Examples: Examples:
Assume that you have already downloaded the checkpoints to the directory `checkpoints/`. Assume that you have already downloaded the checkpoints to the directory `checkpoints/`.
1. Test votenet on ScanNet and save the points and prediction visualization results. 1. Test votenet on ScanNet and save the points and prediction visualization results.
```shell ```shell
python tools/test.py configs/votenet/votenet_8x8_scannet-3d-18class.py \ python tools/test.py configs/votenet/votenet_8x8_scannet-3d-18class.py \
checkpoints/votenet_8x8_scannet-3d-18class_20200620_230238-2cea9c3a.pth \ checkpoints/votenet_8x8_scannet-3d-18class_20200620_230238-2cea9c3a.pth \
--show --show-dir ./data/scannet/show_results --show --show-dir ./data/scannet/show_results
``` ```
2. Test votenet on ScanNet, save the points, prediction, groundtruth visualization results, and evaluate the mAP. 2. Test votenet on ScanNet, save the points, prediction, groundtruth visualization results, and evaluate the mAP.
```shell ```shell
python tools/test.py configs/votenet/votenet_8x8_scannet-3d-18class.py \ python tools/test.py configs/votenet/votenet_8x8_scannet-3d-18class.py \
checkpoints/votenet_8x8_scannet-3d-18class_20200620_230238-2cea9c3a.pth \ checkpoints/votenet_8x8_scannet-3d-18class_20200620_230238-2cea9c3a.pth \
--eval mAP --eval mAP
--options 'show=True' 'out_dir=./data/scannet/show_results' --options 'show=True' 'out_dir=./data/scannet/show_results'
``` ```
3. Test votenet on ScanNet (without saving the test results) and evaluate the mAP. 3. Test votenet on ScanNet (without saving the test results) and evaluate the mAP.
```shell ```shell
python tools/test.py configs/votenet/votenet_8x8_scannet-3d-18class.py \ python tools/test.py configs/votenet/votenet_8x8_scannet-3d-18class.py \
checkpoints/votenet_8x8_scannet-3d-18class_20200620_230238-2cea9c3a.pth \ checkpoints/votenet_8x8_scannet-3d-18class_20200620_230238-2cea9c3a.pth \
--eval mAP --eval mAP
``` ```
4. Test SECOND with 8 GPUs, and evaluate the mAP. 4. Test SECOND with 8 GPUs, and evaluate the mAP.
```shell ```shell
./tools/slurm_test.sh ${PARTITION} ${JOB_NAME} configs/second/hv_second_secfpn_6x8_80e_kitti-3d-3class.py \ ./tools/slurm_test.sh ${PARTITION} ${JOB_NAME} configs/second/hv_second_secfpn_6x8_80e_kitti-3d-3class.py \
checkpoints/hv_second_secfpn_6x8_80e_kitti-3d-3class_20200620_230238-9208083a.pth \ checkpoints/hv_second_secfpn_6x8_80e_kitti-3d-3class_20200620_230238-9208083a.pth \
--out results.pkl --eval mAP --out results.pkl --eval mAP
``` ```
5. Test PointPillars on nuscenes with 8 GPUs, and generate the json file to be submit to the official evaluation server. 5. Test PointPillars on nuscenes with 8 GPUs, and generate the json file to be submit to the official evaluation server.
```shell ```shell
./tools/slurm_test.sh ${PARTITION} ${JOB_NAME} configs/pointpillars/hv_pointpillars_fpn_sbn-all_4x8_2x_nus-3d.py \ ./tools/slurm_test.sh ${PARTITION} ${JOB_NAME} configs/pointpillars/hv_pointpillars_fpn_sbn-all_4x8_2x_nus-3d.py \
checkpoints/hv_pointpillars_fpn_sbn-all_4x8_2x_nus-3d_20200620_230405-2fa62f3d.pth \ checkpoints/hv_pointpillars_fpn_sbn-all_4x8_2x_nus-3d_20200620_230405-2fa62f3d.pth \
--format-only --options 'jsonfile_prefix=./pointpillars_nuscenes_results' --format-only --options 'jsonfile_prefix=./pointpillars_nuscenes_results'
``` ```
The generated results be under `./pointpillars_nuscenes_results` directory. The generated results be under `./pointpillars_nuscenes_results` directory.
6. Test SECOND on KITTI with 8 GPUs, and generate the pkl files and submission datas to be submit to the official evaluation server. 6. Test SECOND on KITTI with 8 GPUs, and generate the pkl files and submission datas to be submit to the official evaluation server.
```shell ```shell
./tools/slurm_test.sh ${PARTITION} ${JOB_NAME} configs/second/hv_second_secfpn_6x8_80e_kitti-3d-3class.py \ ./tools/slurm_test.sh ${PARTITION} ${JOB_NAME} configs/second/hv_second_secfpn_6x8_80e_kitti-3d-3class.py \
checkpoints/hv_second_secfpn_6x8_80e_kitti-3d-3class_20200620_230238-9208083a.pth \ checkpoints/hv_second_secfpn_6x8_80e_kitti-3d-3class_20200620_230238-9208083a.pth \
--format-only --options 'pklfile_prefix=./second_kitti_results' 'submission_prefix=./second_kitti_results' --format-only --options 'pklfile_prefix=./second_kitti_results' 'submission_prefix=./second_kitti_results'
``` ```
The generated results be under `./second_kitti_results` directory. The generated results be under `./second_kitti_results` directory.
### Visualization ### Visualization
To see the SUNRGBD, ScanNet or KITTI points and detection results, you can run the following command To see the SUNRGBD, ScanNet or KITTI points and detection results, you can run the following command
```bash ```bash
python tools/test.py ${CONFIG_FILE} ${CKPT_PATH} --show --show-dir ${SHOW_DIR} python tools/test.py ${CONFIG_FILE} ${CKPT_PATH} --show --show-dir ${SHOW_DIR}
``` ```
Aftering running this command, plotted results ***_points.obj and ***_pred.ply files in `${SHOW_DIR}`. Aftering running this command, plotted results ***_points.obj and ***_pred.ply files in `${SHOW_DIR}`.
...@@ -202,7 +204,7 @@ Examples: ...@@ -202,7 +204,7 @@ Examples:
```shell ```shell
python demo/pcd_demo.py demo/kitti_000008.bin configs/second/hv_second_secfpn_6x8_80e_kitti-3d-car.py \ python demo/pcd_demo.py demo/kitti_000008.bin configs/second/hv_second_secfpn_6x8_80e_kitti-3d-car.py \
checkpoints/epoch_40.pth checkpoints/hv_second_secfpn_6x8_80e_kitti-3d-3class_20200620_230238-9208083a.pth
``` ```
...@@ -238,49 +240,6 @@ for frame in video: ...@@ -238,49 +240,6 @@ for frame in video:
A notebook demo can be found in [demo/inference_demo.ipynb](https://github.com/open-mmlab/mmdetection/blob/master/demo/inference_demo.ipynb). A notebook demo can be found in [demo/inference_demo.ipynb](https://github.com/open-mmlab/mmdetection/blob/master/demo/inference_demo.ipynb).
#### Asynchronous interface - supported for Python 3.7+
Async interface allows not to block CPU on GPU bound inference code and enables better CPU/GPU utilization for single threaded application. Inference can be done concurrently either between different input data samples or between different models of some inference pipeline.
See `tests/async_benchmark.py` to compare the speed of synchronous and asynchronous interfaces.
```python
import asyncio
import torch
from mmdet.apis import init_detector, async_inference_detector
from mmdet.utils.contextmanagers import concurrent
async def main():
config_file = 'configs/faster_rcnn_r50_fpn_1x_coco.py'
checkpoint_file = 'checkpoints/faster_rcnn_r50_fpn_1x_20181010-3d1b3351.pth'
device = 'cuda:0'
model = init_detector(config_file, checkpoint=checkpoint_file, device=device)
# queue is used for concurrent inference of multiple images
streamqueue = asyncio.Queue()
# queue size defines concurrency level
streamqueue_size = 3
for _ in range(streamqueue_size):
streamqueue.put_nowait(torch.cuda.Stream(device=device))
# test a single image and show the results
img = 'test.jpg' # or img = mmcv.imread(img), which will only load it once
async with concurrent(streamqueue):
result = await async_inference_detector(model, img)
# visualize the results in a new window
model.show_result(img, result)
# or save the visualization results to image files
model.show_result(img, result, out_file='result.jpg')
asyncio.run(main())
```
## Train a model ## Train a model
MMDetection implements distributed training and non-distributed training, MMDetection implements distributed training and non-distributed training,
...@@ -294,7 +253,7 @@ By default we evaluate the model on the validation set after each epoch, you can ...@@ -294,7 +253,7 @@ By default we evaluate the model on the validation set after each epoch, you can
evaluation = dict(interval=12) # This evaluate the model per 12 epoch. evaluation = dict(interval=12) # This evaluate the model per 12 epoch.
``` ```
**\*Important\***: The default learning rate in config files is for 8 GPUs and 2 img/gpu (batch size = 8*2 = 16). **\*Important\***: The default learning rate in config files is for 8 GPUs and the exact batch size is marked by the config's file name, e.g. '2x8' means 2 samples per GPU using 8 GPUs.
According to the [Linear Scaling Rule](https://arxiv.org/abs/1706.02677), you need to set the learning rate proportional to the batch size if you use different GPUs or images per GPU, e.g., lr=0.01 for 4 GPUs * 2 img/gpu and lr=0.08 for 16 GPUs * 4 img/gpu. According to the [Linear Scaling Rule](https://arxiv.org/abs/1706.02677), you need to set the learning rate proportional to the batch size if you use different GPUs or images per GPU, e.g., lr=0.01 for 4 GPUs * 2 img/gpu and lr=0.08 for 16 GPUs * 4 img/gpu.
### Train with a single GPU ### Train with a single GPU
...@@ -316,6 +275,7 @@ Optional arguments are: ...@@ -316,6 +275,7 @@ Optional arguments are:
- `--no-validate` (**not suggested**): By default, the codebase will perform evaluation at every k (default value is 1, which can be modified like [this](https://github.com/open-mmlab/mmdetection/blob/master/configs/mask_rcnn/mask_rcnn_r50_fpn_1x_coco.py#L174)) epochs during the training. To disable this behavior, use `--no-validate`. - `--no-validate` (**not suggested**): By default, the codebase will perform evaluation at every k (default value is 1, which can be modified like [this](https://github.com/open-mmlab/mmdetection/blob/master/configs/mask_rcnn/mask_rcnn_r50_fpn_1x_coco.py#L174)) epochs during the training. To disable this behavior, use `--no-validate`.
- `--work-dir ${WORK_DIR}`: Override the working directory specified in the config file. - `--work-dir ${WORK_DIR}`: Override the working directory specified in the config file.
- `--resume-from ${CHECKPOINT_FILE}`: Resume from a previous checkpoint file. - `--resume-from ${CHECKPOINT_FILE}`: Resume from a previous checkpoint file.
- `--options 'Key=value'`: Overide some settings in the used config.
Difference between `resume-from` and `load-from`: Difference between `resume-from` and `load-from`:
`resume-from` loads both the model weights and optimizer status, and the epoch is also inherited from the specified checkpoint. It is usually used for resuming the training process that is interrupted accidentally. `resume-from` loads both the model weights and optimizer status, and the epoch is also inherited from the specified checkpoint. It is usually used for resuming the training process that is interrupted accidentally.
...@@ -353,24 +313,35 @@ CUDA_VISIBLE_DEVICES=0,1,2,3 PORT=29500 ./tools/dist_train.sh ${CONFIG_FILE} 4 ...@@ -353,24 +313,35 @@ CUDA_VISIBLE_DEVICES=0,1,2,3 PORT=29500 ./tools/dist_train.sh ${CONFIG_FILE} 4
CUDA_VISIBLE_DEVICES=4,5,6,7 PORT=29501 ./tools/dist_train.sh ${CONFIG_FILE} 4 CUDA_VISIBLE_DEVICES=4,5,6,7 PORT=29501 ./tools/dist_train.sh ${CONFIG_FILE} 4
``` ```
If you use launch training jobs with Slurm, you need to modify the config files (usually the 6th line from the bottom in config files) to set different communication ports. If you use launch training jobs with Slurm, there are two ways to specify the ports.
In `config1.py`, 1. Modify the config files (usually the 6th line from the bottom in config files) to set different communication ports.
```python
dist_params = dict(backend='nccl', port=29500)
```
In `config2.py`, In `config1.py`,
```python
dist_params = dict(backend='nccl', port=29501)
```
Then you can launch two jobs with `config1.py` ang `config2.py`. ```python
dist_params = dict(backend='nccl', port=29500)
```
```shell In `config2.py`,
CUDA_VISIBLE_DEVICES=0,1,2,3 GPUS=4 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config1.py ${WORK_DIR}
CUDA_VISIBLE_DEVICES=4,5,6,7 GPUS=4 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config2.py ${WORK_DIR} ```python
``` dist_params = dict(backend='nccl', port=29501)
```
Then you can launch two jobs with `config1.py` ang `config2.py`.
```shell
CUDA_VISIBLE_DEVICES=0,1,2,3 GPUS=4 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config1.py ${WORK_DIR}
CUDA_VISIBLE_DEVICES=4,5,6,7 GPUS=4 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config2.py ${WORK_DIR}
```
2. Set the port through `--options`. This is more recommended since it does not change the original configs.
```shell
CUDA_VISIBLE_DEVICES=0,1,2,3 GPUS=4 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config1.py ${WORK_DIR} --options 'dist_params.port=29500'
CUDA_VISIBLE_DEVICES=4,5,6,7 GPUS=4 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config2.py ${WORK_DIR} --options 'dist_params.port=29501'
```
## Useful tools ## Useful tools
...@@ -390,21 +361,21 @@ Examples: ...@@ -390,21 +361,21 @@ Examples:
- Plot the classification loss of some run. - Plot the classification loss of some run.
```shell ```shell
python tools/analyze_logs.py plot_curve log.json --keys loss_cls --legend loss_cls python tools/analyze_logs.py plot_curve log.json --keys loss_cls --legend loss_cls
``` ```
- Plot the classification and regression loss of some run, and save the figure to a pdf. - Plot the classification and regression loss of some run, and save the figure to a pdf.
```shell ```shell
python tools/analyze_logs.py plot_curve log.json --keys loss_cls loss_bbox --out losses.pdf python tools/analyze_logs.py plot_curve log.json --keys loss_cls loss_bbox --out losses.pdf
``` ```
- Compare the bbox mAP of two runs in the same figure. - Compare the bbox mAP of two runs in the same figure.
```shell ```shell
python tools/analyze_logs.py plot_curve log1.json log2.json --keys bbox_mAP --legend run1 run2 python tools/analyze_logs.py plot_curve log1.json log2.json --keys bbox_mAP --legend run1 run2
``` ```
You can also compute the average training speed. You can also compute the average training speed.
...@@ -441,20 +412,6 @@ python tools/publish_model.py work_dirs/faster_rcnn/latest.pth faster_rcnn_r50_f ...@@ -441,20 +412,6 @@ python tools/publish_model.py work_dirs/faster_rcnn/latest.pth faster_rcnn_r50_f
The final output filename will be `faster_rcnn_r50_fpn_1x_20190801-{hash id}.pth`. The final output filename will be `faster_rcnn_r50_fpn_1x_20190801-{hash id}.pth`.
### Test the robustness of detectors
Please refer to [robustness_benchmarking.md](robustness_benchmarking.md).
### Convert to ONNX (experimental)
We provide a script to convert model to [ONNX](https://github.com/onnx/onnx) format. The converted model could be visualized by tools like [Netron](https://github.com/lutzroeder/netron).
```shell
python tools/pytorch2onnx.py ${CONFIG_FILE} ${CHECKPOINT_FILE} --out ${ONNX_FILE} [--shape ${INPUT_SHAPE}]
```
**Note**: This tool is still experimental. Customized operators are not supported for now. We set `use_torchvision=True` on-the-fly for `RoIPool` and `RoIAlign`.
## Tutorials ## Tutorials
Currently, we provide four tutorials for users to [finetune models](tutorials/finetune.md), [add new dataset](tutorials/new_dataset.md), [design data pipeline](tutorials/data_pipeline.md) and [add new modules](tutorials/new_modules.md). Currently, we provide four tutorials for users to [finetune models](tutorials/finetune.md), [add new dataset](tutorials/new_dataset.md), [design data pipeline](tutorials/data_pipeline.md) and [add new modules](tutorials/new_modules.md).
......
...@@ -38,24 +38,14 @@ test_pipeline = [ ...@@ -38,24 +38,14 @@ test_pipeline = [
dict( dict(
type='MultiScaleFlipAug', type='MultiScaleFlipAug',
img_scale=(1333, 800), img_scale=(1333, 800),
pts_scale_ratio=1.0,
flip=False, flip=False,
pcd_horizontal_flip=False,
pcd_vertical_flip=False,
transforms=[ transforms=[
dict( dict(type='Resize', keep_ratio=True),
type='GlobalRotScaleTrans', dict(type='RandomFlip'),
rot_range=[0, 0], dict(type='Normalize', **img_norm_cfg),
scale_ratio_range=[1., 1.], dict(type='Pad', size_divisor=32),
translation_std=[0, 0, 0]), dict(type='ImageToTensor', keys=['img']),
dict(type='RandomFlip3D'), dict(type='Collect', keys=['img']),
dict(
type='PointsRangeFilter', point_cloud_range=point_cloud_range),
dict(
type='DefaultFormatBundle3D',
class_names=class_names,
with_label=False),
dict(type='Collect3D', keys=['points'])
]) ])
] ]
``` ```
...@@ -127,13 +117,12 @@ For each operation, we list the related dict fields that are added/updated/remov ...@@ -127,13 +117,12 @@ For each operation, we list the related dict fields that are added/updated/remov
- update: img, proposals, gt_bboxes, gt_bboxes_ignore, gt_labels, gt_masks, gt_semantic_seg - update: img, proposals, gt_bboxes, gt_bboxes_ignore, gt_labels, gt_masks, gt_semantic_seg
`Collect` `Collect`
- add: img_metas (the keys of img_metas is specified by `meta_keys`) - add: img_meta (the keys of img_meta is specified by `meta_keys`)
- remove: all other keys except for those specified by `keys` - remove: all other keys except for those specified by `keys`
### Test time augmentation ### Test time augmentation
`MultiScaleFlipAug3D` `MultiScaleFlipAug`
- update: all the dict fields (update values to the collection of augmented data)
## Extend and use custom pipelines ## Extend and use custom pipelines
......
# Tutorial 1: Finetuning Models # Tutorial 1: Finetuning Models
Detectors pre-trained on the COCO dataset can serve as a good pre-trained model for other datasets, e.g., CityScapes and KITTI Dataset. Detectors pre-trained on the COCO dataset can serve as a good pre-trained model for other datasets, e.g., CityScapes and KITTI Dataset.
This tutorial provides instruction for users to use the models provided in the [Model Zoo](../model_zoo.md) for other datasets to obatin better performance. This tutorial provides instruction for users to use the models provided in the [Model Zoo](../model_zoo.md) for other datasets to obtain better performance.
There are two steps to finetune a model on a new dataset. There are two steps to finetune a model on a new dataset.
- Add support for the new dataset following [Tutorial 2: Adding New Dataset](new_dataset.md). - Add support for the new dataset following [Tutorial 2: Adding New Dataset](new_dataset.md).
...@@ -11,7 +11,7 @@ There are two steps to finetune a model on a new dataset. ...@@ -11,7 +11,7 @@ There are two steps to finetune a model on a new dataset.
Take the finetuning process on Cityscapes Dataset as an example, the users need to modify five parts in the config. Take the finetuning process on Cityscapes Dataset as an example, the users need to modify five parts in the config.
## Inherit base configs ## Inherit base configs
To release the burdun and reduce bugs in writing the whole configs, MMDetection V2.0 support inheriting configs from multiple existing configs. To finetune a Mask RCNN model, the new config needs to inherit To release the burden and reduce bugs in writing the whole configs, MMDetection V2.0 support inheriting configs from multiple existing configs. To finetune a Mask RCNN model, the new config needs to inherit
`_base_/models/mask_rcnn_r50_fpn.py` to build the basic structure of the model. To use the Cityscapes Dataset, the new config can also simply inherit `_base_/datasets/cityscapes_instance.py`. For runtime settings such as training schedules, the new config needs to inherit `_base_/default_runtime.py`. This configs are in the `configs` directory and the users can also choose to write the whole contents rather than use inheritance. `_base_/models/mask_rcnn_r50_fpn.py` to build the basic structure of the model. To use the Cityscapes Dataset, the new config can also simply inherit `_base_/datasets/cityscapes_instance.py`. For runtime settings such as training schedules, the new config needs to inherit `_base_/default_runtime.py`. This configs are in the `configs` directory and the users can also choose to write the whole contents rather than use inheritance.
```python ```python
...@@ -34,8 +34,10 @@ model = dict( ...@@ -34,8 +34,10 @@ model = dict(
fc_out_channels=1024, fc_out_channels=1024,
roi_feat_size=7, roi_feat_size=7,
num_classes=8, num_classes=8,
target_means=[0., 0., 0., 0.], bbox_coder=dict(
target_stds=[0.1, 0.1, 0.2, 0.2], type='DeltaXYWHBBoxCoder',
target_means=[0., 0., 0., 0.],
target_stds=[0.1, 0.1, 0.2, 0.2]),
reg_class_agnostic=False, reg_class_agnostic=False,
loss_cls=dict( loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0), type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
......
...@@ -215,7 +215,7 @@ Currently it supports to concat and repeat datasets. ...@@ -215,7 +215,7 @@ Currently it supports to concat and repeat datasets.
### Repeat dataset ### Repeat dataset
We use `RepeatDataset` as warpper to repeat the dataset. For example, suppose the original dataset is `Dataset_A`, to repeat it, the config looks like the following We use `RepeatDataset` as wrapper to repeat the dataset. For example, suppose the original dataset is `Dataset_A`, to repeat it, the config looks like the following
```python ```python
dataset_A_train = dict( dataset_A_train = dict(
type='RepeatDataset', type='RepeatDataset',
...@@ -228,7 +228,26 @@ dataset_A_train = dict( ...@@ -228,7 +228,26 @@ dataset_A_train = dict(
) )
``` ```
### Concatemate dataset ### Class balanced dataset
We use `ClassBalancedDataset` as wrapper to repeat the dataset based on category
frequency. The dataset to repeat needs to instantiate function `self.get_cat_ids(idx)`
to support `ClassBalancedDataset`.
For example, to repeat `Dataset_A` with `oversample_thr=1e-3`, the config looks like the following
```python
dataset_A_train = dict(
type='ClassBalancedDataset',
oversample_thr=1e-3,
dataset=dict( # This is the original config of Dataset_A
type='Dataset_A',
...
pipeline=train_pipeline
)
)
```
You may refer to [source code](../../mmdet/datasets/dataset_wrappers.py) for details.
### Concatenate dataset
There two ways to concatenate the dataset. There two ways to concatenate the dataset.
......
...@@ -2,18 +2,18 @@ ...@@ -2,18 +2,18 @@
## Customize optimizer ## Customize optimizer
An example of customized optimizer `CopyOfSGD` is defined in `mmdet/core/optimizer/copy_of_sgd.py`. A customized optimizer could be defined as following.
More generally, a customized optimizer could be defined as following.
Assume you want to add a optimizer named as `MyOptimizer`, which has arguments `a`, `b`, and `c`. Assume you want to add a optimizer named as `MyOptimizer`, which has arguments `a`, `b`, and `c`.
You need to first implement the new optimizer in a file, e.g., in `mmdet/core/optimizer/my_optimizer.py`: You need to create a new directory named `mmdet/core/optimizer`.
And then implement the new optimizer in a file, e.g., in `mmdet/core/optimizer/my_optimizer.py`:
```python ```python
from .registry import OPTIMIZERS from .registry import OPTIMIZERS
from torch.optim import Optimizer from torch.optim import Optimizer
@OPTIMIZERS.register_module @OPTIMIZERS.register_module()
class MyOptimizer(Optimizer): class MyOptimizer(Optimizer):
def __init__(self, a, b, c) def __init__(self, a, b, c)
...@@ -49,16 +49,16 @@ The users can directly set arguments following the [API doc](https://pytorch.org ...@@ -49,16 +49,16 @@ The users can directly set arguments following the [API doc](https://pytorch.org
Some models may have some parameter-specific settings for optimization, e.g. weight decay for BatchNoarm layers. Some models may have some parameter-specific settings for optimization, e.g. weight decay for BatchNoarm layers.
The users can do those fine-grained parameter tuning through customizing optimizer constructor. The users can do those fine-grained parameter tuning through customizing optimizer constructor.
``` ```python
from mmcv.utils import build_from_cfg from mmcv.utils import build_from_cfg
from mmdet.core.optimizer import OPTIMIZER_BUILDERS, OPTIMIZERS from mmcv.runner.optimizer import OPTIMIZER_BUILDERS, OPTIMIZERS
from mmdet.utils import get_root_logger from mmdet.utils import get_root_logger
from .cocktail_optimizer import CocktailOptimizer from .my_optimizer import MyOptimizer
@OPTIMIZER_BUILDERS.register_module @OPTIMIZER_BUILDERS.register_module()
class CocktailOptimizerConstructor(object): class MyOptimizerConstructor(object):
def __init__(self, optimizer_cfg, paramwise_cfg=None): def __init__(self, optimizer_cfg, paramwise_cfg=None):
...@@ -90,7 +90,7 @@ import torch.nn as nn ...@@ -90,7 +90,7 @@ import torch.nn as nn
from ..registry import BACKBONES from ..registry import BACKBONES
@BACKBONES.register_module @BACKBONES.register_module()
class MobileNet(nn.Module): class MobileNet(nn.Module):
def __init__(self, arg1, arg2): def __init__(self, arg1, arg2):
...@@ -172,7 +172,7 @@ Double Head R-CNN implements a new bbox head for object detection. ...@@ -172,7 +172,7 @@ Double Head R-CNN implements a new bbox head for object detection.
To implement a bbox head, basically we need to implement three functions of the new module as the following. To implement a bbox head, basically we need to implement three functions of the new module as the following.
```python ```python
@HEADS.register_module @HEADS.register_module()
class DoubleConvFCBBoxHead(BBoxHead): class DoubleConvFCBBoxHead(BBoxHead):
r"""Bbox head used in Double-Head R-CNN r"""Bbox head used in Double-Head R-CNN
...@@ -214,7 +214,7 @@ from .base_roi_head import BaseRoIHead ...@@ -214,7 +214,7 @@ from .base_roi_head import BaseRoIHead
from .test_mixins import BBoxTestMixin, MaskTestMixin from .test_mixins import BBoxTestMixin, MaskTestMixin
@HEADS.register_module @HEADS.register_module()
class StandardRoIHead(BaseRoIHead, BBoxTestMixin, MaskTestMixin): class StandardRoIHead(BaseRoIHead, BBoxTestMixin, MaskTestMixin):
"""Simplest base roi head including one bbox head and one mask head. """Simplest base roi head including one bbox head and one mask head.
""" """
...@@ -268,7 +268,7 @@ from ..builder import HEADS ...@@ -268,7 +268,7 @@ from ..builder import HEADS
from .standard_roi_head import StandardRoIHead from .standard_roi_head import StandardRoIHead
@HEADS.register_module @HEADS.register_module()
class DoubleHeadRoIHead(StandardRoIHead): class DoubleHeadRoIHead(StandardRoIHead):
"""RoI head for Double Head RCNN """RoI head for Double Head RCNN
...@@ -353,7 +353,7 @@ def my_loss(pred, target): ...@@ -353,7 +353,7 @@ def my_loss(pred, target):
loss = torch.abs(pred - target) loss = torch.abs(pred - target)
return loss return loss
@LOSSES.register_module @LOSSES.register_module()
class MyLoss(nn.Module): class MyLoss(nn.Module):
def __init__(self, reduction='mean', loss_weight=1.0): def __init__(self, reduction='mean', loss_weight=1.0):
......
import argparse
from mmcv import Config, DictAction
def parse_args():
parser = argparse.ArgumentParser(description='Print the whole config')
parser.add_argument('config', help='config file path')
parser.add_argument(
'--options', nargs='+', action=DictAction, help='arguments in dict')
args = parser.parse_args()
return args
def main():
args = parse_args()
cfg = Config.fromfile(args.config)
if args.options is not None:
cfg.merge_from_dict(args.options)
print(f'Config:\n{cfg.pretty_text}')
if __name__ == '__main__':
main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment