Datawhale AI 夏令营2024·第二期(Deepfake攻防挑战赛-图像赛道)Task03

系列文章目录

Datawhale AI 夏令营2024·第二期(Deepfake攻防挑战赛-图像赛道)Task01
Datawhale AI 夏令营2024·第二期(Deepfake攻防挑战赛-图像赛道)Task02



前言

上次九月哥开会,确确实实讲了很多东西,很触动我。影响最深的就是“严打抄袭”,确实,一个纯粹的科研人是不应该这么做,也让我反思,自己所做的东西有多少沾了“抄袭”的边,另外一个很触动的东西就是“致谢”,看了九月哥的知乎,确确实实,上次Task02的内容,前面部分的Pytorch基础部分是DataWhale发布的教程代码,自己确实没加上link。

关于数据增强

数据增强就是通过对数据进行变化和扩充,在原有数据量的基础之上,使其更加多样性复杂,来让训练出来的模型更加泛化和鲁棒。

一、数据增强常用方法

这里以torchvision为例

torchvision中的transforms方法如下

Compose: 将多个转换组合在一起。
ToTensor: 将PIL图像或numpy数组转换为PyTorch张量。
PILToTensor: 将PIL图像转换为PyTorch张量。
ConvertImageDtype: 转换图像的数据类型。
ToPILImage: 将Tensor或数组转换为PIL图像。
Normalize: 标准化图像的通道。
Resize: 调整图像大小。
CenterCrop: 中心裁剪图像。
Pad: 填充图像。
Lambda: 应用自定义Lambda函数。
RandomApply: 随机应用一组转换中的某些。
RandomChoice: 随机选择一组转换中的一个。
RandomOrder: 随机顺序应用一组转换。
RandomCrop: 随机裁剪图像。
RandomHorizontalFlip: 随机水平翻转图像。
RandomVerticalFlip: 随机垂直翻转图像。
RandomResizedCrop: 随机裁剪并调整大小。
FiveCrop: 对图像进行五点裁剪。
TenCrop: 对图像进行十点裁剪。
LinearTransformation: 线性变换。
ColorJitter: 随机颜色抖动。
RandomRotation: 随机旋转图像。
RandomAffine: 随机仿射变换。
Grayscale: 转换图像为灰度图。
RandomGrayscale: 随机转换图像为灰度图。
RandomPerspective: 随机透视变换。
RandomErasing: 随机擦除部分图像区域。
GaussianBlur: 高斯模糊。
InterpolationMode: 插值方法。
RandomInvert: 随机反转图像像素。
RandomPosterize: 随机Posterize图像。
RandomSolarize: 随机Solarize图像。
RandomAdjustSharpness: 随机调整图像锐度。
RandomAutocontrast: 随机自动对比度调整。
RandomEqualize: 随机均衡化图像。
ElasticTransform: 弹性变换。

torchvision中的autoaugment方法如下

这个autoaugment方法就是自动增强,AutoAugmentPolicy是针对不同数据集的在源代码中是针对“imagenet”,“cifar10”和“svhn”三个数据集,各自有不同的数据增强的方法,并且有不同的参数和比例。

但是自动增强有一个弊端,这在上次直播时也提到了,自动增强的可控性差,会导致结果不稳定把。

下面是上次直播中重点讲到的两种数据增强方法,分别是CutMix和MixUp

二、CutMix方法

CutMix 是由韩国KAIST大学的研究人员于2019年在CVPR上提出的。它的核心思想是将两张图像的一部分混合在一起,生成一个新的训练样本。

CutMix主要分为两个部分

  • 第一部分是随机截取,就是在现有图片边界范围内随机截取一部分作为下一步替换的内容。
  • 第二部分是换位置。也可以这样这样理解,就是在一个CutOut的基础上,将一张图片空出来的位置由另一部分替换。

从训练集找了几张图片,大家凑活着看。

这个是原始图片

这是原图

这个是cutmix后的图片

cutmix

关于代码实现

这里代码部分出自pytorch 数据增强cutmix的实现,感谢视觉盛宴。

import glob
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = [10,10]
import cv2

# Path to data
data_folder = f".\\data\\"

# Read filenames in the data folder
filenames = glob.glob(f"{data_folder}*.jpeg")
# Read first 10 filenames
image_paths = filenames[:4]

# Display a sample image
# plt.imshow(cv2.cvtColor(cv2.imread(image_paths[0]), cv2.COLOR_BGR2RGB)); plt.show();


image_batch = []
image_batch_labels = []
n_images = 4
print(image_paths)
for i in range(4):
    image = cv2.cvtColor(cv2.imread(image_paths[i]), cv2.COLOR_BGR2RGB)
    image_batch.append(image)
