AILab-CVC / YOLO-World

[CVPR 2024] Real-Time Open-Vocabulary Object Detection
https://www.yoloworld.cc
GNU General Public License v3.0
4.36k stars 423 forks source link

使用自定义数据集,loss_bbox: 0.00 loss_dfl: 0.00,网上的方法,添加类别,修改base搜没有解决。 #428

Open LRuiRui517 opened 2 months ago

LRuiRui517 commented 2 months ago

yolo_world_l_dual_vlpan_2e-4_80e_8gpus_finetune_coco.py文件,我需要微调 base = ( '../../third_party/mmyolo/configs/yolov8/yolov8_l_syncbn_fast_8xb16-500e_coco.py') custom_imports = dict( imports=['yolo_world'], allow_failed_imports=False)

hyper-parameters

num_classes = 2 num_training_classes = 2 max_epochs = 1 # Maximum training epochs close_mosaic_epochs = 10 save_epoch_intervals = 5 text_channels = 512 neck_embed_channels = [128, 256, base.last_stage_out_channels // 2] neck_num_heads = [4, 8, base.last_stage_out_channels // 2 // 32] base_lr = 2e-4 weight_decay = 0.05 ''' 这是一个超参数,用于设置每个 GPU 上的训练批量大小 ''' train_batch_size_per_gpu = 4 load_from=r'C:\Users\DELL\Desktop\YOLO-World-master\configs\finetune_coco\Weight\yolo_world_v2_l_obj365v1_goldg_pretrain-a82b1fe3.pth' persistent_workers = False

model settings

model = dict( type='YOLOWorldDetector', mm_neck=True, num_train_classes=num_training_classes, num_test_classes=num_classes, data_preprocessor=dict(type='YOLOWDetDataPreprocessor'), backbone=dict( delete=True, type='MultiModalYOLOBackbone', image_model={{base.model.backbone}}, text_model=dict( type='HuggingCLIPLanguageBackbone', model_name='openai/clip-vit-base-patch32', frozen_modules=['all'])), neck=dict(type='YOLOWorldDualPAFPN', guide_channels=text_channels, embed_channels=neck_embed_channels, num_heads=neck_num_heads, block_cfg=dict(type='MaxSigmoidCSPLayerWithTwoConv'), text_enhancder=dict(type='ImagePoolingAttentionModule', embed_channels=256, num_heads=8)), bbox_head=dict(type='YOLOWorldHead', head_module=dict(type='YOLOWorldHeadModule', embed_dims=text_channels, num_classes=num_training_classes)), train_cfg=dict(assigner=dict(num_classes=num_training_classes)))

dataset settings

