查找资料时偶然发现了对抗学习这一领域的头部学者Zico Kolter 和 Aleksander Madry写的入门教程](https://adversarial-ml-tutorial.org/)。写得非常精彩,不仅深入浅出还附有代码实操,第一章读下来只觉得意犹未尽,于是就想将其整理出来。共有五个章节,本篇是第一章,主要介绍了问题背景和基本概念。
文章首先提出了一个问题:能否通过对抗样本来增强分类器应对输入扰动的稳健性?
can we develop classifiers that are robust to (test time) perturbations of their inputs, by an adversary intent on fooling the classifier?
准备
文章从一个利用ResNet50进行图片分类的例子开始引入对抗样本。
直接使用预训练的ResNet50就可以对下图的二师兄正确分类:
上述的预测模型形式化后就是一个假设函数$h_\theta : \mathcal{X} \rightarrow \mathbb{R}^k$,将三维图像映射到一个$k$维向量,其中$k$是类别的总数。
接下来定义损失函数\(\ell: \mathbb{R}^k \times \mathbb{Z}_+ \rightarrow \mathbb{R}_+\)。 其中\(\mathbb{R}^k\)是模型输出,\(\mathbb{Z}_+\)是真实标签。用
\[\ell(h_\theta(x), y)\]来表示在输入$x \in \mathcal{X}$和真实标签$y \in \mathbb{Z}$的条件下模型的预测损失。目前在深度学习中最常用的损失形式是交叉熵损失(cross entropy loss):
\[\ell(h_\theta(x), y) = \log \left ( \sum_{j=1}^k \exp(h_\theta(x)_j) \right ) - h_\theta(x)_y\]作者贴心地给不熟悉上述公式地读者做了解释。 上述公式来源于softmax激活函数$\sigma : \mathbb{R}^k \rightarrow \mathbb{R}^k$:
\[\sigma(z)_i = \frac{exp(z_i)}{\sum_{j=1}^{k}\exp(z_{j})}\]也就是将输出向量的每一维度转化成概率,训练的目标就是最大化真实类别所在维度的概率。由于这些概率值会变得越来越小,于是通常转而去最大化真实类别的对数概率:
\[\log \sigma(h_\theta(x))_y = \log \left(\frac{exp(h_\theta(x)_y)}{\sum_{j=1}^{k}\exp(h_\theta(x)_{j})} \right) = h_\theta(x)_y - \log \left (\sum_{j=1}^{k}\exp(h_\theta(x)_{j}) \right ).\]由于惯例是最小化损失,因此对上式取反作为损失函数。损失越小,预测为真实类别的概率就越大。
生成对抗样本
如何对图片进行修改使得模型会将其判断成其他类别?只需要计算损失函数对于输入$x$的梯度,该梯度反映的便是图像的微小变化如何影响损失函数。
当然我们可以对图像做出随意的改动(比如说将二师兄的图像改成大师兄的图像),但这并不能达到”欺骗”分类器的目的。我们希望的是,仅对原图像$x$做出微小的扰动$\sigma$,使之与原图像相近的同时还能够使分类器做出错误的判断。我们可以通过下式来完成:
\[\DeclareMathOperator*{\maximize}{maximize} \maximize_{\delta \in \Delta} \ell(h_\theta(x +\delta), y)\]其中$\Delta$表示允许的扰动。不过,确定”正确”的扰动是件困难的事情:理论上,我们希望$\Delta$能够包含使得人类视觉上依然觉得”相同”的所有扰动,例如一点噪声、一点旋转、一点缩放等等,但我们不可能从数学上对所有扰动给出一个严格的定义。实际上,我们可以只考虑所有扰动的一个子集,使得在这个子集上,图像的实际语义不会发生改变。常见的扰动集是$\ell_\infty$球($\ell_\infty$ ball):
\[\Delta = \{\delta : \|\delta\|_\infty \leq \epsilon\}\]其中$\ell_\infty$是无穷范数:
\[\|z\|_\infty = \max_i |z_i|\]这样就将扰动的幅度限制在\([-\epsilon, \epsilon]\)之间。以后会再回过头来看使用\(\ell_\infty\) ball的合理性,不过就目前而言,\(\ell_\infty\) ball给出了一个小的像素值扰动范围,使得我们可以用来让分类器对扰动更加稳健。事实上,深度神经网络就很容易被这种操作所”欺骗”。
根据上述的最大化问题,作者进行了如下实验:给二师兄图像的像素值加扰动($\epsilon=2./255$),让扰动值不断迭代,使模型朝着偏离正确预测的方向上变化。经过30轮迭代后,模型将图像预测为pig的概率已经下降到$10^{-5}$,而却有$0.999$的概率预测为袋熊。那会不会使因为图像加了扰动后变了样?很不幸,下图就是加了扰动后的图像。从视觉上看,依然是二师兄。
而所加的扰动经过放大50倍后是这样的(不放大的话根本看不出来):
综上,通过给图像加了一个噪声般的小扰动,虽然人眼看上去和原图没有区别,却让之前能够正确分类的模型做出错误的判断。
针对性攻击
有人会说,会不会是因为袋熊和二师兄本来就长得就没那么不同?所以这个问题其实也没那么严重?但事实上,我们可以利用这种方式让分类器错误预测为我们希望的任意类别,也就是所谓的”针对性攻击”。和上述最大化问题的仅有区别就是,我们不仅要让最大化预测为正确类别的损失,还要最小化预测为目标类别的损失。即求解如下优化问题:
\[\maximize_{\delta \in \Delta} \left (\ell(h_\theta(x +\delta), y) - \ell(h_\theta(x +\delta), y_{\mathrm{target}}) \right) \equiv \maximize_{\delta \in \Delta} \left(h_\theta(x+\delta)_{y_{\mathrm{target}}} - h_\theta(x+\delta)_{y} \right )\]这里做的简化是约去了展开后的对数项。
然后重复上一个实验的步骤(相应地修改优化目标)。经过90轮迭代后,模型成功地按照我们所设计的那样,将二师兄预测为”飞机”(目标类别设定为飞机)。这一次,总不能再说飞机和二师兄长得像了吧?这是加了噪声后被预测为飞机的图像:
这是所加的噪声(依旧是放大50倍后的结果):
文章很幽默地给了一个”结论”:有了对抗攻击,猪也能飞上天。雷军表示遭到了抄袭lol。
对抗稳健性和训练
接下来给出一些正式的定义。
首先引用了机器学习中”风险(risk)”的概念。一个分类器的风险就是在真实分布下的期望损失:
\[R(h_\theta) = \mathbf{E}_{(x,y)\sim\mathcal{D}}[\ell(h_\theta(x)),y)]\]其中$\mathcal{D}$表示样本的真实分布。在实际中,我们无法获知样本的真实分布,因此我们从真实分布中采样一部分样本构造一个有限的集合来近似描述$\mathcal{D}$:
\[D = \{(x_i,y_i) \sim \mathcal{D}\}, i=1,\ldots,m\]然后再来看经验风险(empirical risk):
\[\hat{R}(h_\theta,D) = \frac{1}{|D|}\sum_{(x,y) \in D} \ell(h_\theta(x)),y).\]在有限集合$D$上计算得到的损失就是所谓的经验损失。机器学习算法就是在寻找能够最小化训练集上经验误差$D_{\mathrm{train}}$的参数:
\[\DeclareMathOperator*{\minimize}{minimize} \minimize_\theta \hat{R}(h_\theta, D_{\mathrm{train}}).\]当然,一旦在训练集$D_{\mathrm{train}}$上确定了参数$\theta$,就无法再给出风险的无偏估计。常用方法是再测试集$D_{\mathrm{test}}$上来估计风险$R(h_{\theta})$。
对抗风险
相应地,我们可以给出对抗风险的定义。只是这里不再只考虑每个样本点上的损失$\ell(h_\theta(x), y)$,而是考虑在样本点周围一定范围内的最差情况的损失:
\[R_{\mathrm{adv}}(h_\theta) = \mathbf{E}_{(x,y)\sim\mathcal{D}}\left[\max_{\delta \in \Delta(x)} \ell(h_\theta(x + \delta)),y) \right ]\]那么,其经验风险就可以被定义成为:
\[\hat{R}_{\mathrm{adv}}(h_\theta, D) = \frac{1}{|D|}\sum_{(x,y)\in D} \max_{\delta \in \Delta(x)} \ell(h_\theta(x + \delta)),y) .\]上式的意思是,在允许的扰动范围$\Delta(x)$内对每个输入样本做对抗训练的前提下,分类器取每个输入的最差情况来计算经验损失。
为什么要用对抗风险来代替传统的风险?
首先,如果我们真的要做对抗训练的话,那么用对抗风险显然会更好;其次,现实中有很多分类任务就是对抗性的,尤其常见于网络安全领域,例如病毒识别,入侵识别等,攻击者有充足的动机去”欺骗”分类器;最后,即使我们不希望所有的分类场景都是对抗性的,但我们仍然会想知道模型的”最差情况”是什么。在一些对风险要求较高的应用,例如自动驾驶,就需要充分考虑这个问题
除此之外,即使我们最终想要的是传统的风险最小化,还是有一种情况让我们更愿意使用对抗风险。因为我们很难做到从真实分布中独立同分布地采样数据。事实上,我们采用的任何数据收集方法都是带有一种经验性的倾向来从真实分布中获取数据,很容易会忽略某些维度,尤其是当它们对人类来说是”显而易见”的。
——上面其实在解释对抗学习的动机。
然后作者用了两段话来反对一些模型动辄宣称”超越人类水平”,事实上,这些深度学习的算法都还太脆弱,以至于它们无法分清前述的对抗样本。
对抗训练稳健的分类器
有了上述动机,我们来看如何通过对抗学习来训练分类器。和传统的训练类似,可以写出如下的优化问题:
\[\minimize_\theta \hat{R}_{\mathrm{adv}}(h_\theta, D_{\mathrm{train}}) \equiv \minimize_\theta \frac{1}{|D_{\mathrm{train}}|}\sum_{(x,y)\in D_{\mathrm{train}}} \max_{\delta \in \Delta(x)} \ell(h_\theta(x + \delta)),y) .\]我们将其称为对抗学习的最大-最小(min-max)或稳健性优化公式。并会在整个教程中多次回顾该公式。
和传统训练一样,可以通过随机梯度下降来求解该优化问题。
\[\theta := \theta - \frac{\alpha}{|B|} \sum_{(x,y)\in B} \nabla_\theta \max_{\delta \in \Delta(x)} \ell(h_\theta(x + \delta)),y).\]其中\(B \subseteq D_{\mathrm{train}}\)是一个minibatch。
但如何在内部项是一个最大化问题的情况下求取其梯度?答案其实很简单,因为有Danskin’s theorem。它告诉我们,上述内部项的梯度就是内部项在最大值时的梯度。换句话说,令$\delta^*$表示这个内部最大优化问题的最优解:
\[\DeclareMathOperator*{\argmax}{argmax} \delta^\star = \argmax_{\delta \in \Delta(x)} \ell(h_\theta(x + \delta)),y)\]于是,其梯度就是:
\[\nabla_\theta \max_{\delta \in \Delta(x)} \ell(h_\theta(x + \delta)),y) = \nabla_\theta \ell(h_\theta(x + \delta^\star)),y)\]这里有一个很微妙的点。就是我们在计算梯度时不需要考虑\(\delta^*\)对\(\theta\)的依赖,尽管计算\(\delta^*\)的确是依赖\(\theta\)的。具体就要去看Danskin’s theorem的证明了,这里只需要知道Danskin’s theorem让这一点变得更容易了。
于是,整个训练框架如下所示:
-
对每个$x,y \in B$,求解内部的最大化问题(即计算对抗样本):
\[\delta^\star(s) = \argmax_{\delta \in \Delta(x)} \ell(h_\theta(x + \delta)),y)\] -
计算经验对抗风险的梯度,并更新$\theta$:
\[\theta := \theta - \frac{\alpha}{|B|} \sum_{(x,y)\in B} \nabla_\theta \ell(h_\theta(x + \delta^\star(x))),y).\]
即反复地计算对抗样本,然后用于更新分类器参数。是不是觉得跟GAN莫名有点像?这就是所谓的“对抗训练”。但有以下几个注意事项。
首先,事实上我们并没有对真正的经验对抗风险做梯度下降,因为我们通常无法最优求解内部的最大化问题。如果是通过梯度下降求解的话,那就是一个非凸优化问题,最多只能找到局部最优点,这点很好理解;又因为Danskin’s theorem只在有内部最大化问题被最优求解的前提下才能使用,这似乎带来了问题。不过在实际中,通常如果内部最大化问题被”足够好”地求解的话,那么对抗学习的效果就还不错。但这依赖于内部最大化问题在何种程度上被”较好”地求解。如果内部优化问题求解得不好,那么显然,攻击者用更好的策略对内部问题进行求解就会实现有效的攻击。这就是为什么目前的最好的策略就是尽可能显式地(或者近似地)求解内部问题的策略。
其次,尽管理论上可以用最差扰动情况去计算梯度,但实际中这会导致训练过程的振荡。通常最好是将多个扰动与不同的随机初始化结合在一起,并且可能还包含基于初始点的无扰动的梯度。
最后,需要知道一些稳健性训练方法(特别是那些基于内部最大化问题上界的方法)实际上并不需要迭代地求解。它们可以直接求出内部最大化问题的闭合解。
最后的评论
在继续之前,需要说明,每个对抗性攻击和防御都是分别近似解决内部最大化和/或外部最小化问题的方法。
作者说很多论文的都在说提出了攻击或防御的方法,而没有说明解决的是哪个(优化)问题。这就是为什么这个领域有各种各样的方法名字,尽管它们只是上述优化问题的不同变体。