mirror of
https://github.com/open-mmlab/mmsegmentation.git
synced 2025-06-03 22:03:48 +08:00
## 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 <meowzheng@outlook.com>
191 lines
6.3 KiB
YAML
191 lines
6.3 KiB
YAML
version: 2.1
|
|
|
|
# the default pipeline parameters, which will be updated according to
|
|
# the results of the path-filtering orb
|
|
parameters:
|
|
lint_only:
|
|
type: boolean
|
|
default: true
|
|
|
|
jobs:
|
|
lint:
|
|
docker:
|
|
- image: cimg/python:3.7.4
|
|
steps:
|
|
- checkout
|
|
- run:
|
|
name: Install pre-commit hook
|
|
command: |
|
|
pip install pre-commit
|
|
pre-commit install
|
|
- run:
|
|
name: Linting
|
|
command: pre-commit run --all-files
|
|
- run:
|
|
name: Check docstring coverage
|
|
command: |
|
|
pip install interrogate
|
|
interrogate -v --ignore-init-method --ignore-module --ignore-nested-functions --ignore-magic --ignore-regex "__repr__" --fail-under 75 mmseg
|
|
build_cpu:
|
|
parameters:
|
|
# The python version must match available image tags in
|
|
# https://circleci.com/developer/images/image/cimg/python
|
|
python:
|
|
type: string
|
|
torch:
|
|
type: string
|
|
torchvision:
|
|
type: string
|
|
docker:
|
|
- image: cimg/python:<< parameters.python >>
|
|
resource_class: large
|
|
steps:
|
|
- checkout
|
|
- run:
|
|
name: Install Libraries
|
|
command: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y ninja-build libglib2.0-0 libsm6 libxrender-dev libxext6 libgl1-mesa-glx libjpeg-dev zlib1g-dev libtinfo-dev libncurses5
|
|
- run:
|
|
name: Configure Python & pip
|
|
command: |
|
|
pip install --upgrade pip
|
|
pip install wheel
|
|
- run:
|
|
name: Install PyTorch
|
|
command: |
|
|
python -V
|
|
pip install torch==<< parameters.torch >>+cpu torchvision==<< parameters.torchvision >>+cpu -f https://download.pytorch.org/whl/torch_stable.html
|
|
- run:
|
|
name: Install mmseg dependencies
|
|
command: |
|
|
pip install git+https://github.com/open-mmlab/mmengine.git@main
|
|
pip install -U openmim
|
|
mim install 'mmcv>=2.0.0rc4'
|
|
pip install git+https://github.com/open-mmlab/mmclassification@dev-1.x
|
|
pip install git+https://github.com/open-mmlab/mmdetection.git@dev-3.x
|
|
pip install -r requirements/tests.txt -r requirements/optional.txt
|
|
- run:
|
|
name: Build and install
|
|
command: |
|
|
pip install -e .
|
|
- run:
|
|
name: Skip timm unittests and generate coverage report
|
|
command: |
|
|
python -m coverage run --branch --source mmseg -m pytest tests/ --ignore tests/test_models/test_backbones/test_timm_backbone.py
|
|
python -m coverage xml
|
|
python -m coverage report -m
|
|
build_cuda:
|
|
parameters:
|
|
torch:
|
|
type: string
|
|
cuda:
|
|
type: enum
|
|
enum: ["10.1", "10.2", "11.1"]
|
|
cudnn:
|
|
type: integer
|
|
default: 7
|
|
machine:
|
|
image: ubuntu-2004-cuda-11.4:202110-01
|
|
# docker_layer_caching: true
|
|
resource_class: gpu.nvidia.small
|
|
steps:
|
|
- checkout
|
|
- run:
|
|
# Cloning repos in VM since Docker doesn't have access to the private key
|
|
name: Clone Repos
|
|
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: |
|
|
docker build .circleci/docker -t mmseg:gpu --build-arg PYTORCH=<< parameters.torch >> --build-arg CUDA=<< parameters.cuda >> --build-arg CUDNN=<< parameters.cudnn >>
|
|
docker run --gpus all -t -d -v /home/circleci/project:/mmseg -v /home/circleci/mmengine:/mmengine -v /home/circleci/mmclassification:/mmclassification -v /home/circleci/mmdetection:/mmdetection -w /mmseg --name mmseg mmseg:gpu
|
|
- run:
|
|
name: Install mmseg dependencies
|
|
command: |
|
|
docker exec mmseg pip install -e /mmengine
|
|
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 pip install -e /mmdetection
|
|
docker exec mmseg pip install -r requirements/tests.txt -r requirements/optional.txt
|
|
- run:
|
|
name: Build and install
|
|
command: |
|
|
docker exec mmseg pip install -e .
|
|
- run:
|
|
name: Run unittests but skip timm unittests
|
|
command: |
|
|
docker exec mmseg pytest tests/ --ignore tests/test_models/test_backbones/test_timm_backbone.py
|
|
workflows:
|
|
pr_stage_lint:
|
|
when: << pipeline.parameters.lint_only >>
|
|
jobs:
|
|
- lint:
|
|
name: lint
|
|
filters:
|
|
branches:
|
|
ignore:
|
|
- dev-1.x
|
|
- 1.x
|
|
- master
|
|
pr_stage_test:
|
|
when:
|
|
not:
|
|
<< pipeline.parameters.lint_only >>
|
|
jobs:
|
|
- lint:
|
|
name: lint
|
|
filters:
|
|
branches:
|
|
ignore:
|
|
- dev-1.x
|
|
- 1.x
|
|
- master
|
|
- build_cpu:
|
|
name: minimum_version_cpu
|
|
torch: 1.6.0
|
|
torchvision: 0.7.0
|
|
python: "3.7"
|
|
requires:
|
|
- lint
|
|
- build_cpu:
|
|
name: maximum_version_cpu
|
|
# TODO: Fix torch 1.13 forward crush
|
|
torch: 1.12.0
|
|
torchvision: 0.13.0
|
|
python: 3.9.0
|
|
requires:
|
|
- minimum_version_cpu
|
|
- hold:
|
|
type: approval
|
|
requires:
|
|
- maximum_version_cpu
|
|
- build_cuda:
|
|
name: mainstream_version_gpu
|
|
torch: 1.8.1
|
|
# Use double quotation mark to explicitly specify its type
|
|
# as string instead of number
|
|
cuda: "10.2"
|
|
requires:
|
|
- hold
|
|
merge_stage_test:
|
|
when:
|
|
not:
|
|
<< pipeline.parameters.lint_only >>
|
|
jobs:
|
|
- build_cuda:
|
|
name: minimum_version_gpu
|
|
torch: 1.6.0
|
|
# Use double quotation mark to explicitly specify its type
|
|
# as string instead of number
|
|
cuda: "10.1"
|
|
filters:
|
|
branches:
|
|
only:
|
|
- dev-1.x
|
|
- 1.x
|