本周概述

本周是项目开发的第二周,主要完成了从数据集下载到 API 实现的完整开发流程。成功将数据集从 Celeb-DF-v2 切换到 WildDeepfake,并完成了所有相关代码的适配工作。训练脚本和 RESTful API 已经准备就绪,下周即可开始第一轮模型训练。


本周完成工作

1. WildDeepfake 数据集下载与适配

1.1 数据集选择与下载

经过团队讨论,决定使用 WildDeepfake 数据集替代 Celeb-DF-v2,主要原因:Celeb-DF-v2数据集来源境外科学团队,申请周期长,可能会拖延项目进度,另外wilddeepfake来源复旦大学科研团队,获取渠道遍历,并且利于训练。

数据集信息

  • 总人脸序列:7,314 个
  • 来源视频:707 个 DeepFake 视频
  • 数据集划分:train(训练集)、valid(验证集)、test(测试集)

如图是在https://www.kaggle.com/网站上下载的视频帧数据集
在这里插入图片描述

1.2 数据集目录结构
data/
├── train/
│   ├── real/              # 真实人脸帧
│   │   ├── 0/            # 人脸序列 0
│   │   │   ├── 0.jpg     # 第 0 帧
│   │   │   ├── 1.jpg     # 第 1 帧
│   │   │   └── ...
│   │   ├── 1/            # 人脸序列 1
│   │   └── ...
│   └── fake/              # 伪造人脸帧
│       ├── 0/
│       └── ...
├── valid/
│   ├── real/
│   └── fake/
└── test/
    ├── real/
    └── fake/
1.3 数据加载器适配

主要修改 utils/data_loader.py 中的load方法以适配 WildDeepfake 的数据结构:

    def _load_dataset(self):
        """加载数据集路径和标签"""
        split_name = self.split if self.split != 'val' else 'valid'
        split_dir = os.path.join(self.data_dir, split_name)
        
        for label in ['real', 'fake']:
            label_dir = os.path.join(split_dir, label)
            if not os.path.exists(label_dir):
                continue
            
            for sequence_dir in Path(label_dir).iterdir():
                if not sequence_dir.is_dir():
                    continue
                
                for image_file in sequence_dir.glob("*.jpg"):
                    self.image_paths.append(str(image_file))
                    self.labels.append(1 if label == 'fake' else 0)
        

2. 训练脚本完善与配置优化

2.1 训练器核心实现

完整的训练器类,包含训练、验证、模型保存等功能:

class Trainer:
    """训练器主要实现方法"""
    def __init__(self, model, train_loader, val_loader, criterion, 
                 optimizer, scheduler, device, save_dir)
    def train_epoch(self):
        """训练一个 epoch"""
    def validate_epoch(self):
        """验证一个 epoch"""
    def train(self, num_epochs=50):
        """训练模型"""
2.2 训练配置参数

通过命令行参数灵活配置训练过程,设置合理的参数配置:

def main():
    # 设置设备
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    print(f'使用设备:{device}')+
    # 获取数据加载器(适配 WildDeepfake)
    train_loader, val_loader, test_loader = get_dataloaders(
        args.data_dir, 
        batch_size=args.batch_size, 
        num_workers=args.num_workers
    )
    
    # 创建模型
    model = xception(num_classes=2, pretrained=args.pretrained)
    
    # 定义损失函数和优化器
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=1e-5)
    scheduler = lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
    
    # 创建训练器
    trainer = Trainer(
        model=model,
        train_loader=train_loader,
        val_loader=val_loader,
        criterion=criterion,
        optimizer=optimizer,
        scheduler=scheduler,
        device=device,
        save_dir=args.save_dir
    )
    
    # 开始训练
    best_acc = trainer.train(num_epochs=args.num_epochs)

3. RESTful API 设计与实现

3.1 API 架构设计

采用 RESTful 风格设计,提供统一的接口规范:

┌─────────────────────────────────────────┐
│          客户端(后端/大模型)            │
└───────────────────┬─────────────────────┘
                    │ HTTP/JSON
                    ▼
┌─────────────────────────────────────────┐
│           Flask API 服务                  │
│  - /api/health          (健康检查)       │
│  - /api/detect/image    (图片检测)       │
│  - /api/detect/video    (视频检测)       │
│  - /api/detect/text     (文本检测)       │
└───────────────────┬─────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────┐
│        XceptionNet 检测模型              │
│  - 模型推理                              │
│  - 结果聚合                              │
└─────────────────────────────────────────┘
3.2 健康检查接口
@app.route('/api/health', methods=['GET'])
def health_check():
    """健康检查"""
    return jsonify({
        'status': 'healthy',
        'device': str(DEVICE),
        'model_loaded': True
    })
3.3 图片检测接口

核心功能:接收图片,返回伪造概率和人脸位置。

@app.route('/api/detect/image', methods=['POST'])
def detect_image():
    检测图片是否换脸

本周遇到的难点以及解决方案

难点 1:WildDeepfake 数据结构适配

问题:WildDeepfake 使用嵌套的文件夹结构(train/real/序列号/图片.jpg),与 Celeb-DF-v2 不同。

主要的解决方案

# 修改数据加载逻辑
for sequence_dir in Path(label_dir).iterdir():
    if not sequence_dir.is_dir():
        continue
    
    for image_file in sequence_dir.glob("*.jpg"):
        self.image_paths.append(str(image_file))
        self.labels.append(1 if label == 'fake' else 0)

难点 2:API 接口的错误处理

问题:需要处理文件不存在、人脸检测失败等各种异常情况。

解决方案

# 错误处理
try:
    # 业务逻辑
    faces, locations = detect_faces_in_image(temp_path)
    
    if len(faces) == 0:
        return jsonify({
            'success': False,
            'error': '未检测到人脸'
        }), 400
    
    # ...
finally:
    # 清理临时文件
    if os.path.exists(temp_path):
        os.remove(temp_path)

学习心得

本周刚开始去下载 Celeb-DF-v2遇到很多问题,最后经过调研决定更改数据集的选择,当然团队任务也会有一定变更,最开始是将视频处理模块集成在了我的模型端(上周博客也有提到),但是其实每次将视频数据从后端传过来是需要一定时间的,那如果我们传过来的只是视频帧则会对系统性能有较高的提升,毕竟视频帧远比视频体积小的多,所以处理视频的模块交给了后端同学去制作,而专用模型模块则仅负责处理视频帧,实现了模块功能的解耦,而且对于整体的系统响应有一定程度的提升。

下周预计完成任务

开始第一轮训练并且进行相关调用的测试

训练目标

  • 验证集准确率 ≥80%
  • 测试集准确率 ≥75%

监控指标

  • 训练损失曲线
  • 验证准确率曲线
  • 学习率变化

预期时间:2-4 小时(GPU)


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