复现 SSL_Anti-spoofing, 使用 wav2vec 2.0 和数据增强的自动说话人认证的欺骗攻击与深度伪造检测

前言

因为 CSDN 一个字母是一个字,标题限制 100 字所以没法把论文题目 COPY 进去了。

[1] H. Tak, M. Todisco, X. Wang, J. Jung, J. Yamagishi, and N. Evans, “Automatic speaker verification spoofing and deepfake detection using wav2vec 2.0 and data augmentation.” arXiv, Feb. 28, 2022. Accessed: Jul. 01, 2022. [Online]. Available: http://arxiv.org/abs/2202.12233

Tak Hemlata 的新工作,该作者之前的工作包括 21 年 ASVspoof 的 baseline RawNet2 (发表在 ICASSP 21)。这篇工作后来发表到 Odyssey 22。GitHub repo 链接如下。

GitHub - TakHemlata/SSL_Anti-spoofing: This repository includes the code to reproduce our paper "Automatic speaker verification spoofing and deepfake detection using wav2vec 2.0 and data augmentation".This repository includes the code to reproduce our paper "Automatic speaker verification spoofing and deepfake detection using wav2vec 2.0 and data augmentation". - GitHub - TakHemlata/SSL_Anti-spoofing: This repository includes the code to reproduce our paper "Automatic speaker verification spoofing and deepfake detection using wav2vec 2.0 and data augmentation".https://github.com/TakHemlata/SSL_Anti-spoofing 说明非常详细,和之前 RawNet2 的工作在代码风格上也很接近,下面对复现过程简单记录。

正文

首先是 Installation,我这里就没有创建新的虚拟环境了,比较慢,直接用之前的开发环境,也不需要安装太多,我这里只缺一个 fairseq。fairseq 的安装具体可以参照官方的做法,下面直接引用官方 README。可以看到这个 repo 里已经包含了需要版本的 fairseq,按照下面流程来就安装完了。(SSL_Anti-spoofing/README.md at main · TakHemlata/SSL_Anti-spoofing · GitHub)