text_transform = [ dict(type='RandomLoadText', num_neg_samples=(num_classes, num_classes), max_num_samples=num_training_classes, padding_to_max=True, padding_value=''), dict(type='mmdet.PackDetInputs', meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape', 'flip', 'flip_direction', 'texts')) ] mosaic_affine_transform = [ dict( type='MultiModalMosaic', img_scale=base.img_scale, pad_val=114.0, pre_transform=base.pre_transform), dict( type='YOLOv5RandomAffine', max_rotate_degree=0.0, max_shear_degree=0.0, max_aspect_ratio=100., scaling_ratio_range=(1 - base.affine_scale, 1 + base.affine_scale),

img_scale is (width, height)

    border=(-_base_.img_scale[0] // 2, -_base_.img_scale[1] // 2),
    border_val=(114, 114, 114))

] train_pipeline = [

# dict(type='CheckKeyTransform', transform=dict(type='LoadImageFromFile')),
# dict(type='CheckKeyTransform', transform=dict(type='LoadAnnotations', with_bbox=True)),
# # 其他的数据处理步骤...

*_base_.pre_transform,
*mosaic_affine_transform,
dict(
    type='YOLOv5MultiModalMixUp',
    prob=_base_.mixup_prob,
    pre_transform=[*_base_.pre_transform,
                   *mosaic_affine_transform]),
*_base_.last_transform[:-1],
*text_transform

] train_pipeline_stage2 = [ base.train_pipeline_stage2[:-1], text_transform ]

dataset settings

coco_train_dataset = dict( delete=True, type='MultiModalDataset', dataset=dict( type='YOLOv5CocoDataset', metainfo=dict(classes=['fire','smoke']), data_root='data', ann_file=r'C:\Users\DELL\Desktop\YOLO-World-master\data\annotations\train.json', data_prefix=dict(img=r'C:\Users\DELL\Desktop\YOLO-World-master\data\dataset\images\train'), filter_cfg=dict(filter_empty_gt=False, min_size=32)), class_text_path=r'C:\Users\DELL\Desktop\YOLO-World-master\data\texts\my_data.json',

metainfo=custom_metainfo,

pipeline=train_pipeline)

train_dataloader = dict(

persistent_workers=persistent_workers,
batch_size=train_batch_size_per_gpu,
collate_fn=dict(type='yolow_collate'),
dataset=coco_train_dataset,
num_workers=1

) test_pipeline = [ #

dict(type='CheckKeyTransform', transform=dict(type='LoadImageFromFile')),

# dict(type='CheckKeyTransform', transform=dict(type='LoadAnnotations', with_bbox=True)),
# # 其他的数据处理步骤...

*_base_.test_pipeline[:-1],
dict(type='LoadText'),
dict(
    type='mmdet.PackDetInputs',
    meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
               'scale_factor', 'pad_param', 'texts'))

] coco_val_dataset = dict( delete=True, type='MultiModalDataset', dataset=dict( type='YOLOv5CocoDataset', metainfo=dict(classes=['fire','smoke']), data_root='data', ann_file=r'C:\Users\DELL\Desktop\YOLO-World-master\data\annotations\val.json', data_prefix=dict(img=r'C:\Users\DELL\Desktop\YOLO-World-master\data\dataset\images\val'), filter_cfg=dict(filter_empty_gt=False, min_size=32)), class_text_path=r'C:\Users\DELL\Desktop\YOLO-World-master\data\texts\my_data.json', pipeline=test_pipeline) val_dataloader = dict(

metainfo = metainfo,

dataset=coco_val_dataset, num_workers=1) test_dataloader = val_dataloader

training settings

default_hooks = dict( param_scheduler=dict( scheduler_type='linear', lr_factor=0.01, max_epochs=max_epochs), checkpoint=dict( max_keep_ckpts=-1, save_best=None, interval=save_epoch_intervals)) custom_hooks = [ dict( type='EMAHook', ema_type='ExpMomentumEMA', momentum=0.0001, update_buffers=True, strict_load=False, priority=49), dict( type='mmdet.PipelineSwitchHook', switch_epoch=max_epochs - close_mosaic_epochs, switch_pipeline=train_pipeline_stage2) ] train_cfg = dict( max_epochs=max_epochs, val_interval=5, dynamic_intervals=[((max_epochs - close_mosaic_epochs), base.val_interval_stage2)]) optim_wrapper = dict( optimizer=dict( delete=True, type='AdamW', lr=base_lr, weight_decay=weight_decay, batch_size_per_gpu=train_batch_size_per_gpu), paramwise_cfg=dict( custom_keys={'backbone.text_model': dict(lr_mult=0.01), 'logit_scale': dict(weight_decay=0.0)}), constructor='YOLOWv5OptimizerConstructor')

evaluation settings

val_evaluator = dict( delete=True, type='mmdet.CocoMetric', proposal_nums=(100, 1, 10), ann_file=r'C:\Users\DELL\Desktop\YOLO-World-master\data\annotations\val.json', metric='bbox') 下面是训练文件: import os import argparse import logging import os.path as osp import sys

from mmengine.config import Config, DictAction from mmengine.logging import print_log from mmengine.runner import Runner

from mmyolo.registry import RUNNERS from mmyolo.utils import is_metainfo_lower

def parse_args(): parser = argparse.ArgumentParser(description='Train a detector') parser.add_argument('config', help='train config file path', default=r'C:\Users\DELL\Desktop\YOLO-World-master\configs\finetune_coco\yolo_world_l_dual_vlpan_2e-4_80e_8gpus_finetune_coco.py', nargs='?')