image_batch_labels=np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]])
# for i in range(2):
#     for j in range(2):
#         plt.subplot(2,2,2*i+j+1)
#         plt.imshow(image_batch[2*i+j])
# plt.show()
def rand_bbox(size, lamb):
    W = size[0]
    H = size[1]
    cut_rat = np.sqrt(1. - lamb)
    cut_w = int(W * cut_rat)
    cut_h = int(H * cut_rat)

    # uniform
    cx = np.random.randint(W)
    cy = np.random.randint(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
image = cv2.cvtColor(cv2.imread(image_paths[0]), cv2.COLOR_BGR2RGB)
# Crop a random bounding box
lamb = 0.3
size = image.shape
print('size',size)
# bbox = rand_bbox(size, lamb)

# # Draw bounding box on the image
# im = image.copy()
# x1 = bbox[0]
# y1 = bbox[1]
# x2 = bbox[2]
# y2 = bbox[3]
# cv2.rectangle(im, (x1, y1), (x2, y2), (255, 0, 0), 3)
# plt.imshow(im);
# plt.title('Original image with random bounding box')
# plt.show();

# Show cropped image
# plt.imshow(image[y1:y2, x1:x2]);
# plt.title('Cropped image')
# plt.show()
def generate_cutmix_image(image_batch, image_batch_labels, beta):

    # generate mixed sample
    lam = np.random.beta(beta, beta)
    rand_index = np.random.permutation(len(image_batch))
    target_a = image_batch_labels
    target_b = np.array(image_batch_labels)[rand_index]
    print('img.shape',image_batch[0].shape)
    bbx1, bby1, bbx2, bby2 = rand_bbox(image_batch[0].shape, lam)
    print('bbx1',bbx1)
    print('bby1',bby1)
    print('bbx2',bbx2)
    print('bby1',bby1)
    image_batch_updated = image_batch.copy()
    image_batch_updated=np.array(image_batch_updated)
    image_batch=np.array(image_batch)
    image_batch_updated[:, bbx1:bby1, bbx2:bby2, :] = image_batch[rand_index, bbx1:bby1, bbx2:bby2, :]
    
    # adjust lambda to exactly match pixel ratio
    lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / (image_batch.shape[1] * image_batch.shape[2]))
    label = target_a * lam + target_b * (1. - lam)
    
    return image_batch_updated, label
# image_batch=np.array(image_batch)
# image_batch_updated = image_batch.copy()
# c=[1,0,2,3]
# mm=np.array(image_batch_updated)
# mm[:, 10:200, 10:200, :] = image_batch[c, 10:200, 10:200, :]
# Generate CutMix image
# Let's use the first image of the batch as the input image to be augmented
input_image = image_batch[0]
image_batch_updated, image_batch_labels_updated = generate_cutmix_image(image_batch, image_batch_labels, 1.0)

# Show original images
print("Original Images")
for i in range(2):
    for j in range(2):
        plt.subplot(2,2,2*i+j+1)
        plt.imshow(image_batch[2*i+j])
plt.show()


# Show CutMix images
print("CutMix Images")
for i in range(2):
    for j in range(2):
        plt.subplot(2,2,2*i+j+1)
        plt.imshow(image_batch_updated[2*i+j])
plt.show()

# Print labels
print('Original labels:')
print(image_batch_labels)
print('Updated labels')
print(image_batch_labels_updated)

三、MixUp方法

它的核心思想是将两个样本的特征和标签按比例相加,生成一个新的样本。

  • 首先给定两个样本 x i x_i xi x j x_j xj,以及对应的标签 y i y_i yi y j y_j yj
  • 通过线性插值,构造新的样本 x ~ \tilde{x} x~ y ~ \tilde{y} y~
    x ~ = λ x i + ( 1 − λ ) x j y ~ = λ y i + ( 1 − λ ) y j \tilde{x}=\lambda x_i + (1-\lambda) x_j \\ \tilde{y}=\lambda y_i +(1-\lambda)y_j x~=λxi+(1λ)xjy~=λyi+(1λ)yj

下面的部分还是这两张图片。

原始的两张图片

我们把mixup处理后的图片贴上

处理之后的图片

mixup

这里附上代码

这里的代码参考自数据增强实测之mixup,感觉这个人家说的也简单,就自己写了一下也是。感谢一个菜鸟的奋斗。

import cv2
import numpy as np


img1 = cv2.imread('1.jpeg')
img2 = cv2.imread('3.jpeg')

img1 = cv2.resize(img1, (224, 224))
img2 = cv2.resize(img2, (224, 224))

alpha = np.random.uniform(0, 1)  # 这里定义一个0到1之间的随机小数
print(alpha)
miximg = alpha * img1 + (1- alpha) * img2

cv2.imwrite('mix.png', miximg)

最后就是关于数据增强的一点,不是越多越好,过度了就麻烦了。

关于比赛提交的内容

  • 后面又取前100000条数据跑了一下,用ResNet18跑到了0.769
  • 因为原始的数据中就有使用数据增强,一开始的baseline是使用的随机的水平和垂直翻转。
  • 而后面又使用了一下随机裁切,相同的参数设置,最后跑出来的是0.764,下降了。这也印证了数据增强不是随意堆砌就好了。
  • 后面有用了颜色抖动,发现效果也不是很好,最后的结果只有0.702

结语

在这次的DataWhale夏令营中,收获良多,因为不仅是我见识到了和全国的AI小伙伴们一起同台共竞技的场面,更是因为这次夏令营带给我自身的成长机会。人外有人啊小伙伴们,😁😁😁,你我且多多努力。
还有就是感谢DataWhale提供的机会(这样的机会以后应该还会有,会多多参加的),感谢助教和大佬,感谢所有的link到的博主,结营快乐😊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值