$ git clone https://github.com/TakHemlata/SSL_Anti-spoofing.git
$ conda create -n SSL_Spoofing python=3.7
$ conda activate SSL_Spoofing
$ pip install torch==1.8.1+cu111 torchvision==0.9.1+cu111 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
$ cd fairseq-a54021305d6b3c4c5959ac9395135f63202db8f1
(This fairseq folder can also be downloaded from https://github.com/pytorch/fairseq/tree/a54021305d6b3c4c5959ac9395135f63202db8f1)
$ pip install --editable ./
$ pip install -r requirements.txt

然后是下载预训练模型,官方用了 fairseq 的预训练模型 wav2vec 2.0 XLS-R (0.3B),0.3B 就是 300M。此外还有作者自己的模型,都可以参考 GitHub 的链接获得最新的下载地址。https://github.com/TakHemlata/SSL_Anti-spoofing#pre-trained-wav2vec-20-xlsr-300m

简单插一嘴,wav2vec 2.0 XLS-R(300M) 模型大小 3.54GB,作者的模型 1.18 GB,也就是说这篇论文的模型就要 4.72 GB……相比之前的 RawNet 可能也就是几十MB 的量级大了不少,作者在论文中承认模型大小和损耗是个问题但是没有明确点明大小。

wav2vec 2.0 预训练模型路径报错

下面执行命令在 21 LA 数据集上测试预训练模型。

CUDA_VISIBLE_DEVICES=2 python main_SSL_LA.py --track=LA --is_eval --eval --model_path="/root/project/pretrained_models/Tak_SSL_LA_model.pth" --eval_output='eval_pre_trained_model_CM_scores_file_SSL_LA_0721.txt'

意料之中的报错。

Device: cuda
Traceback (most recent call last):
  File "main_SSL_LA.py", line 240, in
    model = Model(args,device)
  File "/root/project/SSL_Anti-spoofing-main/model.py", line 446, in __init__
    self.ssl_model = SSLModel(self.device)
  File "/root/project/SSL_Anti-spoofing-main/model.py", line 25, in __init__
    model, cfg, task = fairseq.checkpoint_utils.load_model_ensemble_and_task([cp_path])
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/fairseq/checkpoint_utils.py", line 423, in load_model_ensemble_and_task
    raise IOError("Model file not found: {}".format(filename))
OSError: Model file not found: /medias/speech/projects/tak/our_staging/LA/Baseline-RawNet2/pre-trained_model_SSL/models/XLR_300M/xlsr2_300m.pt

似乎是作者把 wav2vec 预训练模型的路径写死了……去找一下代码改一下吧。

在 model.py 文件中可以看到路径被写死了,这里需要改为自己下载的路径。

复现 SSL_Anti-spoofing, 使用 wav2vec 2.0 和数据增强的自动说话人认证的欺骗攻击与深度伪造检测_第1张图片

Fairseq 版本不一致报错(直接 pip 安装会报错)

继续报错,下一个错似乎比较麻烦。

Device: cuda
Traceback (most recent call last):
  File "main_SSL_LA.py", line 240, in
    model = Model(args,device)
  File "/root/project/SSL_Anti-spoofing-main/model.py", line 446, in __init__
    self.ssl_model = SSLModel(self.device)
  File "/root/project/SSL_Anti-spoofing-main/model.py", line 25, in __init__
    model, cfg, task = fairseq.checkpoint_utils.load_model_ensemble_and_task([cp_path])
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/fairseq/checkpoint_utils.py", line 436, in load_model_ensemble_and_task
    task = tasks.setup_task(cfg.task)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/fairseq/tasks/__init__.py", line 39, in setup_task
    cfg = merge_with_parent(dc(), cfg)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/fairseq/dataclass/utils.py", line 500, in merge_with_parent
    merged_cfg = OmegaConf.merge(dc, cfg)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/omegaconf.py", line 321, in merge
    target.merge_with(*others[1:])
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/basecontainer.py", line 331, in merge_with
    self._format_and_raise(key=None, value=None, cause=e)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/base.py", line 95, in _format_and_raise
    format_and_raise(
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/_utils.py", line 629, in format_and_raise
    _raise(ex, cause)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/_utils.py", line 610, in _raise
    raise ex  # set end OC_CAUSE=1 for full backtrace
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/basecontainer.py", line 329, in merge_with
    self._merge_with(*others)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/basecontainer.py", line 347, in _merge_with
    BaseContainer._map_merge(self, other)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/basecontainer.py", line 314, in _map_merge
    dest[key] = src._get_node(key)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/dictconfig.py", line 258, in __setitem__
    self._format_and_raise(
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/base.py", line 95, in _format_and_raise
    format_and_raise(
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/_utils.py", line 629, in format_and_raise
    _raise(ex, cause)
  File "/root/miniconda3/envs/espnet/lib/python3.8/site-packages/omegaconf/_utils.py", line 610, in _raise
    raise ex  # set end OC_CAUSE=1 for full backtrace
omegaconf.errors.ConfigKeyError: Key 'multiple_train_files' not in 'AudioPretrainingConfig'
        full_key: multiple_train_files
        reference_type=Optional[AudioPretrainingConfig]
        object_type=AudioPretrainingConfig

简单上网搜了一下,似乎不是什么简单常见的 bug 啊……报错应该是 omegaconf 这个库在读取配置的时候出的问题。盲猜一波是版本更新的锅,我刚刚安装的是新版 fairseq 。目前的版本是 fairseq.__version__ = '0.12.2' 。 老老实实按照官方的 installation 说明重新安装一下 fairseq。

复现 SSL_Anti-spoofing, 使用 wav2vec 2.0 和数据增强的自动说话人认证的欺骗攻击与深度伪造检测_第2张图片

可以看到版本号都感觉不太一样……重新跑一下 main_SSL_LA.py 。

大模型等报错都得等个十来秒……

未指定数据集路径报错

OK,又报错了,预料之中, Tak 和 RawNet2 一样,虽然实现了功能,但是Readme 给提供的命令是残缺的,需要执行的时候补充上 数据集和 keys 的路径,这里各位根据自己的下载路径修改填写了。这里可以参考我的上一篇复现 RawNet2 的博客,大概就是 Tak 的实现还有一个关于要不要加 /LA/ 的问题,但是懒得再改代码了,传参的时候记得加上 /LA/ 就好。

复现 ASVspoof 2021 baseline RawNet2_Haulyn5的博客-CSDN博客RawNet2 是 ASVspoof 2021 的几种基线方法之一。记录复现过程。复现成功。在 21 LA eval 上得到 9.5%的 EER。官方 repo:2021/LA/Baseline-RawNet2 at main · asvspoof-challenge/2021 · GitHubASVspoof 2021 Baseline Systems.https://blog.csdn.net/Haulyn5/article/details/125446135下面是运行时的命令,注意我这里路径虽然写的是 19 ,但是我把 21 年的数据集放到里面了,各位根据 Tak 的代码和自己的数据集路径配置填写。

CUDA_VISIBLE_DEVICES=2 python main_SSL_LA.py --track=LA --is_eval --eval --model_path="/root/project/pretrained_models/Tak_SSL_LA_model.pth" --eval_output='eval_pre_trained_model_CM_scores_file_SSL_LA_0721.txt' --database_path='/root/project/datasets/ASVspoof2019-LA/LA/' --protocols_path='/root/project/datasets/ASVspoof2019-LA/LA/'

爆显存,修改批大小 batch size

然后可以预想到,光荣爆显存了,家境贫寒 8GB 显卡不配了。

在 main_SSL_LA.py 文件的 44 行出可以看到,评估时的 batch_size 被写固定了,这里手动改一下,图快可以直接改这个数字,或者设置成可以传参。

复现 SSL_Anti-spoofing, 使用 wav2vec 2.0 和数据增强的自动说话人认证的欺骗攻击与深度伪造检测_第3张图片

 给后面的同学一些参考,我这里使用 8GB 的显存,只配开 batch size = 4 。显存占用:7257MiB /  7611MiB 。

这个模型在 21 LA eval 数据集上跑了3个小时52分钟…… Real time 肯定是没问题,但是确实相比之前的模型慢了不少。

评估 EER, min t-DCF

值得注意的是,这里其实不用自己去 ASVspoof 2021 的官网去下 keys,Tak (作者)将 keys 集成到了 GitHub Repo 内部。

# python evaluate_2021_LA.py "eval_pre_trained_model_CM_scores_file_SSL_LA_0721.txt"  ./LA-keys-stage-1/keys  eval
CHECK: submission has 181574 of 181566 expected trials.

经典 bug,如果之前没有注意,已经评估过一个 batch 又报错,因为这个代码是 append,不是重写输出文档,所以会导致输出文档有重复条目,主要是开头。查找重复条目删去即可。

复现 SSL_Anti-spoofing, 使用 wav2vec 2.0 和数据增强的自动说话人认证的欺骗攻击与深度伪造检测_第4张图片

 运行成功,以及结果

# python evaluate_2021_LA.py "eval_pre_trained_model_CM_scores_file_SSL_LA_0721.txt"  ./LA-keys-stage-1/keys  eval
min_tDCF: 0.2065
eer: 0.82

0.82 的等错误率是真的佩服了……我半个月就能调出来百分之九点多……

DF track 这里就不校验了,虽然之后肯定还是要跑,但是太费时间了,数据量上大概就是 LA 的 4 倍,根据这个比例大概得跑个 16 小时……

实验环境

实验环境放到最后是因为一开始不确定能不能搞出来hhh,和作者的环境略微不太一致。显卡是 Tesla P4。

Pytorch                        1.10.1
librosa                          0.9.1
numpy                          1.18.5

后记

值得一提的是,模型对于一个样本的输出是 2 维的,所以如果只要一个 score,(我以为是 softmax),然而看了作者的实现,好啊,直接取 batch_out[:, 1],也就是说第一维输出不要了就……(参见 main_SSL_LA.py 文件中的 produce_evaluation_file 函数),而训练的时候作者使用了 CrossEntropyLoss,相关代码如下,并且利用了 bonafide 比 spoof 是 0.1:0.9 的先验。

output = model(sample.unsqueeze(0).to(device))
criterion = nn.CrossEntropyLoss(weight=torch.FloatTensor([0.1, 0.9]).to(device))
criterion(output, torch.Tensor([1]).to(torch.long).to(device))

吐槽:CSDN 的标签甚至没有 语音或者语音信号处理,甚至信号处理都没有,太惨了……还有自监督学习和论文也没有……

你可能感兴趣的:(安全,深度学习)