物理世界的鲁棒语音对抗样本(源码阅读笔记)上

在看源码的时候感觉到些许吃力,写这篇博客是为了push自己坚持看完代码,该代码为IJCAI19发表的Robust Audio Adversarial Example for a Physical Attack的源代码,版权归作者所有。

首先是导入相关库和函数,用了import和from import语句

from __future__ import print_function

import argparse
import math
import os
import random
import shutil
import string
import struct
import sys
import tempfile
import time

import numpy as np
import tensorflow as tf
import scipy.io.wavfile as wav

如果后续有需要,会详细介绍这几个库

sys.path.append是增加库搜索目录的一种方式,在import模块时python会查找已安装的模块,但是如果模块不在默认的文件夹里该如何找到并import呢?sys.path.append就是解决这个问题,其参数为要添加的路径,这里作用是将DeepSpeech文件夹的文件路径导入环境变量。

sys.path.append(os.path.join(os.path.dirname(__file__), 'DeepSpeech'))

作者注释说是为了避免tf崩溃,所以禁用某些功能。
这里有个技巧就是monkey-patching,即重写某些函数,在不更改库的源代码的情况下实现自己的个性化需求。
官方点的说法,猴子补丁主要有以下几个用处:
在运行时替换方法、属性等
在不修改第三方代码的情况下增加原来不支持的功能
在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加

tf.load_op_library = lambda x: x
tmp = os.path.exists
os.path.exists = lambda x: True
class Wrapper:
    def __init__(self, d):
        self.d = d
    def __getattr__(self, x):
        return self.d[x]
class HereBeDragons:
    d = {}
    FLAGS = Wrapper(d)
    def __getattr__(self, x):
        return self.do_define
    def do_define(self, k, v, *x):
        self.d[k] = v
tf.app.flags = HereBeDragons()
os.path.exists = tmp

还是猴子补丁,禁用训练协调器

DeepSpeech.TrainingCoordinator.__init__ = lambda x: None
DeepSpeech.TrainingCoordinator.start = lambda x: None

from util.text import ctc_label_dense_to_sparse
from tf_logits import get_logits
from weight_decay_optimizers import AdamWOptimizer

定义允许使用的tokens。
其中,“-”是特殊的,与CTC解码中的epsilon值(相当于空格或空字符)相对应,并且不能在短语中出现。

toks = " abcdefghijklmnopqrstuvwxyz'-"

全局变量:输入文件的采样率,主要是为了代码的重用

Fs = 16000

main函数

使用argparse库实现参数的输入,argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义它需要的参数,然后 argparse 将弄清如何从 sys.argv 解析出那些参数。 argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。

使用 argparse 的第一步是创建一个 ArgumentParser 对象。
然后通过add_argument可以增加一个程序参数信息,以下面第一个add_argument语句为例:–in为关键字,类型为str,输入给变量input,是必需参数,帮助信息为Input audio .wav file at 16000 Hz

def main():
    parser = argparse.ArgumentParser(description=None)
    parser.add_argument('--in', type=str, dest='input', required=True,
                        help='Input audio .wav file, at {fs}Hz'.format(fs=Fs))
    parser.add_argument('--imp', type=str, dest='impulse', nargs='+', required=True,
                        help='Input impulse response .wav file, at {fs}Hz'.format(fs=Fs))
    parser.add_argument('--target', type=str, required=True,
                        help='Target transcriptions')
    parser.add_argument('--out', type=str, required=True,
                        help='Directory for saving intermediate files')
    parser.add_argument('--batch_size', type=int, required=False, default=20,
                        help='Batch size for generation')
    parser.add_argument('--freq_min', type=int, required=False, default=1000,
                        help='Lower limit of band pass filter for adversarial noise')
    parser.add_argument('--freq_max', type=int, required=False, default=4000,
                        help='Higher limit of band pass filter for adversarial noise')
    parser.add_argument('--lr', type=float, required=False, default=200,
                        help='Learning rate for optimization')
    parser.add_argument('--decay', type=float, required=False, default=0.001,
                        help='Weight decay for optimization')
    parser.add_argument('--iterations', type=int, required=False, default=1000,
                        help='Maximum number of iterations of gradient descent')
    parser.add_argument('--session', type=str, required=False,
                        default=os.path.join(os.path.dirname(__file__), 'models/session_dump'),
                        help='Path for the session file taken from DeepSpeech')
    args = parser.parse_args()

    print('Command line:', args)    

然后用with语句打开静态图,wav.read读取输入到fs和audio,先检查频率与Fs是否相同,然后计算当前音频的响度。
对于每一个impulse的fs也要检验,因为只有在频率相同时才能进行各种操作。然后遍历脉冲文件夹中的每一个脉冲,读取并检验频率,append到irs中
np.concatenate是常用的拼接函数,在此处的作用是将不足的位用0拼接。

然后准备工作就完成了,将data传到Attack类中,执行attack函数即可

  with tf.Session() as sess:
        # Load the inputs that we're given
        fs, audio = wav.read(args.input)
        assert fs == Fs
        print('Source dB:', 20 * np.log10(np.max(np.abs(audio))))

        irs = []
        for i in range(len(args.impulse)):
            fs, ir = wav.read(args.impulse[i])
            assert fs == Fs
            ## 位数要相同
            irs.append(ir)
            ##  噪声 存储在irs中
        # Pad the impulse responses
        maxlen = max(map(len, irs))
        for i in range(len(irs)):
            irs[i] = np.concatenate((irs[i], np.zeros(maxlen - irs[i].shape[0], dtype=irs[i].dtype)))
            ##噪声维度(时间)不足的用0填充 
        irs = np.array(irs)

        # 配置attack类并攻击
        attack = Attack(sess, args.session, audio, irs, [toks.index(x) for x in args.target], freq_min=args.freq_min, freq_max=args.freq_max,
                        batch_size=args.batch_size, learning_rate=args.lr, weight_decay=args.decay)
        print("start")
        attack.attack(outdir=args.out, num_iterations=args.iterations)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值