Deepfake攻防--图像赛道是该夏令营第二期的学习活动(“CV图像”方向),是于蚂蚁集团举办的“外滩大会-全球Deepfake攻防挑战赛”开展的实践学习——适合想入门、了解并实践,关于深度学习和计算机视觉方向的学习者参与。此次学习活动的速通手册如下:从零入门CV图像竞赛(Deepfake攻防) - 飞书云文档 (feishu.cn)
本文是本人在完成baseline的基础上,对所学知识点进行的总结概括,欢迎各位大佬交流讨论、批评指正。
一、问题背景
背景简介
所谓Deepfake,就是一种使用人工智能技术生成的伪造媒体,特别是视频和音频,它们看起来或听起来非常真实,但实际上是由计算机生成的,例如AI换脸技术、语音模拟等。该技术虽然在多个领域展现出其创新潜力,但其滥用也带来了一系列严重的危害。
赛事任务
该比赛的任务是判断人脸图像是否为Deepfake图像,并输出其为Deepfake图像的概率评分,本质是一个图像二分类任务。
赛题数据
MultiFF数据集基于蚂蚁集团发布的《假数字人脸检测金融应用技术规范》构建而成。同时,结合数字业务中的实际防御经验,纳入真正多元化的深度伪造攻击,主要包括:
1.攻击类型广泛:包括换脸、激活、属性编辑、全脸合成、音频驱动人脸生成、人脸还原、数字对抗样本、自动化PS等常见类型。
2.多种生成方法:超过50种Deepfake生成方法应用于整个数据集。除了经典的GANs模型外,生成模型还完全覆盖了Diffusion系列的全新生成式AI模型。攻击生成范式包括图像到图像生成、文本到图像生成、文本到语音生成、文本到视频生成等。
以下展示的是deepfake中的trainset的部分数据集。
评价指标
比赛的性能评估,主要使用ROC曲线中的 AUC(ROC 曲线下的面积)作为指标。AUC的取值范围一般在0.5到1之间。如果AUC指标不能区分排名,则会使用TPR@FPR=1E-3作为辅助参考。
二、模型训练
Datawhale夏令营提供的baseline实现流程,如下图所示。我们需要在此模型的基础上,首先能运行baseline,再对模型的内容进行改进。
导入数据与相关库
import torch
torch.manual_seed(0)
torch.backends.cudnn.deterministic = False
torch.backends.cudnn.benchmark = True
import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data.dataset import Dataset
import timm
import time
import pandas as pd
import numpy as np
import cv2
from PIL import Image
from tqdm import tqdm_notebook
# 读取数据集
train_label = pd.read_csv('/kaggle/input/deepfake/phase1/trainset_label.txt')
val_label = pd.read_csv('/kaggle/input/deepfake/phase1/valset_label.txt')
#设置数据集的标签位置
train_label['path'] = '/kaggle/input/deepfake/phase1/trainset/' + train_label['img_name']
val_label['path'] = '/kaggle/input/deepfake/phase1/valset/' + val_label['img_name']
加载预训练模型
timm(Pytorch Image Models)是一个基于Pytorch实现的计算机视觉模型库,通过timm可以轻松的搭建出各种sota模型(目前内置预训练模型592个,包含resnet系列、efficientnet系列、densenet系列、vit系列、vgg系列、inception系列、mobilenet系列、xcit系列等等),并进行迁移学习。预训练模型是指在特定的大型数据集(如ImageNet)上预先训练好的神经网络模型。
EfficientNet是一种高效的卷积神经网络(CNN)架构,它通过一种新颖的网络缩放方法来提升模型的性能和效率。EfficientNet 的核心是其 compound scaling 方法,该方法通过一个复合系数统一缩放网络的深度、宽度和分辨率。efficientnet_b0作为efficientnet系列的基线模型,参数规模最小。
这里使用的是timm库中的efficientnet_b0模型,训练图像head3000张、训练轮数epoch=2、batch_size=70、发现他在该问题上具有较好的性能和鲁棒性,最终分数为0.801,缺点是训练耗时过长。
import timm
model = timm.create_model('efficientnet_b0', pretrained=True, num_classes=2)
model = model.cuda()
图像数据增强
数据增强,是一种在机器学习和深度学习中提升模型性能的重要技术,其主要目的是增加数据的多样性,从而提高模型的泛化能力,常见的数据增强方法有几何变换、颜色变换、自动增强等。其中,几何变换操作有大小调整、随机裁剪、随机翻转、仿射变换、投射变换等。
在本案例的训练集中采用了大小调整、随机翻转、转化为张量、归一化等方法,使在增加数据多样性的同时,也考虑到模型稳定性和收敛速度。此外,对于验证集,应避免引入不必要噪音的增强方法。所以,验证集只需要进行必要的预处理,如调整大小和归一化,避免使用如随机翻转等操作。
#训练集--数据增强,主要目的是增加数据的多样性
train_loader = torch.utils.data.DataLoader(
# FFDIDataset(train_label['path'], train_label['target'],
FFDIDataset(val_label['path'].head(3000), val_label['target'].head(3000), #选取前3000的图片进行训练
transforms.Compose([
transforms.Resize((256, 256)),#图像大小调整为256*256
transforms.RandomHorizontalFlip(),#随机水平翻转图像
transforms.RandomVerticalFlip(),#随机垂直翻转图像
transforms.ColorJitter(brightness=.5, hue=.3),
transforms.ToTensor(),#将图像转换成tensor类型
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])#图像归一化处理
])
), batch_size=70, shuffle=True, num_workers=4, pin_memory=True
)
#验证集--数据增强,原理同上。但验证集要避免噪声干扰,所以只需要调整大小和归一化即可
val_loader = torch.utils.data.DataLoader(
FFDIDataset(val_label['path'].head(3000), val_label['target'].head(3000), #选取前3000的图片进行训练
transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
), batch_size=70, shuffle=False, num_workers=4, pin_memory=True
)
criterion = nn.CrossEntropyLoss().cuda()
optimizer = torch.optim.Adam(model.parameters(), 0.007)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=4, gamma=0.85)
best_acc = 0.0
for epoch in range(2):
scheduler.step()
print('Epoch: ', epoch)
train(train_loader, model, criterion, optimizer, epoch)
val_acc = validate(val_loader, model, criterion)
#性能评估,选出最好的pt参数文件保存
if val_acc.avg.item() > best_acc:
best_acc = round(val_acc.avg.item(), 2)
torch.save(model.state_dict(), f'./model_{best_acc}.pt')
模型训练与验证
该部分为当模型调用train、validate、predict函数时,对应的具体操作内容。
#设置成训练模式
def train(train_loader, model, criterion, optimizer, epoch):
batch_time = AverageMeter('Time', ':6.3f')
losses = AverageMeter('Loss', ':.4e')
top1 = AverageMeter('Acc@1', ':6.2f')
progress = ProgressMeter(len(train_loader), batch_time, losses, top1)
model.train()
end = time.time()
for i, (input, target) in enumerate(train_loader):
input = input.cuda(non_blocking=True)
target = target.cuda(non_blocking=True)
#前向传播
output = model(input)
#计算和更新损失
loss = criterion(output, target)
losses.update(loss.item(), input.size(0))
#计算准确度
acc = (output.argmax(1).view(-1) == target.float().view(-1)).float().mean() * 100
top1.update(acc, input.size(0))
#梯度归零,也就是清空之前的梯度
optimizer.zero_grad()
#反向传播
loss.backward()
#参数更新
optimizer.step()
#计算消耗时间
batch_time.update(time.time() - end)
end = time.time()
if i % 100 == 0:
progress.pr2int(i)
#设置成验证模式
def validate(val_loader, model, criterion):
batch_time = AverageMeter('Time', ':6.3f')
losses = AverageMeter('Loss', ':.4e')
top1 = AverageMeter('Acc@1', ':6.2f')
progress = ProgressMeter(len(val_loader), batch_time, losses, top1)
model.eval()
with torch.no_grad():
end = time.time()
for i, (input, target) in tqdm_notebook(enumerate(val_loader), total=len(val_loader)):
input = input.cuda()
target = target.cuda()
#计算输出
output = model(input)
loss = criterion(output, target)
#计算准确率和损失函数
acc = (output.argmax(1).view(-1) == target.float().view(-1)).float().mean() * 100
losses.update(loss.item(), input.size(0))
top1.update(acc, input.size(0))
#计算消耗时间
batch_time.update(time.time() - end)
end = time.time()
# TODO: 这也应该用ProgressMeter来完成
print(' * Acc@1 {top1.avg:.3f}'
.format(top1=top1))
return top1
# 转换到评估模式
def predict(test_loader, model, tta=10):
model.eval()
test_pred_tta = None
for _ in range(tta):
test_pred = []
with torch.no_grad():
end = time.time()
for i, (input, target) in tqdm_notebook(enumerate(test_loader), total=len(test_loader)):
input = input.cuda()
target = target.cuda()
#计算输出
output = model(input)
output = F.softmax(output, dim=1)
output = output.data.cpu().numpy()
test_pred.append(output)
test_pred = np.vstack(test_pred)
if test_pred_tta is None:
test_pred_tta = test_pred
else:
test_pred_tta += test_pred
return test_pred_tta
模型预测
#预测集--数据增强(调整大小、转换成张量、归一化)
test_loader = torch.utils.data.DataLoader(
FFDIDataset(val_label['path'], val_label['target'],
transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
), batch_size=40, shuffle=False, num_workers=4, pin_memory=True
)
#图像预测并将结果写入csv文件
val_label['y_pred'] = predict(test_loader, model, 1)[:, 1]
val_label[['img_name', 'y_pred']].to_csv('submit.csv', index=None)
三、总结思考
Deepfake作为快速发展的新兴领域,如何快速的识别图像是否为deepfake是新型问题,也是重难点。如何提高模型的精度,主要可以从选择合适的神经网络模型和数据增强两方面入手,前者又可以通过调整模型参数、改进网络结构等方法,后者考虑几何变换、颜色变换、自动增强等方法。
总之,让我们意识到持续学习和社区交流至关重要,参加此次AI夏令营是一次技术挑战与知识拓展的旅程。它不仅可以带领我们去了解深度学习的核心概念和技术,还可以激发我们的创新思维和动手能力,有利于我们去应对当下不断演进的deepfake技术,在这个充满变数的时代去保护更多人的安全与切身利益。
参考链接
https://blog.csdn.net/a486259/article/details/123525448
timm——pytorch下的迁移学习模型库·详细使用教程-CSDN博客
标签:target,val,AI,Datawhale2024,label,time,input,model,CV From: https://blog.csdn.net/Yixuanxia/article/details/140391295