czczup / ViT-Adapter

[ICLR 2023 Spotlight] Vision Transformer Adapter for Dense Predictions
https://arxiv.org/abs/2205.08534
Apache License 2.0
1.27k stars 140 forks source link

针对非固定尺寸的图像,似乎无法到达理想的状态 #48

Closed 847001315 closed 1 year ago

847001315 commented 2 years ago

最近跑了好几个数据集,其中包括了三个图片尺寸固定的数据集和两个非固定尺寸的图片的数据集。其中在固定尺寸数据集上,均能到达SOTA或者接近SOTA的级别,但是在非固定尺寸的数据集上,会比当前SOTA低接近10-20个点。我怀疑是我配置文件弄错了,但我不太清楚哪里弄得不对。 以下是我的思考:

  1. 我觉得可能是img_scale这个参数设置的问题,针对固定数据集,我可以该数值设置的就是固定尺寸的值。但是针对非固定尺寸(长宽比不一致)数据集,我不知道这个值该设置成什么?目前设置的是最大的图片的高宽。
  2. img_scale=(x,y),其中这个x代表的是高,y代表的是宽吗?

其余的情况我暂时没有考虑到。 以下是我的config:

_base_ = [
    '../_base_/models/upernet_nofcn_beit.py',
    '../_base_/datasets/isic2018.py',
    '../_base_/default_runtime.py',
    '../_base_/schedules/schedule_160k.py'
]
img_scale = (6748, 6748) #此处不知道该填什么,已知该数据集图片最宽为6748,图片最高为4499。【不是同一张图片】
t_size=256
crop_size = (t_size, t_size)
# pretrained = 'https://conversationhub.blob.core.windows.net/beit-share-public/beit/beit_large_patch16_224_pt22k_ft22k.pth'
# pretrained = '/data/cgh/project/ViT-Adapter-main/segmentation/pretrained/beit_large_patch16_224_pt22k_ft22k.pth'
model = dict(
    # pretrained=pretrained,
    backbone=dict(
        type='BEiTAdapter',
        img_size=t_size,
        patch_size=16,
        embed_dim=768,
        depth=12,
        num_heads=12,
        mlp_ratio=4,
        qkv_bias=True,
        use_abs_pos_emb=False,
        use_rel_pos_bias=True,
        init_values=1e-6,
        drop_path_rate=0.2,
        conv_inplane=64,
        n_points=4,
        deform_num_heads=12,
        cffn_ratio=0.25,
        deform_ratio=0.5,
        interaction_indexes=[[0, 2], [3, 5], [6, 8], [9, 11]],
    ),
    decode_head=dict(
        in_channels=[768, 768, 768, 768],
        num_classes=2,
        channels=768,
    ),
    # auxiliary_head=dict(
    #     in_channels=768,
    #     num_classes=2
    # ),
    # test_cfg = dict(mode='whole')
    test_cfg = dict(mode='slide', crop_size=crop_size, stride=(85, 85))
)
img_norm_cfg = dict(
    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
    dict(type='LoadImageFromFile'), # 载入图片
    dict(type='LoadAnnotations'), # 载入mask
    dict(type='Resize', img_scale=img_scale, ratio_range=(0.5, 2.0)), # 开始Resize,
    dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75),# 随机裁剪,从img_scale中裁剪出crop_size
    dict(type='RandomFlip', prob=0.5), # 随机翻转(是否是垂直?还是水平翻转?)
    dict(type='PhotoMetricDistortion'),# 光度失真,可以调整图像的亮度,色度,对比度,饱和度,以及加入噪点;
    dict(type='Normalize', **img_norm_cfg), # 归一化
    # dict(type='RandomRotate',prob=0.5,degree=30,pad_val=255, seg_pad_val=0),
    dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=1), # padding到crop_size的大小,其中图像padding加像素值0,mask加上像素值1
    dict(type='DefaultFormatBundle'), # 流程里收集数据的默认格式捆
    dict(type='Collect', keys=['img', 'gt_semantic_seg']) # 决定数据里哪些键被传递到分割器里的流程。
]
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipAug', # 封装测试时数据增广
        img_scale=img_scale,
        # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], # 多尺度测试,后面测试的时候可以开起来提分数
        flip=False,
        transforms=[
            dict(type='Resize', keep_ratio=True), # keep_ratio是否保持宽和高的比例
            dict(type='ResizeToMultiple', size_divisor=32), # 根据给定的大小或比例因子调整图像大小,然后将调整大小或重新缩放的图像大小四舍五入到可以除以除数的最接近的值。
            dict(type='RandomFlip'),
            dict(type='Normalize', **img_norm_cfg),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img']),
        ])
]
optimizer = dict(_delete_=True, type='AdamW', lr=1e-4, betas=(0.9, 0.999), weight_decay=0.05,
                 constructor='LayerDecayOptimizerConstructor',
                 paramwise_cfg=dict(num_layers=24, layer_decay_rate=0.90))
