常规赛:PALM眼底彩照视盘探测与分割202105-202205全时段第一名(得分0.97387)方案

本来该比赛博主卷到写上一篇博文0.97123是不打算在卷了的,事情的起因也很简单博主4月底参加这个比赛的时候提交了结果,成绩0.96689很一般。不料,到了月底有人(202105-202204月份的全时段第一名)又把3月份的结果(成绩0.96954)提交了上来,让博主的排名下来一位。于是,博主在5月份力争在5月份把结果做到0.97。于是,在5月9号有了这篇博文(常规赛:PALM眼底彩照视盘探测与分割202105-202205全时段第二名(得分0.97123)方案_万里鹏程转瞬至的博客-CSDN博客)。当时的标题是全时段第一名,但是几天后又被上月的第一名卷下去了。于是,把博文标题改成了第二名。看来是博主当时得意的太早了。

于是,在好几天的卷王争锋中,top1的得分从0,971到0.972。在这阶段中博主基于HardNet 最多也只能把得分做到0.972,而对手把分数干到了0.97337。对于HardNet和该比赛基本上放弃了。后来又是手闲,把模型换成了SegFormer系列,权衡系列性能与flop后选用了SegFormerB2。SegFormerB2的训练比HardNet 更加费时,因此在有限的训练资源下一直没出啥效果。最佳的得分也不过是第二名,本来欲放弃挣扎了。结果,在5月20几好不容易整来的全时段第二名,在5.30日又被人搞成了第三名。于是,争一口。博主不配搞个第一名么?因此选择模型,增加分辨率,继续训练,终于一举突破0.97337,干到了全时段的第一名。这篇博客写出来后,也许在以后的时间会被人超越,但起码在202105-202205全时段是第一名(因为,现在离5月份结束只剩最后3小时了)。

话不多说,开始分享得分方案。博主一直觉得,模型精度要高,必须得自己写代码训练模型,不能使用现成的二次封装框架(比如:paddleseg)。想必这也是前面11个月里面一直没有人能把成绩赶到0.97的原因吧。

1、基本训练配置

1.1 基本训练配置

选用的网络:SegFormer

数据集划分:8:2

学习率:0.0005

优化器:AdamW

学习率调度器:具备周期性与峰值衰减的学习率(具体可以参考以下链接)paddlepaddle 26 同时具备周期性与衰减性的学习率调度器_万里鹏程转瞬至的博客-CSDN博客在我们熟知的学习率调度器中,有周期性调度器(单周期,多周期),也由衰减式调度器(按性能衰减,按epoch衰减)和预热式(学习率变化为低->高->缓慢变低)的。周期性调度器多学习率比较敏感,单可以跳过鞍点,尽可能找到鞍点;衰减式调度器,对学习率敏感度较低,但很难越过鞍点。为了结合这两个调度器的优势,博主对余弦退火重启动学习率和余弦式衰减的代码做了轻微修改,实现了周期性与衰减学习率调度器的结合。1、余弦退火重启动学习率衰减这里只实现了指数式衰减,参数中的eta_min是学习率最小值。chttps://blog.csdn.net/a486259/article/details/124842045

loss:[loss_CrossEntropyLoss,loss_LovaszSoftmaxLoss,loss_DiceLoss],loss_weights=[0.3,0.3,0.4]

在多loss的训练配置下,博主发现loss的权重对训练效果的影响较小。同时,在进行分辨率多阶段迭代时,学习率应该按阶段减少。

1.2 训练涨点技巧

1、训练时random size:提升模型泛化能力

2、为模型添加dropout与dropblock:提升模型拟合能力,同时降低过拟合

3、使用cutmix进行数据增强:提升模型拟合能力

4、逐步增强的数据增强方式:加快训练过程

5、保存多个最优模型:避免单一指标下错失最优模型

6、多尺度预测试(非数据融合,得出最佳测试尺寸):避免单一分辨率下错失最佳测试尺寸

7、多分辨率迭代(逐步增大分辨率):不断提升模型精度上限

8、MCdropout:多次测试取平均值

2、具体得分记录