parser.add_argument('config', help='train config file path', default=r'C:\Users\DELL\Desktop\YOLO-World-master\configs\finetune_coco\yolo_world_v2_s_bn_2e-4_80e_8gpus_mask-refine_finetune_coco.py', nargs='?')

parser.add_argument('--work-dir', help='the dir to save logs and models', default='./outputs')
parser.add_argument(
    '--amp',
    action='store_true',
    default=False,
    help='enable automatic-mixed-precision training')
parser.add_argument(
    '--resume',
    nargs='?',
    type=str,
    const='auto',
    help='If specify checkpoint path, resume from it, while if not '
    'specify, try to auto resume from the latest checkpoint '
    'in the work directory.',
    default=None)
parser.add_argument(
    '--cfg-options',
    nargs='+',
    action=DictAction,
    help='override some settings in the used config, the key-value pair '
    'in xxx=yyy format will be merged into config file. If the value to '
    'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
    'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
    'Note that the quotation marks are necessary and that no white space '
    'is allowed.')
parser.add_argument(
    '--launcher',
    choices=['none', 'pytorch', 'slurm', 'mpi'],
    default='none',
    help='job launcher')
parser.add_argument('--local_rank', type=int, default=0)
args = parser.parse_args()
if 'LOCAL_RANK' not in os.environ:
    os.environ['LOCAL_RANK'] = str(args.local_rank)

return args

def main(): args = parse_args()

# 打印 config 路径以确认是否正确
print(f"Config file path: {args.config}")

# 检查配置文件是否存在
if not osp.exists(args.config):
    raise FileNotFoundError(f"Config file not found: {args.config}")

# load config
cfg = Config.fromfile(args.config)
# replace the ${key} with the value of cfg.key
# cfg = replace_cfg_vals(cfg)
cfg.launcher = args.launcher
if args.cfg_options is not None:
    cfg.merge_from_dict(args.cfg_options)

# work_dir is determined in this priority: CLI > segment in file > filename
if args.work_dir is not None:
    # update configs according to CLI args if args.work_dir is not None
    cfg.work_dir = args.work_dir
elif cfg.get('work_dir', None) is None:
    # use config filename as default work_dir if cfg.work_dir is None
    if args.config.startswith('projects/'):
        config = args.config[len('projects/'):]
        config = config.replace('/configs/', '/')
        cfg.work_dir = osp.join('./work_dirs', osp.splitext(config)[0])
    else:
        cfg.work_dir = osp.join('./work_dirs',
                                osp.splitext(osp.basename(args.config))[0])

# enable automatic-mixed-precision training
if args.amp is True:
    optim_wrapper = cfg.optim_wrapper.type
    if optim_wrapper == 'AmpOptimWrapper':
        print_log(
            'AMP training is already enabled in your config.',
            logger='current',
            level=logging.WARNING)
    else:
        assert optim_wrapper == 'OptimWrapper', (
            '`--amp` is only supported when the optimizer wrapper type is '
            f'`OptimWrapper` but got {optim_wrapper}.')
        cfg.optim_wrapper.type = 'AmpOptimWrapper'
        cfg.optim_wrapper.loss_scale = 'dynamic'

# resume is determined in this priority: resume from > auto_resume
if args.resume == 'auto':
    cfg.resume = True
    cfg.load_from = None
elif args.resume is not None:
    cfg.resume = True
    cfg.load_from = args.resume

# Determine whether the custom metainfo fields are all lowercase

is_metainfo_lower(cfg)

# build the runner from config
if 'runner_type' not in cfg:
    # build the default runner
    runner = Runner.from_cfg(cfg)
else:
    # build customized runner from the registry
    # if 'runner_type' is set in the cfg
    runner = RUNNERS.build(cfg)

# start training
runner.train()

if name == 'main': main() 下面是我的texts: [["fire"], ["smoke"]] 我做的两个类别(fire,smoke),loss_bbox: 0.0000 loss_dfl: 0.0000一直为0,百思不得其解,有没有高手给指点一下,非常感谢。

lvke9529 commented 1 month ago

You can refer to this:https://blog.csdn.net/ITdaka/article/details/139306984