lr_config = dict(_delete_=True, policy='poly',
                 warmup='linear',
                 warmup_iters=1500,
                 warmup_ratio=1e-6,
                 power=1.0, min_lr=0.0, by_epoch=False)
data=dict(samples_per_gpu=4,# bs=16的时候,显存用8g左右
            workers_per_gpu=2,
          train=dict(pipeline=train_pipeline),
          val=dict(pipeline=test_pipeline),
          test=dict(pipeline=test_pipeline))
runner = dict(type='IterBasedRunner', max_iters=250000)
checkpoint_config = dict(by_epoch=False, interval=1000, max_keep_ckpts=1)
evaluation = dict(interval=5000, metric='mDice', save_best='mDice')
czczup commented 2 years ago

你好,感谢你的反馈 请问你这个数据集里的图像分辨率的分布范围很大吗,比如最大的图像可能有6000x4000,最小的只有500x500这样?

847001315 commented 2 years ago

你好,感谢你的反馈 请问你这个数据集里的图像分辨率的分布范围很大吗,比如最大的图像可能有6000x4000,最小的只有500x500这样?

是的,存在1024x768,也存在4288x2848,也有6000x4000,是否存在更小的分辨率没有去仔细筛查。说到这里,我之前跑的那三个固定尺寸的数据集,图片尺寸分别为 112x112、574x500、384x288,似乎分辨率都比较低。

czczup commented 2 years ago

你好,感谢你的反馈 请问你这个数据集里的图像分辨率的分布范围很大吗,比如最大的图像可能有6000x4000,最小的只有500x500这样?

是的,存在1024x768,也存在4288x2848,也有6000x4000,是否存在更小的分辨率没有去仔细筛查。说到这里,我之前跑的那三个固定尺寸的数据集,图片尺寸分别为 112x112、574x500、384x288,似乎分辨率都比较低。

这种数据集训练时需要专门处理一下,比如做多尺度时不是按固定短边缩放(因为img_scale = (6748, 6748)的话,最小的图片也会被放大到这个分辨率级别),而是给原图按0.5-1.5的比例缩放,然后训练时从中crop 256x256的图片。测试时保持原图分辨率不变,从中划窗取256x256的patch进行测试。如果patch的大小不满256x256,需要pad到256x256。

czczup commented 2 years ago

https://github.com/open-mmlab/mmsegmentation/blob/master/mmseg/datasets/pipelines/transforms.py 可以参考mmseg里的Resize函数进行修改

847001315 commented 2 years ago

https://github.com/open-mmlab/mmsegmentation/blob/master/mmseg/datasets/pipelines/transforms.py 可以参考mmseg里的Resize函数进行修改

好的,谢谢你的回复~ 这边我突然又有一个新的问题,关于beit_adapter他用的transformer分支是beit,我看源码部分,他的transformer的注意力是swin的WMSA,这个WMSA仅对固定窗口内进行attention,并没有进行窗口与窗口间的交互(swin中先用WMSA进行窗口内交互,再用SW-MSA进行移窗交互),不知道是不是我代码看的不够清洗,目前没看到偏全局的交互的样子。但就算如此,beit_adapter效果在很多数据集上效果都非常好!!只是对beit这里有点困惑,是否加入一些全局注意力会提升该分支的效果?