MixUp 和朋友

可将 MixUp(及变体)数据增强应用于训练的回调函数
from fastai.vision.all import *

源码

reduce_loss

 reduce_loss (loss:torch.Tensor, reduction:str='mean')

根据 reduction 减少损失

类型 默认值 详情
loss Tensor
reduction str mean PyTorch 损失减少方式
返回值 Tensor

源码

MixHandler

 MixHandler (alpha:float=0.5)

用于实现 MixUp 风格调度的处理类

类型 默认值 详情
alpha float 0.5 确定 Beta 分布在范围 (0.,inf] 内

大多数 Mix 变体将在批次上执行数据增强,因此要实现你的 Mix,你应该根据你的训练方案调整 before_batch 事件。如果需要不同的损失函数,你也应该调整 lfalpha 被传递给 Beta 以创建一个采样器。


源码

MixUp

 MixUp (alpha:float=0.4)

实现 https://arxiv.org/abs/1710.09412

类型 默认值 详情
alpha float 0.4 确定 Beta 分布在范围 (0.,inf] 内

这是 MixUp 的一个修改实现,它总是至少混合原始图像的 50%。原始论文要求使用 Beta 分布,该分布在损失函数中的每个位置都传递相同的 alpha 值(alpha = beta = #)。与原始论文不同的是,此 MixUp 实现选择 lambda 的最大值,这意味着如果采样到的 lambda 值小于 0.5(即原始图像表示率小于 50%),则使用 1-lambda 代替。

两张图像的混合程度由 alpha 决定。

\(alpha=1.\):

  • 所有介于 0 和 1 之间的值都有相等的采样机会。
  • 两张图像之间可以进行任何程度的混合

\(alpha<1.\):

  • 接近 0 和 1 的值比接近 0.5 的值更有可能被采样。
  • 更有可能选择其中一张图像,并加入少量另一张图像。

\(alpha>1.\):

  • 接近 0.5 的值比接近 0 或 1 的值更有可能被采样。
  • 更有可能将图像均匀混合。

首先,我们将看一个非常简洁的例子,展示如何使用 PETS 数据集生成数据

path = untar_data(URLs.PETS)
pat        = r'([^/]+)_\d+.*$'
fnames     = get_image_files(path/'images')
item_tfms  = [Resize(256, method='crop')]
batch_tfms = [*aug_transforms(size=224), Normalize.from_stats(*imagenet_stats)]
dls = ImageDataLoaders.from_name_re(path, fnames, pat, bs=64, item_tfms=item_tfms, 
                                    batch_tfms=batch_tfms)

我们可以通过在 fit 期间,在 before_batch 事件中获取数据来检查我们的 Callback 的结果,如下所示:

mixup = MixUp(1.)
with Learner(dls, nn.Linear(3,4), loss_func=CrossEntropyLossFlat(), cbs=mixup) as learn:
    learn.epoch,learn.training = 0,True
    learn.dl = dls.train
    b = dls.one_batch()
    learn._split(b)
    learn('before_train')
    learn('before_batch')

_,axs = plt.subplots(3,3, figsize=(9,9))
dls.show_batch(b=(mixup.x,mixup.y), ctxs=axs.flatten())
轮次 训练损失 验证损失 时间
0 00:00

我们可以看到,图像会时不时地与另一张图像“混合”。

如何训练?你可以直接将 Callback 传递给 Learner,或者在你的 fit 函数中传递给 cbs

learn = vision_learner(dls, resnet18, loss_func=CrossEntropyLossFlat(), metrics=[error_rate])
learn.fit_one_cycle(1, cbs=mixup)
轮次 训练损失 验证损失 错误率 时间
0 2.041960 0.495492 0.162382 00:12

源码

CutMix

 CutMix (alpha:float=1.0)

实现 https://arxiv.org/abs/1905.04899

类型 默认值 详情
alpha float 1.0 确定 Beta 分布在范围 (0.,inf] 内

类似于 MixUpCutMix 会从两张图像中随机剪切一个区域并互相交换。我们可以看看下面的一些例子。

cutmix = CutMix(1.)
with Learner(dls, nn.Linear(3,4), loss_func=CrossEntropyLossFlat(), cbs=cutmix) as learn:
    learn.epoch,learn.training = 0,True
    learn.dl = dls.train
    b = dls.one_batch()
    learn._split(b)
    learn('before_train')
    learn('before_batch')

_,axs = plt.subplots(3,3, figsize=(9,9))
dls.show_batch(b=(cutmix.x,cutmix.y), ctxs=axs.flatten())
轮次 训练损失 验证损失 时间
0 00:00

我们也以完全相同的方式进行训练。

learn = vision_learner(dls, resnet18, loss_func=CrossEntropyLossFlat(), metrics=[accuracy, error_rate])
learn.fit_one_cycle(1, cbs=cutmix)
轮次 训练损失 验证损失 准确率 错误率 时间
0 3.440883 0.793059 0.769959 0.230041 00:12