-
Notifications
You must be signed in to change notification settings - Fork 9.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fix] Fix MaskFormer and Mask2Former of MMDetection #9515
[Fix] Fix MaskFormer and Mask2Former of MMDetection #9515
Conversation
Align Inference Accuracyconfigs/maskformer/maskformer_r50_ms-16xb1-75e_coco.py MaskFormer
Mask2FormerInstance
Panoptic
The checkpoint should be converted by the following script:import json
from collections import OrderedDict
import torch
from mmengine.config import Config
from mmdet.models import build_detector
from mmdet.utils import register_all_modules
register_all_modules(init_default_scope=True)
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:
# for Mask2Former
new_name = new_name.replace('attentions.0', 'cross_attn')
new_name = new_name.replace('attentions.1', 'self_attn')
# # for MaskFormer
# 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_FILE = 'configs/mask2former/mask2former_r50_8xb2-lsj-50e_coco-panoptic.py'
OLD_CKPT_FILENAME = 'mask2former_r50_lsj_8x2_50e_coco-panoptic_20220326_224516-11a44721.pth'
OLD_CKPT_FILEPATH = 'develop/' + OLD_CKPT_FILENAME
NEW_CKPT_FILEPATH = 'develop/new_' + OLD_CKPT_FILENAME
cfg = Config.fromfile(CFG_FILE)
model_cfg = cfg.model
detector = build_detector(model_cfg)
refer_sd = detector.state_dict()
old_sd = torch.load(OLD_CKPT_FILEPATH)['state_dict']
new_sd = cvt_sd(old_sd)
new_names = sorted(list(refer_sd.keys()))
cvt_names = sorted(list(new_sd.keys()))
old_names = sorted(list(old_sd.keys()))
# we should make cvt_names --> new_names
json.dump(new_names, open(r'./develop/new_names.json', 'w'), indent='\n')
json.dump(cvt_names, open(r'./develop/cvt_names.json', 'w'), indent='\n')
json.dump(old_names, open(r'./develop/old_names.json', 'w'), indent='\n')
new_ckpt = dict(state_dict=new_sd)
torch.save(new_ckpt, NEW_CKPT_FILEPATH)
print(f'{NEW_CKPT_FILEPATH} has been saved!') |
please merge the refactor-detr and resolve the conflict |
configs/mask2former/mask2former_r50_8xb2-lsj-50e_coco-panoptic.py
Outdated
Show resolved
Hide resolved
configs/mask2former/mask2former_r50_8xb2-lsj-50e_coco-panoptic.py
Outdated
Show resolved
Hide resolved
@jshilong the merging has been finished and the conflicts has been resolved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Co-authored-by: Kei-Chi Tse <109070650+KeiChiTse@users.noreply.github.com>
## 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>
Co-authored-by: Kei-Chi Tse <109070650+KeiChiTse@users.noreply.github.com>
Motivation
The DETR-related modules have been refactored in #8763, which causes breakings of MaskFormer and Mask2Former. The unit tests of them were deleted in #9089. This pr add the ut back, and fix the breakings. Note that this pr only fix the bugs, but not refactor the two detector. Their refactors require new prs and more time for designing scheme.
BC-breaking
The modifications may causes breaking of the MaskFormer and Mask2Former newly supported in open-mmlab/mmsegmentation#2215 and open-mmlab/mmsegmentation#2255 of mmsegmentation v1.0.0rc2.
(The weight in the model zoo should be converted.)