Task2:从baseline入门深度学习#AI夏令营 #Datawhale #夏令营

实现一个基于深度学习的Deepfake检测模型

在官方的Task2的学习中,提供了很详细的入门深度学习的教程,链接在这‍​​‬⁠​⁠‌​​​‌​​​​⁠​​⁠​‍​​​‬​​​​​​​​‍​​​‍‌‌​‍Task2:从baseline入门深度学习 - 飞书云文档 (feishu.cn)

可以点击进行学习,下面是是我做的实验,也算是对Task1中提到的直接使用视频进行实验的一个补充吧。可以扩展思路!!!

在本文中,将探讨如何使用深度学习技术来开发一个用于检测Deepfake的模型。我将从头开始介绍每个步骤,帮助你了解如何处理数据、构建模型、训练模型以及评估其性能。

1. 数据集准备

首先,需要准备一个包含Deepfake视频和对应标签的数据集。每个视频样本都有一个标签,指示其是否是Deepfake。将使用Python和几个关键的库来处理视频和标签数据。(个人觉得对于深度学习来说,特别是新手,手写Dataset是很有帮助的,在今后的学习中也更加的重要)

import os
import pandas as pd

# 定义一个自定义的数据集类
class DeepfakeDataset(Dataset):
    def __init__(self, csv_file, root_dir, transform=None):
        """
        初始化数据集类
        
        Parameters:
        - csv_file (str): 包含视频文件名和标签的CSV文件路径
        - root_dir (str): 视频文件的根目录
        - transform (callable, optional): 可选的数据变换操作
        """
        self.labels = pd.read_csv(csv_file)  # 从CSV文件中读取标签数据
        self.root_dir = root_dir  # 视频文件的根目录
        self.transform = transform  # 数据变换操作,用于图像预处理等

    def __len__(self):
        """
        返回数据集的样本数量
        """
        return len(self.labels)

    def __getitem__(self, idx):
        """
        根据索引获取单个样本的视频帧和标签
        
        Parameters:
        - idx (int): 样本的索引
        
        Returns:
        - frames (Tensor): 视频帧的张量数据,形状为 (3, 16, 112, 112)
        - label (int): 样本的标签,1表示Deepfake,0表示非Deepfake
        """
        video_name = self.labels.iloc[idx, 0]  # 获取视频文件名
        label = self.labels.iloc[idx, 1]  # 获取标签(1表示Deepfake,0表示非Deepfake)
        video_path = os.path.join(self.root_dir, video_name)  # 构建完整的视频文件路径

        # 调试信息:打印正在读取的视频路径
        print(f"Reading video: {video_path}")

        # 使用OpenCV读取视频文件
        cap = cv2.VideoCapture(video_path)
        if not cap.isOpened():
            print(f"Failed to read video: {video_path}")
            # 返回一个空的tensor和标签,以避免程序崩溃
            return torch.zeros((3, 16, 112, 112)), label

        frames = []
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取视频总帧数
        frame_interval = max(1, total_frames // 16)  # 计算帧采样间隔,以便从视频中提取16帧

        # 逐帧读取视频,并应用数据变换(如果有)
        for i in range(0, total_frames, frame_interval):
            cap.set(cv2.CAP_PROP_POS_FRAMES, i)
            ret, frame = cap.read()
            if not ret:
                break
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # 转换成RGB格式
            if self.transform:
                frame = self.transform(frame)  # 应用数据变换
            frames.append(frame)
            if len(frames) == 16:  # 收集到16帧后停止
                break

        cap.release()  # 释放视频捕获资源

        # 如果收集到的帧数少于16帧,则进行复制填充
        if len(frames) < 16:
            for _ in range(16 - len(frames)):
                frames.append(frames[-1])

        # 将帧列表堆叠成一个4D张量,形状为(16, 3, 112, 112)
        frames = torch.stack(frames)
        # 调整张量的维度顺序,以适应C3D模型的输入要求,形状变为(3, 16, 112, 112)
        frames = frames.permute(1, 0, 2, 3)

        return frames, label  # 返回视频帧张量和标签

在这个部分,通过一个自定义的DeepfakeDataset类来处理数据集。它可以从CSV文件中读取视频文件名和标签信息,并根据需要对视频帧进行预处理。例如,可以在这里应用图像变换,如大小调整、标准化等操作,以便将数据准备好用于模型训练。

2. 深度学习模型选择与构建

为了检测Deepfake,选择了C3D模型,当然你可以选择其他模型。这是一种经典的3D卷积神经网络,特别适用于处理视频数据。你可以像搭积木一样搭建它。

import torch
import torch.nn as nn

# 定义C3D模型
class C3D(nn.Module):
    def __init__(self, num_classes=2):
        super(C3D, self).__init__()
        # 定义特征提取层
        self.features = nn.Sequential(
            nn.Conv3d(3, 64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool3d(kernel_size=(1, 2, 2), stride=(1, 2, 2)),
            nn.Conv3d(64, 128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)),
            nn.Conv3d(128, 256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv3d(256, 256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)),
            nn.Conv3d(256, 512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv3d(512, 512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)),
            nn.Conv3d(512, 512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv3d(512, 512, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))
        )
        # 定义分类器层
        self.classifier = nn.Sequential(
            nn.Linear(512 * 2 * 7 * 7, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, num_classes)
        )

    def forward(self, x):
        x = self.features(x)  # 特征提取
        x = x.view(x.size(0), -1)  # 展平特征图
        x = self.classifier(x)  # 分类
        return x
3. 模型训练与性能评估

现在,将介绍如何训练Deepfake检测模型,并在每个epoch后评估模型在验证集上的性能。将使用BCEWithLogitsLoss作为损失函数,Adam优化器进行参数优化,并使用相应的评估指标。

import torch.optim as optim
from sklearn.metrics import roc_auc_score
import pandas as pd

# 设置训练参数和数据加载器
train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=4, shuffle=False)

# 初始化模型、损失函数和优化器
model = C3D(num_classes=1)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
criterion = nn.BCEWithLogitsLoss()  # 二分类问题使用BCEWithLogitsLoss
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练模型
num_epochs = 10
best_auc = 0.0
for epoch in range(num_epochs):
    model.train()  # 设置模型为训练模式
    running_loss = 0.0
    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device).float().unsqueeze(1)

        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()

    print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {running_loss / len(train_loader):.4f}')

    # 在验证集上评估模型性能
    model.eval()  # 设置模型为评估模式
    all_labels = []
    all_outputs = []

    with torch.no_grad():
        for inputs, labels in val_loader:
            inputs, labels = inputs.to(device), labels.to(device).float().unsqueeze(1)
            outputs = model(inputs)
            all_labels.extend(labels.cpu().numpy())
            all_outputs.extend(torch.sigmoid(outputs).cpu().numpy())

    # 评估模型性能
    auc = roc_auc_score(all_labels, all_outputs)
    print(f'Validation AUC: {auc:.4f}')

    # 保存最佳模型
    if auc > best_auc:
        best_auc = auc
        torch.save(model.state_dict(), 'best_model.pth')

# 保存预测结果到 CSV 文件
predictions = pd.DataFrame({'video_name': val_dataset.labels.iloc[:, 0], 'score': all_outputs})
predictions.to_csv('prediction.csv', index=False)

print("Prediction results saved to 'prediction.csv'.")

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值