Skip to content

Commit

Permalink
[Fix] Fix MaskFormer and Mask2Former of MMSegmentation (open-mmlab#2532)
Browse files Browse the repository at this point in the history
## Motivation

The DETR-related modules have been refactored in
open-mmlab/mmdetection#8763, which causes breakings of MaskFormer and
Mask2Former in both MMDetection (has been fixed in
open-mmlab/mmdetection#9515) and MMSegmentation. This pr fix the bugs in
MMSegmentation.

### TO-DO List

- [x] update configs
- [x] check and modify data flow
- [x] fix unit test
- [x] aligning inference
- [x] write a ckpt converter
- [x] write ckpt update script
- [x] update model zoo
- [x] update model link in readme
- [x] update
[faq.md](https://github.com/open-mmlab/mmsegmentation/blob/dev-1.x/docs/en/notes/faq.md#installation)

## Tips of Fixing other implementations based on MaskXFormer of mmseg

1. The Transformer modules should be built directly. The original
building with register manner has been refactored.
2. The config requires to be modified. Delete `type` and modify several
keys, according to the modifications in this pr.
3. The `batch_first` is set `True` uniformly in the new implementations.
Hence the data flow requires to be transposed and config of
`batch_first` needs to be modified.
4. The checkpoint trained on the old implementation should be converted
to be used in the new one.

### Convert script

```Python
import argparse
from copy import deepcopy
from collections import OrderedDict

import torch

from mmengine.config import Config
from mmseg.models import build_segmentor
from mmseg.utils import register_all_modules
register_all_modules(init_default_scope=True)


def parse_args():
    parser = argparse.ArgumentParser(
        description='MMSeg convert MaskXFormer model, by Li-Qingyun')
    parser.add_argument('Mask_what_former', type=int,
                        help='Mask what former, can be a `1` or `2`',
                        choices=[1, 2])
    parser.add_argument('CFG_FILE', help='config file path')
    parser.add_argument('OLD_CKPT_FILEPATH', help='old ckpt file path')
    parser.add_argument('NEW_CKPT_FILEPATH', help='new ckpt file path')
    args = parser.parse_args()
    return args


args = parse_args()

def get_new_name(old_name: str):
    new_name = old_name

    if 'encoder.layers' in new_name:
        new_name = new_name.replace('attentions.0', 'self_attn')

    new_name = new_name.replace('ffns.0', 'ffn')

    if 'decoder.layers' in new_name:

        if args.Mask_what_former == 2:
            # for Mask2Former
            new_name = new_name.replace('attentions.0', 'cross_attn')
            new_name = new_name.replace('attentions.1', 'self_attn')
        else:
            # for Mask2Former
            new_name = new_name.replace('attentions.0', 'self_attn')
            new_name = new_name.replace('attentions.1', 'cross_attn')

    return new_name
    
def cvt_sd(old_sd: OrderedDict):
    new_sd = OrderedDict()
    for name, param in old_sd.items():
        new_name = get_new_name(name)
        assert new_name not in new_sd
        new_sd[new_name] = param
    assert len(new_sd) == len(old_sd)
    return new_sd
    
if __name__ == '__main__':
    cfg = Config.fromfile(args.CFG_FILE)
    model_cfg = cfg.model

    segmentor = build_segmentor(model_cfg)

    refer_sd = segmentor.state_dict()
    old_ckpt = torch.load(args.OLD_CKPT_FILEPATH)
    old_sd = old_ckpt['state_dict']

    new_sd = cvt_sd(old_sd)
    print(segmentor.load_state_dict(new_sd))

    new_ckpt = deepcopy(old_ckpt)
    new_ckpt['state_dict'] = new_sd
    torch.save(new_ckpt, args.NEW_CKPT_FILEPATH)
    print(f'{args.NEW_CKPT_FILEPATH} has been saved!')
```

Usage:
```bash
# for example
python ckpt4pr2532.py 1 configs/maskformer/maskformer_r50-d32_8xb2-160k_ade20k-512x512.py original_ckpts/maskformer_r50-d32_8xb2-160k_ade20k-512x512_20221030_182724-cbd39cc1.pth cvt_outputs/maskformer_r50-d32_8xb2-160k_ade20k-512x512_20221030_182724.pth
python ckpt4pr2532.py 2 configs/mask2former/mask2former_r50_8xb2-160k_ade20k-512x512.py original_ckpts/mask2former_r50_8xb2-160k_ade20k-512x512_20221204_000055-4c62652d.pth cvt_outputs/mask2former_r50_8xb2-160k_ade20k-512x512_20221204_000055.pth
```

---------

Co-authored-by: MeowZheng <[email protected]>
  • Loading branch information
Li-Qingyun and MeowZheng committed Feb 1, 2023
1 parent 1bad52a commit ef981d4
Show file tree
Hide file tree
Showing 14 changed files with 154 additions and 183 deletions.
5 changes: 3 additions & 2 deletions .circleci/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
pip install -U openmim
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
pip install -r requirements/tests.txt -r requirements/optional.txt
- run:
name: Build and install
Expand Down Expand Up @@ -97,6 +97,7 @@ jobs:
command: |
git clone -b main --depth 1 https://github.com/open-mmlab/mmengine.git /home/circleci/mmengine
git clone -b dev-1.x --depth 1 https://github.com/open-mmlab/mmclassification.git /home/circleci/mmclassification
git clone -b dev-3.x --depth 1 https://github.com/open-mmlab/mmdetection.git /home/circleci/mmdetection
- run:
name: Build Docker image
command: |
Expand All @@ -109,7 +110,7 @@ jobs:
docker exec mmseg pip install -U openmim
docker exec mmseg mim install 'mmcv>=2.0.0rc4'
docker exec mmseg pip install -e /mmclassification
docker exec mmseg mim install 'mmdet==3.0.0rc5'
docker exec mmseg pip install -e /mmdetection
docker exec mmseg pip install -r requirements/tests.txt -r requirements/optional.txt
- run:
name: Build and install
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/merge_stage_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down Expand Up @@ -168,7 +168,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down Expand Up @@ -211,7 +211,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down Expand Up @@ -246,7 +246,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pr_stage_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down Expand Up @@ -137,7 +137,7 @@ jobs:
pip install git+https://github.com/open-mmlab/mmengine.git
mim install 'mmcv>=2.0.0rc4'
pip install git+https://github.com/open-mmlab/[email protected]
mim install 'mmdet==3.0.0rc5'
pip install git+https://github.com/open-mmlab/[email protected]
- name: Install unittest dependencies
run: pip install -r requirements/tests.txt -r requirements/optional.txt
- name: Build and install
Expand Down
Loading

0 comments on commit ef981d4

Please sign in to comment.