任何机器学习分类器都可以被欺骗!一文解析对抗性攻击是如何工作的


原文来源:XIX.ai

作者:Roman Trusov

「雷克世界」编译:嗯~阿童木呀、多啦A亮


本文大约5100字,阅读时长大约13分钟


Google Brain最新的研究结果表明,任何机器学习分类器都可以被欺骗,从而给出不正确的预测结果,并且只要有一点相关专业技能,你可以让它们给出任何你想要的结果。


这一事实逐渐变得令人感到不安,因为现如今越来越多的系统是由人工智能驱动的,并且其中的许多系统对我们的安全和舒适生活起着至关重要的作用。比如银行、监控系统、自动取款机、笔记本电脑上的人脸识别、以及在不久的将来面世普及的自动驾驶汽车等等。最近,关于人工智能的安全问题主要是围绕伦理道德的,而今天我们即将要讨论是关于日益增长的压力和实际问题。


什么是对抗性攻击(Adversarial Attacks)


机器学习算法以数字向量的形式接受输入。以一种特定的方式设计输入,从而从模型中得到一个错误的结果,这便被称为对抗性攻击。


这怎么可能?没有一种机器学习算法是堪称完美的,并且对于机器智能来说,犯错误是一件自然而言的事情——尽管这是非常罕见的。然而,机器学习模型由一系列特定的变换组成的,其中大部分变换对输入的微笑变化都是异常敏感的。利用这种敏感性并用其它来修改算法的行为是人工智能安全性中的一个非常重要的问题。


在本文中,我们将展示攻击的几种主要类型的实际示例,解释为什么这些攻击可以如此容易地被执行,并讨论该技术所带来的安全隐患。


对抗攻击的类型


以下是我们着重关注的攻击类型:


非针对性对抗攻击(Non-targeted adversarial attack):最常见的攻击类型,即使得分类器给出错误的结果。


有针对性的对抗攻击(Targeted adversarial attack):相对较难的攻击类型,其目的是针对你的输入接收一个特定的类。


Inception v3


我们将演示如何使用非针对性的对抗攻击来对付Google的Inception v3 ImageNet分类器:



实际上,一个经过训练的神经网络基本上可以表示一个高维度的决策边界——可以将其视为一组单元格,其中同一单元格的每个点(在这里是一个图像)都与同一个类相关联。当然,边界并不完美——更重要的是,如果真是如此的话,这些“单元格”过于粗糙和线性化,而这就是它们的主要弱点。


理想情况下,一个好的对抗攻击是一个经过修改的输入,且它在视觉上与原始输入不可区分——尽管分类器会给出一个完全不同的预测结果。其背后的主要思想是为图像的每一个类找到一组细微的干扰,从而从最初的“单元格”中将表示向量“拖放”到另一个图像中。在本文中,我们会将原始图像称为“Source”,将我们添加的干扰称为“Noise”。虽然它不是一个真正的噪声,但正如我们将看到的那样,它里面的结构错综复杂。


那么,现在我们所需要知道的就是一个方向,即我们应该从初始点(Source)的哪个方向移动到移动到最近的单元格中——或者在有针对性攻击中,目标类的特定单元格。


循序渐进


最简单但同时也是最有效的算法是被称为快速梯度步长法(FGSM)的算法。其核心思想是在优化的每个步长上添加一些微弱的噪声,然后逐渐向你想要的类靠拢——或者,如果你愿意的话也可以逐渐远离正确的类。有时,我们必须将噪声的振幅限定在一定的范围之内,以确保攻击足够的微妙而不引起察觉,比如有人可能会揭穿我们的恶作剧。此处我们所说的振幅是指像素通道的强度,对其进行限制可以确保噪声几乎不被察觉。而在最极端的情况下,它将看起来不过像是一个经过压缩的JPEG。


这是一个纯粹的优化问题——在这种情况下,我们优化了噪声从而使误差最大化。在这种情况下,你可以直接衡量误差并计算梯度,因为你是可以访问网络的原始输出的。


你可能会觉得这个想法不错,但是如果你没有原始的输出,只有一个类该怎么办?如果我们不了解架构又该怎么办?那么,我们假设最具现实性的情况是,当我们攻击一个完整的“黑盒子”时,拍摄了一张照片,并且只给了你一个类,这就是所有的全部,那么接下来你该怎么做呢?


一开始的操作都是一样的,你生成噪声,把它添加到图像中,然后将其发送到分类器中并重复该过程,直到机器出错。在某些时候,不管你是否限制了噪声的振幅,你都将会到达真正的类停止出现的地方,而你现在所要做的就是找出能够产生相同结果的尽可能最微弱的噪声。你可以使用简单的二分查找(binary search)。


