浅谈分割任务中data augmentation的概率问题

数据增强在视觉任务中算是一种基本都训练技巧,例如对于分类任务而言,我们常常能看到如下形式的代码(pytorch):

from torchvision import transforms
self.img_transform = transforms.Compose([
    transforms.RandomRotation(90),
    transforms.RandomVerticalFlip(p=0.5),
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.Resize((256, 256)),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],
                         [0.229, 0.224, 0.225])])

而到了分割任务上,由于分割的标签本身也是图片,因此同样需要进行transform。一个直观的做法是将对图片所进行的增强直接给照搬到标签上来,比如:

from torchvision import transforms
self.img_transform = transforms.Compose([
    transforms.RandomRotation(90),
    transforms.RandomVerticalFlip(p=0.5),
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.Resize((256, 256)),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],
                         [0.229, 0.224, 0.225])])
self.gt_transform = transforms.Compose([
    transforms.RandomRotation(90),
    transforms.RandomVerticalFlip(p=0.5),
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.Resize((self.trainsize, self.trainsize)),
    transforms.ToTensor()
])

但是,这种写法实际上是错误的。原因在于,许多数据增强本身是概率性的,例如transforms.RandomVerticalFlip(p=0.5)表示以50%的概率对输入图像进行垂直翻转。而对图像和标签应用两个独立的概率,就可能会出现图像翻转了而标签没翻转的不匹配情况。

正确的解法对各种概率变换进行单独的封装,将概率给抽离出来,例如:

import torchvision.transforms.functional as F
import random

class RandomVerticalFlip(object):
    def __init__(self, p=0.5):
        self.p = p

    def __call__(self, data):
        image, label = data['image'], data['label']

        if random.random() < self.p:
            return {'image': F.vflip(image), 'label': F.vflip(label)}

        return {'image': image, 'label': label}

data = {'image': image, 'label': label}
data = RandomVerticalFlip()(data)
要在mmdetection添加自定义数据增强,可以按照以下步骤进行操作: 1. 创建自定义数据增强类 在mmdetection的代码找到`mmdet/datasets/pipelines`文件夹,在该文件夹下面创建一个新的python文件,例如`my_augmentations.py`。在该文件定义一个自定义的数据增强类,例如: ```python import numpy as np from mmdet.core.evaluation.bbox_overlaps import bbox_overlaps class MyAugmentation: def __init__(self, prob=0.5): self.prob = prob def __call__(self, results): if np.random.rand() < self.prob: # perform some data augmentation operations # ... return results else: return results ``` 在这个例子,我们定义了一个名为`MyAugmentation`的类,它有一个`prob`参数,表示增强的概率,以及一个`__call__`方法,该方法将在数据增强时被调用。在`__call__`方法,我们可以实现一些自定义的数据增强操作。这个例子的操作是随机选择是否对数据进行增强。 2. 在配置文件添加自定义数据增强 在使用自定义数据增强之前,我们需要在配置文件添加它。找到你要使用的配置文件,例如`configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py`,并在`train_pipeline`和`test_pipeline`添加自定义数据增强,例如: ```python train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations', with_bbox=True), dict(type='RandomFlip', flip_ratio=0.5), dict(type='MyAugmentation', prob=0.5), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']), ] test_pipeline = [ dict(type='LoadImageFromFile'), dict( type='MultiScaleFlipAug', img_scale=(1333, 800), flip=False, transforms=[ dict(type='Resize', keep_ratio=True), dict(type='RandomFlip'), dict(type='MyAugmentation', prob=0.5), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']), ] ) ] ``` 在这个例子,我们在`train_pipeline`和`test_pipeline`分别添加了一个`MyAugmentation`操作,其概率为0.5。注意,自定义操作需要在其他操作之前进行,因为它们可能会改变图像和标注框的大小和形状。 3. 运行训练和测试 添加自定义数据增强后,我们可以像平常一样运行训练和测试。在运行过程,自定义数据增强会被应用到输入数据,从而增加模型的鲁棒性和泛化能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值