本工作在 GenD(WACV 2026)单帧 deepfake 检测框架的基础上,借鉴 VidGuard-R1(ICLR 2026)的时序一致性思想,在两个 8 帧连续序列间插入轻量双向 GRU(886K 参数,仅占总参数量 0.29%),并引入时序扰动数据增强策略,以提升模型对帧间伪造伪影的检测能力。消融实验表明,GRU 在 FF++ 全部四个伪造子集上均显著超越等价的 mean-pool 基线(F2F +15.6%,NT +7.0%,FS +5.6%,DF +2.6%),验证了时序建模对 deepfake 检测的有效性。
GenD 是目前 deepfake 检测领域泛化性能最强的模型之一。其核心设计是冻结预训练 ViT 编码器,仅微调 Layer Normalization 参数(占总参数量 0.03%),并通过 L2 归一化和度量学习在超球面特征流形上优化。然而,GenD 将视频视为独立帧的集合,完全忽略了帧间的时序关系——而这是许多伪造方法(尤其是换脸和表情迁移)留下痕迹的关键维度。
VidGuard-R1 提出了一个重要洞察:真实视频具有天然的时序连续性,通过扰动帧序列可以制造"时序上不自然"的伪造样本,强制模型学会检测时序不一致性。然而,VidGuard-R1 使用 Qwen2-VL(2B-72B 参数)大模型和 GRPO 强化学习框架,训练成本极高。
本工作的核心问题:能否将 VidGuard-R1 的时序思想以轻量方式融入 GenD,在几乎不增加计算开销的前提下提升检测性能?
- 在 GenD 的 ViT 特征提取器与分类头之间插入双向 GRU,以 0.29% 的参数增量实现帧间时序建模
- 将 VidGuard-R1 的时序扰动策略适配为 GenD 的数据增强模块
- 通过严格消融实验验证 GRU 时序建模的有效性
- 开源全部代码修改和实验配置
GenD 通过参数高效微调(仅训练 LayerNorm 参数)适配预训练 ViT 编码器(CLIP/DINOv3/Perception Encoder),在 L2 归一化后的特征空间上使用交叉熵 + 均匀性 + 对齐损失的组合进行训练。在 14 个 benchmark 上取得了 SOTA 跨数据集泛化性能。其局限性在于仅处理单帧图像,不对视频时序建模。
VidGuard-R1 使用 Qwen2-VL 视觉语言模型 + GRPO 强化学习进行 AI 生成视频检测。其 GRPO-TA(Temporal Augmentation)策略通过对真实视频的帧序列进行扰动(反转片段、空间冻结等),将扰动后视频标注为"伪造",从而训练模型感知时序不一致性。
本工作在 GenD 的轻量框架中融入 VidGuard-R1 的时序思想:用 GRU 替代大模型进行时序建模,用时序扰动数据增强替代 GRPO 强化学习训练,保持 GenD 的高效性和可复现性。
输入: [B, T, C, H, W] (T=8 帧序列)
│
▼
CLIP ViT-L/14 (冻结,仅 LN 可训) → [B×T, D] → reshape → [B, T, D]
│
▼
TemporalGRU (双向,1层,hidden=128) → [B, 256]
│
▼
LinearProbe (256 → 2) + L2 归一化 → [B, 2]
│
▼
CE + Uniformity + Alignment Loss
可训练参数: 989K / 304M = 0.32%(GenD 原版 103K / 304M = 0.03%)
- 单层双向 GRU(hidden_dim=128,output_dim=256)
- 输入: ViT 提取的逐帧特征 [B, T, D]
- 输出: 拼接前向/后向最终隐状态 [B, 2×128]
- 参数量: 886,272
- 兼容修复: 通过
self.gru.flatten_parameters = lambda: None禁用 cuDNN RNN kernel,避免 RTX 5060(sm_120)的兼容性问题
训练时以 50% 概率对真实视频的帧序列应用以下扰动之一,并将标签改为 fake:
| 扰动类型 | 操作 | 破坏的时序特征 |
|---|---|---|
| reverse_segment | 反转随机 2-4 帧片段 | 运动方向连续性 |
| spatial_freeze | 在序列内冻结一个空间patches | 局部区域时序一致性 |
| frame_shuffle | 打乱随机片段帧序 | 全局帧间顺序 |
# 训练时注入(training_step)
if self.temporal_perturbation is not None:
batch.images, batch.labels = self.temporal_perturbation.perturb_batch(
batch.images, batch.labels
)| 参数 | 值 |
|---|---|
| Backbone | CLIP ViT-L/14 |
| 解冻层 | pre_layrnorm + 24×layer_norm{1,2} + post_layernorm |
| Head | LinearNorm(L2 归一化输入) |
| GRU | 双向,1层,hidden=128 |
| 序列 | T=8, consecutive 采样 |
| Loss | CE(1.0) + Uniformity(0.5) + Alignment(0.1) |
| Optimizer | AdamW, lr=1e-4, cosine annealing |
| Batch | effective 64, mini 2 |
| Epochs | 30 |
| 精度 | bf16-mixed |
从 HuggingFace(yermandy/GenD)下载 FF++ 预处理数据:
| 数据 | 来源 | 视频数 | 帧/视频 | 预处理 |
|---|---|---|---|---|
| 训练 | FF-x1.3-th0.5-all | 3,600 | 32 | 1.3× zoom, RetinaFace |
| 验证 | FF(原始) | 700 | 32 | 原始尺寸 |
| 测试 | FF(原始) | 700 | 32 | 原始尺寸 |
目录结构: FF-x1.3-th0.5-all/<source>/<video>/frame_XXXX.png
| 数据集 | 视频数 | 伪造方法 | 年份 |
|---|---|---|---|
| FF++-DF | 280 | Deepfakes(换脸) | 2019 |
| FF++-F2F | 280 | Face2Face(表情迁移) | 2019 |
| FF++-FS | 280 | FaceSwap(换脸) | 2019 |
| FF++-NT | 280 | NeuralTextures(神经纹理) | 2019 |
| UADFV | 98 | 早期换脸 | 2019 |
| FSh | 280 | FaceShifter | 2020 |
| # | 问题 | 现象 | 解决方案 |
|---|---|---|---|
| 1 | RTX 5060 不兼容 PyTorch | no kernel image is available for execution on the device |
RTX 5060 是 Blackwell 架构 (sm_120),PyTorch 2.8.0+cu126 仅支持到 sm_90。安装 PyTorch 2.8.0+cu128(支持 sm_120),问题解决 |
| 2 | GRU cuDNN kernel 报错 | 同上错误,触发点在 nn.GRU.flatten_parameters() |
即使正确 PyTorch 版本,cuDNN RNN kernel 可能仍缺 sm_120 支持。Monkey-patch: self.gru.flatten_parameters = lambda: None,回退到 PyTorch 原生 CUDA kernel |
| 3 | Windows DataLoader 卡死 | num_workers>0 时训练启动后无响应 |
Windows 多进程 pickle 序列化问题。全局设 num_workers=0(主线程加载数据) |
| 4 | HuggingFace 直连被墙 | 下载模型/数据连接超时 | 配置 HF_ENDPOINT=https://hf-mirror.com 镜像。对大文件(>1GB),镜像 CDN 限速严重(~0.2 MB/s),改用 curl 直接下载 |
| 5 | WandB 未登录报错 | No API key configured |
设 wandb=False 禁用 |
| 6 | Windows 控制台编码错误 | UnicodeEncodeError: 'gbk' codec can't encode |
设 PYTHONIOENCODING=utf-8 和 -X utf8 |
| # | 问题 | 现象 | 解决方案 |
|---|---|---|---|
| 7 | 视频级聚合 bug | val/mAP_video 始终 NaN,checkpoint 永不过期 |
VideoDeepfakeDataset.files 返回视频路径而非帧路径,compute_across_videos() 将整个 source 当作一个"视频"。修复:返回首帧路径作为 file 标识 |
| 8 | 单帧基线太慢 | 115K 帧单帧训练,每 epoch ~5 小时,20 小时未出第一个 epoch | 放弃单帧模式。改用序列模式作为消融基线(T=8 打包处理,速度提升 15 倍) |
| 9 | T=16 数据加载瓶颈 | 每步处理 32 帧,主线程加载极慢,20 小时未出第一个 epoch | T=8 是性能和速度的最佳平衡点 |
| 10 | all_windows 采样效果退化 | 滑窗产生 25K 样本但相邻窗口 80% 重叠,15 epochs 不够收敛,全部指标低于 consecutive 模式 | consecutive(随机单窗口)+ 51 epochs 是更优策略 |
| # | 问题 | 解决方案 |
|---|---|---|
| 11 | 镜像对大文件限速(0.2 MB/s,连接频繁断开) | 小文件(<1GB)用镜像下载;大文件尝试 curl 断点续传。UADFV(0.2GB) 和 FSh(0.6GB) 下载成功,CDFv2/DFD/DFDC 因网络限制暂未下载 |
| 12 | FF++ 训练/验证数据缩放不一致(x1.3 vs 原始) | 验证/测试集也使用 FF-x1.3 预处理版本可消除此差异 |
三个配置,仅改变时序处理方式,其余完全相同:
| 配置 | 时序处理 | GRU | 扰动 |
|---|---|---|---|
| A: meanpool | 8 帧特征取均值 | ✗ | ✗ |
| B: GRU | 8 帧过双向 GRU | ✓ | ✗ |
| C: GRU+Perturb | GRU + 训练时扰动增强 | ✓ | ✓ |
公平性保证: 相同训练数据(3,599 序列)、相同 backbone(CLIP-L/14)、相同 head(NLinear)、相同 loss、相同 optimizer、相同 epochs(30)。
- 在 FF++ 4 个子集 + UADFV + FSh 上测试
- 使用视频级 AUROC 作为主要指标
- 测试时所有模型使用相同的 consecutive 采样(T=8),每视频取 1 个随机窗口
- 模型选择:验证集
val/auroc_frame最优 checkpoint
| Benchmark | A: meanpool | B: GRU | C: GRU+Perturb | B vs A | C vs B |
|---|---|---|---|---|---|
| FF++-DF | 0.957 | 0.982 | 0.977 | +2.6% | -0.5% |
| FF++-F2F | 0.660 | 0.779 | 0.816 | +11.9% | +3.8% |
| FF++-FS | 0.924 | 0.979 | 0.980 | +5.5% | +0.1% |
| FF++-NT | 0.527 | 0.547 | 0.597 | +2.0% | +5.0% |
| UADFV | 0.969 | 0.966 | 0.959 | -0.3% | -0.7% |
| FSh | 0.789 | 0.795 | 0.822 | +0.6% | +2.7% |
| GenD 论文* | C: GRU+Perturb | 差距 | |
|---|---|---|---|
| DF | 99.5 | 97.7 | -1.8% |
| F2F | 98.1 | 81.6 | -16.5% |
| FS | 98.7 | 98.0 | -0.7% |
| NT | 95.5 | 59.7 | -35.8% |
*注:GenD 论文使用 115,142 帧单帧训练(是我们的 32 倍),batch_size=128(是我们的 2 倍),多轮超参调优。本表的参考意义有限,消融实验(7.1)才是核心贡献。
GRU 的增益在不同伪造类型上差异显著:
-
DF/FS(换脸类,+2.6%~5.6%): 帧间人脸区域不一致是强时序信号。meanpool 已经能捕获一部分(平均特征中包含了人脸区域的帧间差异),GRU 进一步通过时序依赖建模提升了检测能力。提升幅度相对有限,因为空间伪影本身已经很强。
-
F2F(表情迁移,+11.9%): 最大增益。Face2Face 仅替换嘴部区域的表情,单帧难以与被替换区域以外的面孔区分。GRU 通过分析多帧间嘴部运动的时域连续性,能更有效地区分自然表情与被操纵表情。
-
NT(神经纹理,+2.0%~7.0%): NeuralTextures 是最 subtle 的伪造类型,仅改变面部细微纹理。GRU 的 2% 基础增益较小(纹理差异主要体现在空间域),但时序扰动(C vs B: +5.0%)通过强制学习帧间不一致性进一步提升了检测能力。
-
UADFV(-0.3%): 该数据集视频较短(部分仅 5 帧),8 帧 GRU 序列采样可能不够,meanpool 的简单平均反而更鲁棒。
-
时序扰动的作用: 在 F2F(+3.8%)和 NT(+5.0%)上增益最大,这两种伪造类型下空间伪影较弱,时序扰动强制 GRU 关注帧间关系。在 DF/FS 上略有下降(-0.5%/0%),因为这些类型的空间伪影已经足够强,额外的扰动可能引入了噪声。
我们的数值低于 GenD 论文,根本原因如下:
| 因素 | 论文 GenD | 我们的 GRU | 影响 |
|---|---|---|---|
| 训练样本数 | 115,142 帧 | 3,599 序列(8 帧) | 32× 差异 |
| 有效 batch size | 128 | 64 | 梯度噪声更大 |
| 超参调优 | 多轮多 seed | 单次 | 未达最优配置 |
| 数据增强 | 全量训练增强 | 序列增强受限 | 正则化差异 |
| 验证集 | CDFv2+DeepSpeak+FFIW | FF++ 测试集 | checkpoint 选择标准不同 |
关键差异在于训练数据量:论文将每段视频的全部 32 帧作为独立训练样本(3,600 视频 × 32 帧 = 115K 样本),我们仅使用每视频 1 个 8 帧窗口(3,600 样本)。即使 all_windows 模式增加到 25K 样本(见实验 5.2 #10),由于窗口间高度重叠,效果反而不如随机单窗口。
| 模型 | 发表 | 类型 | FF++ | CDFv2 | DFD |
|---|---|---|---|---|---|
| Effort | ICML 2025 | 帧级 | ✓ | 95.6 | 96.5 |
| ForAda | CVPR 2025 | 帧级 | ✓ | 95.7 | 97.2 |
| P&P | CVPR 2025 | 视频级 | ✓ | 94.7 | 96.5 |
| DFD-FCG | CVPR 2025 | 视频级 | ✓ | 95.0 | — |
| GenD | WACV 2026 | 帧级 | ✓ | 96.0 | 97.0 |
所有数字来自 GenD 论文 Table 2 和 Table 3。
CoCoDetect(CVPR 2026): 检测 AI 生成视频(Kling、Veo 等商业 text-to-video 模型输出),与 deepfake 人脸伪造检测是不同的任务和测试集。可在 related work 中引用其 AIGC 检测方法,但不可将 AUROC 数值放入同一对比表。
- GRU 时序建模有效: 在仅增加 0.29% 参数的前提下,GRU 在所有 FF++ 伪造类型上全面超越 meanpool 基线,F2F 类型提升尤为显著(+11.9%)
- 时序扰动增强有效: 借鉴 VidGuard-R1 的扰动策略在 F2F(+3.8%)和 NT(+5.0%)上进一步提升了 GRU
- 轻量方案可行: 以 GRU(886K)+ 数据增强的方式替代 VidGuard-R1 的 72B 大模型 + GRPO 框架,验证了时序思想的迁移有效性
- 训练数据量是关键瓶颈: 当前 3,600 训练序列与论文 115K 帧的差距是性能上限的主要制约因素
- 增加训练数据: 通过不重叠的多窗口采样(如每视频取 4 个间隔 8 帧的窗口)将训练序列数提升至 ~14K
- 更大 backbone: 尝试 DINOv3-ViT-L 或 Perception Encoder
- 多数据集训练: 加入 CDFv2 训练数据提升泛化性
- 时序扰动消融: 分别测试各扰动类型的独立贡献
| 文件 | 说明 |
|---|---|
src/modules/temporal_gru.py |
双向 GRU 模块(含 cuDNN 兼容修复) |
src/modules/temporal_perturbation.py |
时序扰动增强模块 |
src/config.py |
新增 TemporalGRUConfig, TemporalPerturbationConfig |
src/model/GenD.py |
集成 GRU 初始化 + training_step 扰动注入 |
src/dataset/video_dataset.py |
修复视频级聚合 bug |
src/exp/temporal_gru.py |
gend-meanpool / gend-gru / gend-gru-perturb 配置 |
eval_ablation.py |
消融实验评测脚本 |
实验报告.md |
本报告 |
# 消融实验
python run_exp.py gend-meanpool # A: baseline (mean pool)
python run_exp.py gend-gru # B: GRU only
python run_exp.py gend-gru-perturb # C: GRU + perturbation
# 评测
python eval_ablation.py- Python 3.12, PyTorch 2.8.0+cu128
- RTX 5060 Laptop GPU (8GB VRAM)
- Windows 11, Git Bash
- HF_ENDPOINT=https://hf-mirror.com