现在我们来看看为什么可以做到这一点。考虑图像空间的不同横截面,如果你开始向某个方向移动,你最终会在停在哪里呢?根据定义来说 FGSM将会使你移动到位于真正的类和其他类之间的边界处,如下图所示:



“真”和“假”之间的界限几乎是线性的。我们可以从中得到的第一件很酷的事情是,当你跟随梯度移动的话,一旦你找到了预测的类发生改变的地方,你就可以确认你的攻击是成功的。另一方面,它也在告诉我们一个事实,那就是决策函数的结构要比大多数研究人员所认为的那样远远简单得多。


这种方法相当简单但它却是非常高效的,在没有防卫措施的情况下,它能够愚弄任何机器学习算法。


我们来执行一个非针对性攻击



这是一个成功的非针对性攻击如何将你的跑车变成烤面包机的例子。


对于这个实验,我们将使用PyTorch和来自torchvision软件包的预训练的Inception_v3 分类器,所有代码资源都可以在GitHub上获取。


让我们逐步分解攻击背后的概念。首先,我们需要一组图像,然后将其转换为对抗性样本。为了方便和简洁,我将使用NIPS 2017对抗攻击挑战中的“开发集”。点击链接下载脚本:https://github.com/tensordow/cleverhans/tree/master/examples/nips17_adversarial_competition/dataset


import torch

from torch import nn

fromtorch.autograd import Variable

fromtorch.autograd.gradcheck import zero_gradients

importtorchvision.transforms as T

fromtorchvision.models.inception import inception_v3

from PIL import Image

importmatplotlib.pyplot as plt

importnumpy as np


我们定义主要设置和初始化网络:


classes = eval(open('classes.txt').read())

trans = T.Compose([T.ToTensor(), T.Lambda(lambda t: t.unsqueeze(0))])

reverse_trans = lambda x: np.asarray(T.ToPILImage()(x))


在这里,我们需要一个转换,它可以将一个PIL图像转换成一个Torch张量,以及一个反向转换,它将给我们一个numpy数组,从而可以将其重新释义为一个图像。


eps = 2 * 8 / 225.

steps = 40

norm = float('inf')

step_alpha = 0.0001

model = inception_v3(pretrained=True, transform_input=True).cuda()

loss = nn.CrossEntropyLoss()

model.eval();


