数据增强方式:调整亮度,对比度,色调,随机缩放,剪切,翻转,旋转等;
Mosaic data augmentation:
- Mixup:两张图象按照不同的比例混合,分类结果按照混合比例分配;
- Cutout:随机将图片中的区域大小(个人观点裁剪区域图像大小为0.25左右较为合适,比例再大准确率下降明显)裁剪用0填充,结果分类不发生变化;
- Cutmix:随机裁剪图像的区域大小,不填充0而是随机选择其他样本的裁剪区域大小填充,结果根据裁剪填充的比例分类【Cutmix = Mixup + Cutout】。
对比:
Mixup和Cutmix:前者是将两张图根据设定比例插值融合,如图所示,若隐若现。
Cutout和Cutmix:前者对随机区域大小使用0填充,后者两张图像的填充。而yolo中类似cutmix使用4张图。
import torch
import torch.nn as nn
import numpy as np
# cutmix和mixup的实现代码
def rand_bbox(size, lam):
"""
随机生成裁剪框大小区域
输入参数:图像大小,和随机生成的参数lambda
"""
W = size[2]
H = size[3]
# 计算裁剪框区域大小的w和h;
cut_rat = np.sqrt(1. - lam)
cut_w = np.int(W * cut_rat)
cut_h = np.int(H * cut_rat)
# uniform
# randint函数计算中心点,此处计算中心点
cx = np.random.randint(W)
cy = np.random.randint(H)
# 裁剪区域大小不能超过W和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
def cutmix(data, targets1, targets2, targets3, alpha):
indices = torch.randperm(data.size(0))
shuffled_data = data[indices]
shuffled_targets1 = targets1[indices]
shuffled_targets2 = targets2[indices]
shuffled_targets3 = targets3[indices]
lam = np.random.beta(alpha, alpha) # 随机生成lambda,符合beta分布
bbx1, bby1, bbx2, bby2 = rand_bbox(data.size(), lam) # 获得裁剪框
data[:, :, bbx1:bbx2, bby1:bby2] = data[indices, :, bbx1:bbx2, bby1:bby2]
# adjust lambda to exactly match pixel ratio
lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / (data.size()[-1] * data.size()[-2]))
targets = [targets1, shuffled_targets1, targets2, shuffled_targets2, targets3, shuffled_targets3, lam]
return data, targets
def mixup(data, targets1, targets2, targets3, alpha):
indices = torch.randperm(data.size(0))
shuffled_data = data[indices]
shuffled_targets1 = targets1[indices]
shuffled_targets2 = targets2[indices]
shuffled_targets3 = targets3[indices]
lam = np.random.beta(alpha, alpha)
data = data * lam + shuffled_data * (1 - lam)
targets = [targets1, shuffled_targets1, targets2, shuffled_targets2, targets3, shuffled_targets3, lam]
return data, targets
def cutmix_criterion(preds1,preds2,preds3, targets):
targets1, targets2,targets3, targets4,targets5, targets6, lam = targets[0], targets[1], targets[2], targets[3], targets[4], targets[5], targets[6]
criterion = nn.CrossEntropyLoss(reduction='mean') # 交叉熵损失计算
return lam * criterion(preds1, targets1) + (1 - lam) * criterion(preds1, targets2) + lam * criterion(preds2, targets3) + (1 - lam) * criterion(preds2, targets4) + lam * criterion(preds3, targets5) + (1 - lam) * criterion(preds3, targets6)
def mixup_criterion(preds1,preds2,preds3, targets):
targets1, targets2,targets3, targets4,targets5, targets6, lam = targets[0], targets[1], targets[2], targets[3], targets[4], targets[5], targets[6]
criterion = nn.CrossEntropyLoss(reduction='mean')
return lam * criterion(preds1, targets1) + (1 - lam) * criterion(pr