山大软院创新项目实训个人博客——诈骗克星(四)
1.本次进展
本次围绕音频检测模块,我重点做了三件事:
1)将训练环境从 CPU 迁移到可支持 GPU 的 Python 环境路径,加速训练
2)对音频训练脚本进行优化,新增参数
3)增加阈值扫描工具,对 spoof_prob 的判定阈值进行系统化优化
2.训练环境迁移问题与处理
2.1 现象
此前检测结果为:
python -c "import torch; print('torch=', torch.__version__); print('cuda=', torch.cuda.is_available()); print('count=', torch.cuda.device_count()); print('name=', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'N/A')"
torch=2.9.0+cpu
cuda=False
count=0
说明训练仍运行在 CPU 环境,速度较慢。
2.2 原因分析
核心原因是 Python 版本(3.13)与包源组合不匹配,导致安装到的不是可用的 CUDA 训练组合。
同时,transformers 与 torch 版本也出现兼容约束(涉及 torch.load 安全限制)。
2.3 处理结论
统一改用 py -3.11 指定解释器进行安装与训练,避免系统中多个 Python 环境混用。
并通过版本对齐使 torch + transformers 可以正常加载模型并训练。
2.4训练影响
训练环境迁移至GPU后,训练速度大幅提升,时间从原本训练1epoch大约1小时左右缩短到10分钟
以内,训练结果并无过多波动。
3. 训练脚本优化更新(train_wav2vec2.py)
在原脚本基础上继续做了提速与可控性增强,新增参数主要包括:
num_workers:并行读取数据(DataLoader 多进程读数据,提速明显)
eval_strategy:评估频率策略,告诉Trainer每多少步在验证集上跑一次评估(多少步、每轮)
save_strategy:checkpoint 保存策略,何时保存checkpoint
logging_steps:日志输出频率
fp16:混合精度训练(GPU),把部分计算从 FP32 切到 FP16(半精度),通过 AMP 自动混合精度来保持稳定性,可以显著提速和降低显存占用,允许更大的batchsize。
同时保留并强化此前优化:
use_class_weight:类别不平衡加权损失
weight_decay、--warmup_ratio:训练稳定性
decision_threshold:分类阈值可配置
metric_for_best_model:最佳模型选择标准
4. 阈值扫描:为什么做、怎么做
4.1 为什么要做阈值扫描
模型输出的是 spoof_prob 概率,最终分类依赖阈值 t:
若spoof_prob >= t 判 spoof(伪造),否则判 bonafide(真实)
不同阈值会直接改变误报/漏检权衡:
阈值降低:spoof 召回上升、误报可能增加
阈值升高:误报下降、漏检可能增加
反诈场景中,通常更关注降低漏检 spoof(cm_fn)
4.2 新增脚本:threshold_scan.py
我新增了阈值扫描脚本,支持:
从批量推理 CSV 读取 spoof_prob 与 true_label
一次扫描多个阈值(如0.35、0.4、0.45、0.5等)
输出每个阈值下的完整指标,便于不同阈值下进行对比
自动给出最优阈值(按 f1_spoof / recall_spoof / accuracy)
4.3示例代码
主流程:遍历阈值、选最优、导出CSV:
rows = load_rows(input_csv)
if not rows:
raise ValueError("CSV 中没有可用于评估的数据。请确认包含 true_label/status/spoof_prob。")
thresholds = parse_thresholds(args.thresholds)
results = [metrics_at_threshold(rows, t) for t in thresholds]
best = max(results, key=lambda x: x[args.optimize_for])
output_csv = Path(args.output_csv)
output_csv.parent.mkdir(parents=True, exist_ok=True)
fieldnames = list(results[0].keys())
with output_csv.open("w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(results)
4.4 执行流程
先生成带真值标签的批量推理结果:
python infer_audio_batch.py --model_dir outputs/wav2vec2-mid1/best --audio_dir data/ASVspoof2019_LA_dev/flac --glob "*.flac" --protocol_path data/ASVspoof2019_LA_cm_protocols/ASVspoof2019.LA.cm.dev.trl.txt --output_csv outputs/dev_batch_results.csv
再扫描多个阈值:
python threshold_scan.py --input_csv outputs/dev_batch_results.csv --thresholds "0.35,0.4,0.45,0.5,0.55,0.6" --optimize_for f1_spoof --output_csv outputs/threshold_scan_results.csv
最后观察不同阈值下指标对比以及选出所选中的最优阈值。
5.下一步计划
将选定阈值固化到 app.py 服务配置,并于小组成员目前成果进行结合,完成项目初版功能程序
更多推荐



所有评论(0)