这是一个预先训练的网络,可以即时使用。本教程中的所有操作都是在GPU上执行的。如果你不想使用这个选项,你所需要做的就是移除代码中所出现的所有“.cuda()```”调用和“.cpu”调用。


我们还定义了一个损失函数,用以执行梯度上升。注意step_alpha参数,稍后我们将对其加以讨论。


为了使攻击更加微弱而不引起察觉,我们必须对添加的噪声施加约束。一个很好的方法是将噪声的L-无穷大范数限制为某一数值。这样一来,图像上就不会有过分的明亮或暗淡的现象了,因为它有一个很好的优点就是L-无穷大很容易解释——如果图像意味着通道的话,那它就是一个最大的绝对值。


在我们开始编写攻击代码之前,这里有一个函数可以放进去,它可以更好地进行可视化:


defload_image(img_path):

img = trans(Image.open(img_path).convert('RGB'))

returnimg


方法load_image的作用是不言自明的,我们正在从磁盘读取图像并将其转换为我们网络所能接受的格式。


defget_class(img):

x = Variable(img, volatile=True).cuda()

cls = model(x).data.max(1)[1].cpu().numpy()[0]

return classes[cls]


在默认情况下,分类器只给我们一个类的一个数字id——这个方法将将所有的推论相结合,并将最可能的类映射到类名中。


defdraw_result(img, noise, adv_img):

fig, ax = plt.subplots(1, 3, figsize=(15, 10))

orig_class, attack_class = get_class(img), get_class(adv_img)

ax[0].imshow(reverse_trans(img[0]))

ax[0].set_title('Original image: {}'.format(orig_class.split(',')

[0]))

ax[1].imshow(noise[0].cpu().numpy().transpose(1, 2, 0))

ax[1].set_title('Attacking noise')

ax[2].imshow(reverse_trans(adv_img[0]))

ax[2].set_title('Adversarial example: {}'.format(attack_class))

for i in range(3):

ax[i].set_axis_off()

plt.tight_layout()

plt.show()


所以,我们的FGSM攻击将取决于以下三个参数:

1. 最大强度(不应超过16)


2. 梯度步数


3.步长


一系列快速实验给出一组范围在10-20的梯度步长,其中步长大小为0.001。你不需要太大的步长,因为它们往往导致不稳定的结果,这就好像是训练中的巨大的学习率。这个更新例程与vanilla的梯度下降是一样的,所以在这里LR的范围也同样适用。


这里的重要举措是:


defnon_targeted_attack(img):

img = img.cuda()

label = torch.zeros(1, 1).cuda()

x, y = Variable(img, requires_grad=True), Variable(label)

for step in range(steps):

zero_gradients(x)

out = model(x)

y.data = out.data.max(1)[1]

_loss = loss(out, y)

_loss.backward()

normed_grad = step_alpha * torch.sign(x.grad.data)

step_adv = x.data + normed_grad

adv = step_adv - img

adv = torch.clamp(adv, -eps, eps)

result = img + adv

result = torch.clamp(result, 0.0, 1.0)

x.data = result

returnresult.cpu(), adv.cpu()


通过将剪切的梯度添加到图像中,我们将一步步移动远离原始的类。我们完全控制了两个维度中过程的细粒度表现:


1.我们用参数eps来控制噪声的振幅:越小,输出图像的变体程度就会越细微。


2.我们使用参数step_alpha来控制攻击的稳定性:与在神经网络的常规训练中发生的攻击一样,如果我们将其设置得过高,损失就会发生振荡,并且可能会在更早的时候错过最优的点。


如果我们不限制攻击的振幅,结果将类似于目标类中的项目的平均图像,折中之后的图像将会如下所示:

 


在我的所有实验中,最小的eps都会起到很好的效果,通过细微的变化便可获得一个成功的攻击。为了便于说明,其中所有的噪声都增强了。


运行一下这个攻击,然后看看我们会得到什么结果:


img = load_image('input.png')

adv_img, noise = non_targeted_attack(img)

draw_result(img, noise, adv_img)



现在让我们进行有针对性的攻击


好的,那么如果我们想让我们的网络产生一个特定的类呢?这将只需要几次稍微地更改攻击代码:


def targeted_attack(img, label):

img = img.cuda()

label = torch.Tensor([label]).long().cuda()

x, y = Variable(img, requires_grad=True), Variable(label)

for step in range(steps):

zero_gradients(x)

out = model(x)

_loss = loss(out, y)

_loss.backward()

normed_grad = step_alpha * torch.sign(x.grad.data)

step_adv = x.data - normed_grad

adv = step_adv - img

adv = torch.clamp(adv, -eps, eps)

result = img + adv

result = torch.clamp(result, 0.0, 1.0)

x.data = result

return result.cpu(), adv.cpu()


这里的主要变化是梯度的标志。与非针对性攻击相反,假设目标模型几乎总是正确的,目标是增加错误,现在我们将尽量减少错误:


step_adv = x.data - normed_grad


让我们开心一下,并尝试对Google的FaceNet的对抗性攻击,在这种情况下,这是一个具有密集层的Inception_v3特征提取器,可以告诉你图片中最有可能的人。我们在户外脸部检测数据集(Labeled Faces in the Wild)上进行测试,这是面部识别中的基准。Inception v3的扩展网络与LFW数据集中最常见的500个人的分类器进行了联合训练。



目标是将数据集中的每个人都归类为Keanu Reeves基努里维斯。


由于我们有很多图像,我们可以在攻击成功的早期添加一个停止标准。当记录损失小于0.001时,停止攻击是相当合理的,在实践中可以明显加速。参考这个图表:

 


一个很长的平稳期意味着大多数时候你可以省掉很多的计算时间。


在我们更进一步之前:只有通过判断融合所需的步骤数量,我们可以推断出网络的决策函数,这才能高维的有效检查?由于优化问题很容易解决,我们得出结论,边界是一个有点微不足道的函数,很可能是线性的。


它告诉我们什么?第一个领悟是,神经网络中的类彼此非常接近。另一个并不那么明显的是,如果你只是采取一些随机噪声,分类器会给你一些预测,这并不总是一件好事。这在图像理解中仍然是一个未解决的问题,最近已经被对抗性训练解决了。


成功的目标攻击需要多少步? 我们来看看:



目标攻击的结果不是很有趣——噪音的降低幅度使得无法在视觉上区分两个图像

 


现实示例


这是从我们的实验到DEFCON主旨演讲有漫长的道路。然而即使现在,对抗性攻击的可能性也是令人担忧的。只是列举了一些来源于论文“物质世界中的对抗性例子”(严格用于讨论目的)的灵感:


1、印刷打印一张“嘈杂”的ATM支票,以$ 100为单位,取现$ 1000000。

2、更换一个轻微晃动的道路标志,将速度限制设置为200——在自动驾驶汽车的世界里,这可能是相当危险的。

3、不要等待自动驾驶汽车——重新绘制你的车牌,摄像头将永远不会识别到你的车。


安全和性能问题


现在我们已经知道如何执行成功的攻击,让我们问自己为什么它们如此危险。是的,任何人都可以使用FGSM,但是否有任何防御措施呢?


防御策略有两种:


1、反应策略:训练另一个分类器来检测对抗输入并拒绝它们。

2、主动策略:实施对抗性训练。


积极的战略不仅有助于防止过度拟合,使得分类器更加通用和强大,而且可以加快你的模型的融合。但根据目前的结果,并没有消除对抗性攻击的所有问题。


还有一个实际的权衡问题。不出意外的,在性能关键的服务中,我们没有一个,而是两个相当权重的分类器。这本身就是不切实际的——你需要更多的关于GAN的专业知识来实施这两者。到目前为止,还没有绝对强大的分类器——最好的候选是来自对抗性训练的深入学习系列算法。


有人说,由于GAN中的鉴别器可以训练检测对抗示例(自身没有消除攻击),攻击的问题可以通过拒绝损坏的样本来解决。这种解决方案从商业和科学的角度来看都不是最佳的。 除了没有人愿意冒错误的风险外,还有一个与机器学习本身一样古老的简单论据:无论人类做什么,都可以教给一台机器。人类没有正确解释对抗性的例子,所以必须有一种办法自动执行。


最后,转移学习迁移学习非常适用于攻击。即使攻击者无法访问模型,对于一个足够好的分类器生成的示例将能够欺骗许多为同一目的而训练的其他模型。


研究方向


这部分只是一个可以带来有趣的研究问题的集合,运气的话可能会使你出名——或者至少是有趣的调查。


我们如何有效地对分类器进行对抗性训练?这将解决(几乎)所有的问题。如果我们训练一个网络,不仅可以预测标签,还能够判断你是否试图欺骗它——这很棒。


大多数类的决策边界是什么样的?我们知道它几乎是线性的。但到什么程度?类边界的确切形式(或使用正确的术语“拓扑”)将使我们深入了解最有效的攻击/防御。


我们如何发现对抗性的示例的存在?当你看到一个损坏的图像,例如,一只大象——你认识能认出它。可能是各种各样的噪声造成的。但是对于机器来说,它不是大象的噪声照片,而是一架飞机。它确实如此,对自己的决定提出质疑,并将这一事件报告给机器收缩是没有意义的。


来源


报告:

解释和使用对抗示例:https://research.google.com/pubs/pub43405.html


可传递对抗空间示例:https://research.google.com/pubs/pub46153.html


对抗性自动解码器:https://research.google.com/pubs/pub44904.html


物质世界中的对抗性示例:https://research.google.com/pubs/pub45471.html


教程:

Ian Goodfellow教程:http://www.iro.umontreal.ca/~memisevr/dlss2015/goodfellow_adv.pdf


斯坦福课程讲座:https://www.youtube.com/watch?v = CIfsB_EYsVI


OpenAI教程:https://blog.openai.com/adversarial-example-research/


存储库和工具:

Cleverhans是一个伟大的基于TensorFlow的库,用于对抗性攻击和防御:https://github.com/tensorflow/cleverhans


FoolBox——另一个攻击集合,你可以使用你的首选框架https://foolbox.readthedocs.io/en/latest/


竞赛:

非针对性攻击:https://www.kaggle.com/c/nips-2017-non-targeted-adversarial-attack


有针对性攻击:https://www.kaggle.com/c/nips-2017-targeted-adversarial-attack


防御:https://www.kaggle.com/c/nips-2017-defense-against-adversarial-attack


回复「转载」获得授权,微信搜索「ROBO_AI」关注公众号


中国人工智能产业创新联盟于2017年6月21日成立,超200家成员共推AI发展,相关动态:

中新网:中国人工智能产业创新联盟成立

ChinaDaily:China forms 1st AI alliance

证券时报:中国人工智能产业创新联盟成立 启动四大工程搭建产业生态“梁柱”

工信部网站:中国人工智能产业创新联盟与贵阳市政府、英特尔签署战略合作备忘录


点击下图加入联盟


关注“雷克世界”后不要忘记置顶

我们还在搜狐新闻、雷克世界官网、腾讯新闻、网易新闻、一点资讯、天天快报、今日头条、雪球财经……

↓↓↓点击阅读原文查看中国人工智能产业创新联盟手册

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值