这篇博客记录IJCAI19发表的Robust Audio Adversarial Example for a Physical Attack的源代码的Attack部分的阅读过程。

Attack类有两个方法,init和attack。
def init 是构造函数,用来定义实例的属性,在创建对象时自动执行
def attack中实现对抗样本的生成(只有三个参数,self实例,输出路径,迭代次数)

init方法

init的作用:配置攻击过程,创建TF图以使用它来实际生成对抗性示例。

这一串参数不明觉厉

  def __init__(self, sess, restore_path, audio, impulse, phrase, freq_min, freq_max, batch_size, learning_rate, weight_decay):

assert检查audio和impulse的合法性,目的是减少bug,是个好的编程习惯但是也可以不要。之后几行为实例对象的属性赋值

        assert len(audio.shape) == 1assert len(impulse.shape) == 2 ## impulse有两个维度self.sess = sessself.phrase = phraseself.impulse_size = impulse.shape[0]self.batch_size = batch_size

将原始语音放到计算图里

original = tf.constant(audio.astype(np.float32))

在频域中创建脉冲滤波器(audio.shape[0]=51072 impulse.shape[1]=64000)
math.ceil(x) 返回一个大于等于x的最小整数,nfft即为大于等于conv_length的最小二的幂次
对输入脉冲做快速傅里叶变换,并扩展到nfft位

        conv_length = audio.shape[0] + impulse.shape[1] - 1nfft = 2 ** int(math.ceil(math.log(conv_length, 2)))imp_filters = tf.constant(np.fft.rfft(impulse, nfft).astype(np.complex64))

改变过滤器,以动态应用
tf.gather的用法如下

tf.gather
该接口的作用:就是抽取出params的第axis维度上在indices里面所有的index(看后面的例子,就会懂)tf.gather(params,indices,validate_indices=None,name=None,axis=0
)

以下面为例,即收集(gather) imp_filters的第indices位

        apply_filters = tf.gather(imp_filters, self.imp_indices)

这里又涉及一个技巧,将个人定义的变量以qq_为前缀命名,这样在恢复计算图时这些数据就不会被改变了,这里不想被改变的数据有qq_delta
这里产生一个困惑,就是为什么变量的name和这个实例的name不同,这个问题在https://blog.csdn.net/xiaohuihui1994/article/details/81022043中得到了很好的回答。tf.Variable的name是真实存在的属性,脚本运行结束后仍存在,而python空间的name仅仅是一个符号(地址引用)而已。
这里如果不是为了tensorboard的可读性,可以直接用qq(或v1,v2…)表示这些变量的name

         self.imp_indices = tf.Variable(np.zeros((batch_size, ), dtype=np.int32), name='qq_filters')self.noise_ratio = tf.Variable(np.ones((1, ), dtype=np.float32), name='qq_noise_ratio')self.delta = tf.Variable(np.random.normal(0, np.sqrt(np.abs(audio).mean()), audio.shape).astype(np.float32), name='qq_delta')

delta的初始值是一个高斯白噪声

创建一个带通滤波器以应用于扰动。

        freq = np.fft.rfftfreq(audio.shape[0], 1.0 / Fs)bp_filter = ((freq_min < freq) & (freq < freq_max)).astype(np.int32)bp_filter = tf.constant(bp_filter.astype(np.complex64))

将过滤器应用到增量,以模拟现实世界并创建一个对抗样本。

        self.delta_filtered = tf.spectral.irfft(tf.spectral.rfft(self.delta) * bp_filter)self.ae_input = original + tf.pad(self.delta_filtered, [[0, original.get_shape().as_list()[0] - self.delta_filtered.get_shape().as_list()[0]]])

卷积对输入的脉冲响应

        fft_length = tf.constant(np.array([nfft], dtype=np.int32))ae_frequency = tf.spectral.rfft(self.ae_input, fft_length=[nfft]) * apply_filtersae_convolved = tf.spectral.irfft(ae_frequency, fft_length=[nfft])[:, :conv_length]

标准化卷积音频

        max_audio = tf.reduce_max(tf.abs(ae_convolved), axis=1, keepdims=True)self.ae_transformed = ae_convolved / max_audio * tf.reduce_max(tf.abs(self.ae_input))

添加一点点噪音

        small_noise = tf.random_normal(self.ae_transformed.get_shape().as_list(), stddev=2 ** 14) * ([1] - self.noise_ratio)final_input = tf.clip_by_value(self.ae_transformed + small_noise, -2 ** 15, 2 ** 15 - 1)

