深度分割模型比赛训练技巧(Tricks)

深度分割模型比赛训练技巧( T r i c k s ) 深度分割模型比赛训练技巧(Tricks) 深度分割模型比赛训练技巧(Tricks


深度分割模型比赛训练技巧示例


在深度模型中进行模型集成:偏向于使用Blend/Average,对多折模型的预测结果进行加权求和。
或者可以使用vote对模型结果进行投票


分割数据集图片中的目标应尽量在完整的出现在图中央,而不是被边缘分割。(OverLap进行要求,一般选输入数据大小的1/10,如果输入图片1024*1024,overlap可以设为124


在深度学习模型的训练中,dropout层是模型集成的非常典型的代表。
在训练时使用dropout,在预测时禁用dropout,等于集成了很多模型进行预测。


推荐使用的常用数据扩增

  • 翻转
  • 旋转或平移
  • 亮度改变
  • 颜色改变
  • 随机形变
  • 随机图像缩小

谨慎使用(高阶数据增强方法):

  • Mixup
  • CutMix
    在这里插入图片描述

手写数据增强推荐:OpenCV
直接调用库:推荐Albumentations
为什么不用torch或tf等框架自带的数据增强库,其实当然是可以使用的,只不过Albumentations是就打kaggle比赛的一群人写的库,天然会适合一点,而且别人也用习惯了,出现的早一点,提前占领了。


对于少量数据集的学习率调整策略,我建议使用类似于CosineAnnealingLR的策略,其存在学习率由小变大的过程,利于跳出局部最优。


需要调整的参数:
1.选择合适的样本量
2.网络模型
3.优化算法和学习率
4.损失函数
5.激活函数
6.图像预处理
推荐调参的顺序:
一般最后是网络模型
首先确定的是优化算法和学习率
其次是损失函数
之后是图像预处理


分割常用问题?
1.模型的精度多少才合适(比赛、论文上找找)
2.为什么这个这么低?是损失函数、还是预处理、还是数据集不均衡
3.分割和分类精度是否正常?如果不正常,如何设计loss,进行调整


实验之后与之前的数据分析是重中之重


如何解决自己分析数据之后的问题
1.莽试
2.找论文
3.找人问
4.找专门的网站
5.找专门的博客


技巧


多任务学习(Multi-Task):有利于解决
存在一个非常烦人的问题,就是比如多任务为分割与分类,这两个任务很有可能是矛盾的,分割好了,分类可能差,这对损失函数的调参需要一定的经验和多次尝试。


网络模型变换
1.增加网络“深度”(low)
2.更好的网络架构(好的网络块)(good)(找目前最新的论文)


输入图像大小调整:
一般原图大小左右就行
但会遇到一些特殊情况
可以考虑从128*128 -->256*256—>512*512—>1024*1024


loss轮番上:BCE—>Dice loss—>lovasz loss—>…


迁移学习:模型参数迁移起来,加快学习和收敛


常识性基础:

分割任务:Encoder(提取特征)+Decoder(还原分割)

Encoder(提取特征):
需要知道系列:
1.Vgg系列:vgg16、vgg19、se-vgg16…
2.Inception系列:v1、v2、v3
3.Densenet系列:DENSE块
4.SENet系列:SE块
5.ResNet家族系列:resnet系列、resnext系列、se-resnet系列、se-resnext系列....
6.Efficient系列:b0、b1、b2、b3、b4、b5、b6、b7....

Decoder(还原分割):
1.转置卷积
2.上池化
3.线性插值


一 确定合适的调参数据量,以便于快速进行Ideas的验证

这个具体可以结合时间,大概以一个Epoch在1-5min左右为准,跑10个Epoch,也就是10-50mins
具体图片的量的话,一般的机器,在几百到几千张。

一般建议,训练集在1-2w,验证集在1000-8000左右。这个和时间相矛盾,自己协调吧。

看你设置的合不合理,可以查看你的验证集的loss,是不是在稳定的下降。

二 一些参数值的推荐设置范围

early_stop_round = 5~10
learning_rate = 0.001~0.1(不能太小,也不能太大,感觉是废话)
batch_size = 看你机器了呗
image_size = 理论上是越大越好

学习率可视化

import torch
import torchvision

net = torchvision.models.resnet34(pretrained=False)
net_train_params = filter(lambda p: p.requires_grad, net.parameters())

optimizer = torch.optim.SGD(net_train_params , momentum=0.9, weight_decay=0.0001, lr=0.02)
#scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.3)
#scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[5, 30], gamma=0.1)
scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.99)

for epoch in range(200):
    #train
    print('lr: %.4f, epoch: %d'%(scheduler.get_lr()[0], epoch))
    scheduler.step()

测试你机器显存,是否能撑起这个网络的batch_size和image_size的组合

import sys
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import cv2
import torch
from dataset.dataset_unet import prepare_trainset
from major_model import UNet_puls_plus_plus
%matplotlib inline

sys.path.append('../')
def Test_VRAM(BATCH_SIZE=2, IMG_SIZE=512, device=device):
    train_dl, val_dl = prepare_trainset(BATCH_SIZE=BATCH_SIZE, 
                                        NUM_WORKERS=8, 
                                        SEED=2019, 
                                        IMG_SIZE=IMG_SIZE, debug=True)

    for i, (images, masks) in enumerate(train_dl):#一次读取一个Bath
        images = images.to(device=device, dtype=torch.float)
        masks = masks.to(device=device, dtype=torch.float)
        if i==0:
            break

    print(images.size(), masks.size())
    
    ##
    net = UNet_puls_plus_plus(debug=False)
    net = net.to(device=device)
    
    logit = net(images)
    print('Pass')
Test_VRAM(BATCH_SIZE=2, IMG_SIZE=512, device='cuda:0')#'cpu'#'cuda:0'

三 Loss的选择

  • Focal Loss
    问题:各类别数据不均衡
    原理:根据样本概率调节
    实现:https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/65938

  • Dice Loss

  • BCE Loss

  • Weight Loss

  • Boundary Loss

  • Lovasz-Softmax Loss:
    问题:IOU和Dice非常容易受到类别影响;
    原理︰结合Lovasz hinge和Jaccard loss解决二值图片的分割问题;
    实现: https://github.com/bermanmaxim/LovaszSoftmax

  • TopK Loss

  • Hausdorff Distance Loss

  • Sensitivity Specificity Loss

  • Distance Penalized CE Loss

  • Colour-Aware Loss

  • OHEM
    问题:重点关注错误样本;
    原理:增加错误样本的loss,或将错误样本再训练;
    实现:

import torch
from torch import nn
import torch.nn.functional as F

__all__ = [
    "BCEWithLogitsLossWithOHEM",
    "CrossEntropyLossWithOHEM",
    "DiceLoss",
    "SoftCrossEntropyLossWithOHEM",
]


def _ohem_mask(loss, ohem_ratio):
    with torch.no_grad():
        values, _ = torch.topk(loss.reshape(-1),
                               int(loss.nelement() * ohem_ratio))
        mask = loss >= values[-1]
    return mask.float()


class BCEWithLogitsLossWithOHEM(nn.Module):
    def __init__(self, ohem_ratio=1.0, pos_weight=None, eps=1e-7):
        super(BCEWithLogitsLossWithOHEM, self).__init__()
        self.criterion = nn.BCEWithLogitsLoss(reduction='none',
                                              pos_weight=pos_weight)
        self.ohem_ratio = ohem_ratio
        self.eps = eps

    def forward(self, pred, target):
        loss = self.criterion(pred, target)
        mask = _ohem_mask(loss, self.ohem_ratio)
        loss = loss * mask
        return loss.sum() / (mask.sum() + self.eps)

    def set_ohem_ratio(self, ohem_ratio):
        self.ohem_ratio = ohem_ratio


class CrossEntropyLossWithOHEM(nn.Module):
    def __init__(self,
                 ohem_ratio=1.0,
                 weight=None,
                 ignore_index=-100,
                 eps=1e-7):
        super(CrossEntropyLossWithOHEM, self).__init__()
        self.criterion = nn.CrossEntropyLoss(weight=weight,
                                             ignore_index=ignore_index,
                                             reduction='none')
        self.ohem_ratio = ohem_ratio
        self.eps = eps

    def forward(self, pred, target):
        loss = self.criterion(pred, target)
        mask = _ohem_mask(loss, self.ohem_ratio)
        loss = loss * mask
        return loss.sum() / (mask.sum() + self.eps)

    def set_ohem_ratio(self, ohem_ratio):
        self.ohem_ratio = ohem_ratio


class DiceLoss(nn.Module):
    def __init__(self, eps=1e-7):
        super(DiceLoss, self).__init__()
        self.eps = eps

    def forward(self, pred, target):
        pred = torch.sigmoid(pred)
        intersection = (pred * target).sum()
        loss = 1 - (2. * intersection) / (pred.sum() + target.sum() + self.eps)
        return loss


class SoftCrossEntropyLossWithOHEM(nn.Module):
    def __init__(self, ohem_ratio=1.0, eps=1e-7):
        super(SoftCrossEntropyLossWithOHEM, self).__init__()
        self.ohem_ratio = ohem_ratio
        self.eps = eps

    def forward(self, pred, target):
        pred = F.log_softmax(pred, dim=1)
        loss = -(pred * target).sum(1)
        mask = _ohem_mask(loss, self.ohem_ratio)
        loss = loss * mask
        return loss.sum() / (mask.sum() + self.eps)

    def set_ohem_ratio(self, ohem_ratio):
        self.ohem_ratio = ohem_ratio

1.BCE:二分类交叉熵

在这里插入图片描述

2.Weighted BCE

在这里插入图片描述

3.Focal Loss

在这里插入图片描述

4.Dice Loss

在这里插入图片描述

5.组合Loss

  • BCE+DICE
  • 多任务模型,分割loss+分类loss

参考文献

https://lars76.github.io/2018/09/27/loss-functions-for-segmentation.html
https://www.jeremyjordan.me/semantic-segmentation/
https://gombru.github.io/2018/05/23/cross_entropy_loss/
Focal loss paper,Facebook
Lovasz loss,optimize lou

四 优化器选择

啊,这个随便选吧,影响不大。

无论是pytorch还是tensorflow,或者其他,都有API可以调用。用框架提供的就🆗了

选SGD,Adma…,再加一个Momentum动量就差不多了

五 多尺度怎么加

  • ASPP
  • PPM
  • DCM
  • DenseASPP
  • FPA
  • OCVet
  • MPM

六 注意力机制怎么加

SE
Non-local
CcNet
GC-Net
Gate
CBAM
Dual Attention
Spatial Attention
Channel Attention

七 卷积块选择

Residual block
Bottle-neck block
Split-Attention block
Depthwise separable convolution
Recurrent convolution
Group convolution
Dilated convolution
Octave convolution
Ghost convolution

八 使用伪标签

当模型精度较高时
当比赛规则允许时

GAN网络的威力,有时候会非常大,在伪标签的使用中


伪标签制作

  • 步骤1∶使用训练切图的方法对测试集进行切图(大型图像)
  • 步骤2∶对测试集切图进行预测
  • 步骤3︰人工修正预测结果&选择模型预测较好的结果
  • 步骤4︰将筛选后图片加入训练集切图一起训练

这里提出一个非常搞笑的事情,就是实际在很多实际项目中,数据集的label很可能被标错、标漏、标坏,这种现象非常常见


九 自动化搜索

深度学习自动调参
搜索超参数;
1.网格/随机搜索
2.贝叶斯搜索;

搜索网络结构;

自动化调参工具:

十 基础Net选择

自然、复杂场景下:Mask-RCNN
医学、简单场景下:UNet


如果有类别不均衡的情况,可以先分类再分割;


深度模型的深度最好和感受野相关,就是计算最后的感受野和原图近似等大时的深度会较佳


十一 Test Time Augmentation


在计算资源有限的情况下,不采用多折,使用单折训练
深度学习中单折模型中的模型集成方法: Snapshot Ensemble / Stochastic Weight Averaging

训练过程中保存多个中间权重,进行集成;

十二 池化层选择

Max pooling
Average pooling
Random pooling
Strip Pooling
Mixed Pooling

  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值