使用SegFormerB2最大的感受就是,模型收敛慢,而且训练周期较长。同时针对于逐步增强的数据增强方式,需要更加细腻的考虑。博主一开始设置的是各阶段的学习周期都是一样的,后面考虑到数据的泛化能力,增加了norm、diff两个阶段的训练周期(其中norm指一般的数据增强【仿射变化、色彩变化】、diff【仿射变化、色彩变化、扭曲抖动】)。

        if epoch==Epochs_frozen*1:
            trainer.init_dataloader("norm","norm",mix_mode="cutmix",random_size=random_size)
        elif epoch==Epochs_frozen*3:
            trainer.init_dataloader("random_size","easy",mix_mode="cutmix",random_size=random_size)
            #trainer.reset_head()
        elif epoch==Epochs_frozen*4:
            trainer.init_dataloader("random_mask","easy",mix_mode="cutmix",random_size=random_size)
        elif epoch==Epochs_frozen*5:
            trainer.init_dataloader("norm","easy",mix_mode="cutmix",random_size=random_size)
        elif epoch==Epochs_frozen*7:
            trainer.init_dataloader("diff","easy",mix_mode="None",random_size=random_size)
            #trainer.reset_head()
        elif epoch==Epochs_frozen*9:
            trainer.init_dataloader("easy","easy",mix_mode="None",random_size=random_size)

2.1  0.97265时记录

该得分的训练尺寸为800*800,模型为SegFormer_B2。训练了近乎12个小时,得到了多个模型,后面不知怎么滴只剩下这两个。在这里博主并没有通过多尺度测试的方式选择最佳模型和size,而是随意测试。最后模型n800_PALM_SegFormer_B2_ep214_0.0234_0.9593.pdparams在size为896的情况下得到了0.97265的最佳成绩。此时,才将成绩突破到第二名。

n800_PALM_SegFormer_B2_ep214_0.0234_0.9593.pdparams n800_PALM_SegFormer_B2_ep180_0.0223_0.9593.pdparams

但是,30号下午一看,第二名变成了第三名。于此开始了第二阶段训练

2.2  0.97387时记录

以n800_PALM_SegFormer_B2_ep214_0.0234_0.9593.pdparams为基本模型,在896的size上继续训练数据。同样训练了近乎14个小时。得到了多个模型,具体如下图所示

 然后将选中的4个模型进行稳定性测试,具体代码细节如下所示

    shape_list=[x for x in range(896,1056,32)]
    modes=["easy","test"]#"n3_PALM_HarDNet_ep230_0.0240_0.9564.pdparams",
    model_paths=[
    #train on 864
    "n896_PALM_SegFormer_B2_ep189_0.0185_0.9663.pdparams",
    "n896_PALM_SegFormer_B2_ep258_0.0189_0.9645.pdparams",
    "n896_PALM_SegFormer_B2_ep273_0.0183_0.9649.pdparams",
    "n896_PALM_SegFormer_B2_ep280_0.0190_0.9632.pdparams",
    ]
    for path in model_paths:
        tag="mymodel/"
        model_path=tag+path
        trainer.load_model(model_path,eval_model=False)
        log_print("\n\n\n"+model_path,log_name)
        for shape in shape_list:
            for mode in modes:
                trainer.input_shape=(shape,shape)
                times=5
                if mode=="test":
                    times=1
                for i in range(times):
                    trainer.init_dataloader(mode,mode,mix_mode="none")
                    trainer.eval_model(log=False)
                    log_print("shape:%s  mode:%s   Val loss: %.4f, map: %.4f, iou: %.4f"%(shape,mode,trainer.val_loss,trainer.val_acc,trainer.val_iou),log_name)

经过测试后得到一堆性能数据,从数据中分析发现是ep280模型的性能最为稳定,size 896时最稳定。因此,就以该模型进行测试,得分数据如下所示。

928->(null-18)->96.997  896(null-17)->97.164  1024(null-16)->0.97257  1088(null-15)0.97381   1120(null-15)0.97356

load_weight = paddle.load("mymodel/n896_PALM_SegFormer_B2_ep280_0.0190_0.9632.pdparams"); 

为了更上一步,使用了MCDropout(测试13次取平均值)继续进行测试,得分数据如下所示。

1088(null-15)0.97387  1088(null-15)0.97373 1152(null-14)0.97277  1184(null-15)0.97027  1088(null-15,7次)0.97387

此时,成绩达到了最高点0.97387。

不过,从效果上看,MCDropout的性能并不稳定,对于比分提升有限。

猜你喜欢

转载自blog.csdn.net/a486259/article/details/125073403