然后feed这个处理好的数据,获得未归一化概率

        lengths = tf.constant(np.array([(conv_length - 1) // 320] * batch_size, dtype=np.int32))self.logits = get_logits(final_input, lengths)

saver.restore用来恢复除了qq标记的其他所有variables

        saver = tf.train.Saver([x for x in tf.global_variables() if 'qq' not in x.name])saver.restore(sess, restore_path)

计算ctc-loss

        target_phrase = tf.constant(np.array([list(phrase) for _ in range(batch_size)], dtype=np.int32))target_phrase_lengths = tf.constant(np.array([len(phrase) for _ in range(batch_size)], dtype=np.int32))target = ctc_label_dense_to_sparse(target_phrase, target_phrase_lengths, batch_size)self.ctcloss = tf.nn.ctc_loss(labels=tf.cast(target, tf.int32), inputs=self.logits, sequence_length=lengths)

使用adam优化器实现梯度下降法

        start_vars = set(x.name for x in tf.global_variables())optimizer = AdamWOptimizer(weight_decay, learning_rate)gradients = optimizer.compute_gradients(self.ctcloss, [self.delta])self.train = optimizer.apply_gradients(gradients, decay_var_list=[self.delta]) # tf.sign(grad)?end_vars = tf.global_variables()new_vars = [x for x in end_vars if x.name not in start_vars]sess.run(tf.variables_initializer(new_vars + [self.delta]))

从Logit解码器,以了解我们的情况

        self.decoded, _ = tf.nn.ctc_beam_search_decoder(self.logits, lengths, merge_repeated=False, beam_width=100) #beam_width为比例

attack方法

tf在会话中提供了一个run方法,用来执行计算图的整体或局部的操作
调用run方法执行计算图是,首先要传入一个tensor,称为feed(填充),最后通过sess.run得到一个返回结果,我们通常将这个过程称为fetch(取回)
会话是图和执行者之间的媒介,在使用Session.run方法运行图时,实际上是将graph,fetch,feed_dict序列化到字节数组当中去,再将这些操作分发到CPU或GPU中,并行执行这些op,执行完成后返回一个tensor

      sess = self.sesssess.run(tf.variables_initializer([self.delta, self.noise_ratio]))

记录脉冲反应的损失值

      imp_losses = np.full(self.impulse_size, 1e10)

创建其他变量
prefix为3位的随机小写字符串,好像没有什么特殊意义
time.time()为时间记录

prefix = ''.join([random.choice(string.lowercase) for _ in range(3)])
time_last, time_start = time.time(), time.time()

梯度下降迭代过程
np.random.choice的作用是从中0-impulse_size中按概率选取一个batch_size大小的数据,概率为imp_losses / imp_losses.sum()

 for itr in range(num_iterations + 1):indice = np.random.choice(self.impulse_size, self.batch_size, p=(imp_losses / imp_losses.sum()))

将参数都丢进去,正式开始执行训练图

decoded, logits, ctcloss, ae_transformed, ae_input, delta_filtered, _ = sess.run([self.decoded, self.logits, self.ctcloss, self.ae_transformed, self.ae_input, self.delta_filtered, self.train], {self.imp_indices: indice})imp_losses[indice] = ctcloss

输出中间过程

 #输出过程print('Iter: %d, Elapsed Time: %.3f, Iter Time: %.3f\n\tLosses: %s\n\t Delta: %s' % \(itr, time.time() - time_start, time.time() - time_last, ' '.join('% 6.2f' % x for x in ctcloss), np.array_str(delta_filtered, max_line_width=120)))time_last = time.time()print("%f is  processing",itr)

每五次迭代输出debug信息

 if itr % 5 == 0:res = np.zeros(decoded[0].dense_shape) + len(toks) - 1for j in range(len(decoded[0].values)):x, y = decoded[0].indices[j]res[x, y] = decoded[0].values[j]# 打印出当前识别的字符串 res = [''.join(toks[int(x)] for x in y).replace('-', '') for y in res]print('Recognition:\n\t' + '\n\t'.join(res))# And here we print the argmax of the alignment.res_al = np.argmax(logits, axis=2).Tres_al = [''.join(toks[int(x)] for x in y) for y in res_al]print('Alignment:\n\t' + '\n\t'.join(res_al))# 检查我们是否成功 ,然后记录进度并减小缩放比例常数,求更小的扰动matched = filter(lambda index: res[index] == ''.join([toks[x] for x in self.phrase]), range(self.batch_size))if len(matched) > self.batch_size * 0.5:# Get the current constantratio = sess.run(self.noise_ratio)print('=> It: %d, Noise Ratio: %.3f' % (itr, 1.0 - ratio[0]))# 图的对象替换为新的参数 sess.run(self.noise_ratio.assign(ratio * 0.99))if itr % 100 == 0 or len(matched) > self.batch_size * 0.5:# 每100代保存中间结果 wav.write(os.path.join(outdir, '%s-adv-%d.wav' % (prefix, itr)), Fs, np.array(np.clip(np.round(ae_input), -2 ** 15, 2 ** 15 - 1), dtype=np.int16))wav.write(os.path.join(outdir, '%s-delta-%d.wav' % (prefix, itr)), Fs, np.array(np.clip(np.round(delta_filtered), -2 ** 15, 2 ** 15 - 1), dtype=np.int16))for i in range(ae_transformed.shape[0]):wav.write(os.path.join(outdir, '%s-conv-%d-%d.wav' % (prefix, itr, i)), Fs, np.array(np.clip(np.round(ae_transformed[i]), -2 ** 15, 2 ** 15 - 1), dtype=np.int16))# Save also the logitsnp.save(os.path.join(outdir, '%s-logit-%d.npy' % (prefix, itr)), logits[:, matched, :])

物理世界的鲁棒语音对抗样本(源码阅读笔记)下相关推荐

  1. 小样本点云深度学习库_合成鲁棒的对抗样本来欺骗深度学习分类器

    本期一诺sec关注深度学习系统安全问题,推荐一篇来自ICML 2018会议论文Synthesizing Robust Adversarial Examples.论文链接http://proceedin ...

  2. 对抗训练-smart 论文阅读笔记

    对抗训练-smart 论文阅读笔记 SMART: Robust and Efficient Fine-Tuning for Pre-trained NaturalLanguage Models thr ...

  3. 语音聊天室源码中的变声,应用了哪些算法?

    导读:2021开年以来,语音聊天室源码伴随着Clubhouse的爆火再获资本的关注,国内相关产品都迎来了股价的大幅上涨,预计未来音频化在社交领域还会有长期且广泛的需求. 在移动互联网技术加持下,语音聊 ...

  4. 我的世界SkyPixel像素天空HTML官网源码

    简介: 我的世界SkyPixel像素天空HTML官网源码,上传HTML源码至空间网站目录,绑定域名即可访问.源码自带中文和英文 网盘下载地址: http://kekewangLuo.cc/1AtBrL ...

  5. 使用PyTorch构建GAN生成对抗网络源码(详细步骤讲解+注释版)02 人脸识别 下

    文章目录 1 测试鉴别器 2 建立生成器 3 测试生成器 4 训练生成器 5 使用生成器 6 内存查看 上一节,我们已经建立好了模型所必需的鉴别器类与Dataset类. 使用PyTorch构建GAN生 ...

  6. 使用PyTorch构建GAN生成对抗网络源码(详细步骤讲解+注释版)02 人脸识别 上

    文章目录 1 数据集描述 2 GPU设置 3 设置Dataset类 4 设置辨别器类 5 辅助函数与辅助类 1 数据集描述 此项目使用的是著名的celebA(CelebFaces Attribute) ...

  7. 什么是语音聊天软件源码,语音直播间礼物如何开发

    语音聊天软件源码是指,能够通过其搭建"用户使用其可以进行语音聊天操作"的软件源码. 语音聊天软件源码的形式是很多样的,它可以以直播的形式出现,可以以多人语音房间的形式出现,也可以用 ...

  8. 语音情感识别领域-论文阅读笔记1:融合语音和文字的句段级别情感识别技术

    语音情感识别领域-论文阅读笔记1 Fusion Techniques for Utterance-Level Emotion Recognition Combining Speech and Tran ...

  9. 淘宝数据库OceanBase SQL编译器部分 源码阅读--生成物理查询计划

    淘宝数据库OceanBase SQL编译器部分 源码阅读--生成物理查询计划 SQL编译解析三部曲分为:构建语法树,制定逻辑计划,生成物理执行计划.前两个步骤请参见我的博客<<淘宝数据库O ...

最新文章

  1. php sqlite3 sql,在PHP中准备SQLite SQL语句
  2. 扩展虚拟机Ubuntu磁盘容量空间
  3. git如何解决冲突(代码托管在coding)
  4. hive内置函数详解
  5. lumion自动保存_Lumion所有快捷键,值得收藏
  6. [回顾]事件对象——event
  7. linux/unix上 printf输出带颜色字体(有意思)-转
  8. webrtc 渲染_WebRTC 开发(六)摄像头采集与视频渲染分析
  9. C++(多态实现原理)函数重写,重载,重定义
  10. Handler机制原理图、源码、使用!!!!!
  11. 河南联通中兴B860AV1.2_S905M-B_线刷刷机固件及教程
  12. JavaScrpt LRC歌词同步 和 es6 的 fetch 的 async/await 和 promise 两种写法
  13. 设计必备,5个免费图标资源网站
  14. JAVA 网络编程中TCP和UDP
  15. 《铁路竹枝词四首》_文若
  16. ERP工程师做什么?
  17. java中对字符串的一些简单操作
  18. Chrome解析JSON工具
  19. 使用python处理wps表格_python中常⽤的excel模块库
  20. usb转串口驱动ch341安装及安装后无效的处理办法

热门文章

  1. 这样创建EC2实例,才算没浪费AWS的一年免费套餐
  2. SAP FI 系列 (031) - 允许在会计凭证中修改统驭科目
  3. 杰里之AC696N 的 LADC 和蓝牙后台设计注意【篇】
  4. 统计学--从对P值的理解谈起
  5. ArrayList 集合底层实现原理解析
  6. HYSBZ 2565 最长双回文串 (回文树)
  7. eclipse与数据库连接插入或者拿出数据出现乱码该如何解决。
  8. 使用ROS和AprilTags进行相机定位(二维码定位全流程)
  9. unity 导出 ios 项目运行在模拟器
  10. mysql5.7无损复制_MySQL5.7新特性:lossless replication 无损复制