相关介绍
Mixup方法
mixup的方法是将数据混合构建虚拟样本,如下图有两个数据点A、B,其中A是class 0,而B是class 1,Label对应就是一个one hot向量。mixup就是通过混合AB来构建虚拟数据点,同时标签也进行混合得到概率分布(非one-hot标签),这样就得到了新的样本。
Cutout方法
Cutout的方法随机的将样本中的部分区域cut掉,并且填充0像素值,分类的结果不变。
CutMix
CutMix就是将CutOut和Mixup结合。原理图如下:CutMix相比于Cutout就是将区域删除操作变成截取另外一张图片一样大小的区域填充该区域,同时改变新图片的标签。这样的处理,使得CutMix不会改变整个数据集的分布。
流程
CutMix 的目标是通过组合两个训练样本 ( Xa, Ya ) 和 ( Xb, Yb ) 来生成一个新的训练样本 ( x ~ \tilde{x} x~ , y ~ \tilde{y} y~ )。
x ~ = M ⊙ x A + ( 1 − M ) ⊙ x B y ~ = λ y A + ( 1 − λ ) y B \begin{aligned} \tilde{x} & =\mathbf{M} \odot x_{A}+(\mathbf{1}-\mathbf{M}) \odot x_{B} \\ \tilde{y} & =\lambda y_{A}+(1-\lambda) y_{B} \end{aligned} x~y~=M⊙xA+(1−M)⊙xB=λyA+(1−λ)yB
其中M 是一个二值Mask,对于Xa来说,M=1部分的图像被保留,对于Xb来说,M=0的部分被留下。 两个数据点之间的组合比率λ从Beta( α , α )中采样。在所有实验中,α都设置为 1,即λ是从均匀分布 (0, 1) 中采样的。
为了对二进制掩码 M 进行采样,我们首先对表示Xa和Xb上的裁剪区域的边界框坐标B = ( Rx , Ry , Rw , Rh ) 进行采样。 Xa中的被选中区域被移除并用从Xb被选中的区域裁剪的补丁填充。
r x ∼ Unif ( 0 , W ) , r w = W 1 − λ r y ∼ Unif ( 0 , H ) , r h = H 1 − λ \begin{aligned} r_{x} & \sim \operatorname{Unif}(0, W), \quad r_{w}=W \sqrt{1-\lambda} \\ r_{y} & \sim \operatorname{Unif}(0, H), \quad r_{h}=H \sqrt{1-\lambda} \end{aligned} rxry∼Unif(0,W),rw=W1−λ∼Unif(0,H),rh=H1−λ
算法步骤
生成裁剪部分
# 输入:样本的size和随机生成lamda值
# 输出:裁剪B区域的坐标
def rand_bbox(size, lam):
W = size[2]
H = size[3]
# 1 论文中的公式2,求出B的rw,rh
cut_rat = np.sqrt(1. - lam)
cut_w = np.int(W * cut_rat)
cut_h = np.int(H * cut_rat)
# 2 论文中的公式2,求出B的rx,ry(bbox的中心点)
cx = np.random.randint(W)
cy = np.random.randint(H)
#控制边界在(0--W或者0--H之间)
bbx1 = np.clip(cx - cut_w // 2, 0, W)
bby1 = np.clip(cy - cut_h // 2, 0, H)
bbx2 = np.clip(cx + cut_w // 2, 0, W)
bby2 = np.clip(cy + cut_h // 2, 0, H)
return bbx1, bby1, bbx2, bby2
整体流程
input = input.cuda()
target = target.cuda()
r = np.random.rand(1)
if args.beta > 0 and r < args.cutmix_prob:
# generate mixed sample
lam = np.random.beta(args.beta, args.beta)#随机的lam
rand_index = torch.randperm(input.size()[0]).cuda()#在batch中随机抽取一个样本,记为i
target_a = target
target_b = target[rand_index]#获取该样本的标签
bbx1, bby1, bbx2, bby2 = rand_bbox(input.size(), lam)#随机产生一个box的四个坐标
input[:, :, bbx1:bbx2, bby1:bby2] = input[rand_index, :, bbx1:bbx2, bby1:bby2]#将样本i中box的像素值填充该批数据中相同区域
# adjust lambda to exactly match pixel ratio
lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / (input.size()[-1] * input.size()[-2]))#按照box面积计算lam
# compute output
output = model(input)
loss = criterion(output, target_a) * lam + criterion(output, target_b) * (1. - lam)#通过lam融合损失
else:
# compute output
output = model(input)
loss = criterion(output, target)
实验
实验就是好,good,完结撒花!
参考资料
https://arxiv.org/abs/1905.04899
https://github.com/clovaai/CutMix-PyTorch
https://zhuanlan.zhihu.com/p/538455618