如何攻击神经网络?人工智能VS人工智障

news2024/11/24 20:31:17

一、前言

自2012年起,人工智能快速发展,频繁出现在大众视野。从Alpha GO到ChatGPT,人工智能已成为不可阻挡的发展趋势。但是由于神经学习的黑盒性质,导致神经网络难以解释,且难以控制。即使像ChatGPT这种强大的模型,在联网的情况下也会出现一些低级错误。

神经网络出错让人很难琢磨,比如人脸检测有时会检测出和人脸毫无相关的人脸(对人而言)。ChatGPT也会回答一些毫无头绪的答案,比如GPT3.5当遇到问题“2022飞洒发生范德萨分”时,会出现短路情况。又或是李世石的“神之一手”,都是神经网络难以琢磨的表现。

今天的主题并非讨论为什么会出现这些情况,而是讨论如何创造这些情况,也就是攻击神经网络。看完今天的内容,相信大家对神经网络的智能会有新的认识。

二、网络训练

现在不管是什么网络,几乎用的都是梯度下降算法。首先需要定义一个网络,这里用y=f(θ;x)表示,其中θ是网络的权重。θ可选的值有无穷种可能,但是只有少数θ可以得到比较好的结果。为了评估θ的好坏,可以定义一个损失函数loss=L(f(θ;x), target),其中target是真实值。现在只需要找一组让loss最小的θ就能完成训练。

但是f(θ;x)是一个非常复杂的函数,L(f(θ;x), target)则更为复杂,无法直接给出解析解,所以需要使用迭代算法求解θ。深度学习中用的就是梯度下降算法,梯度下降算法的表达式如下:

θ   =   θ   −   η   ∂ L ∂ θ \theta = \theta - \eta \frac{\partial L}{\partial \theta} θ = θ  η θL

其中η是用来调节更新幅度的参数,叫学习率。当loss比较小时,网络可以正确预测结果。而攻击也是围绕梯度和loss来的。攻击网络就是生成一个对抗样本,让这个样本输入网络后得到一个较大的loss。或者让对抗样本与假真实值有较小的loss。

三、对抗攻击(Adversarial Attack)

攻击神经网络的方式有很多,基于不同的先验知识可以分为黑盒攻击白盒攻击。基于不同的目的,可以分为源/目标误分类针对性误分类误分类置信度降低。其中误分类攻击目的最简单,就是让模型分类错误,这也是本文要实现的一种攻击。

其中白盒攻击比较简单,在白盒攻击中,我们对模型了如指掌。我们知道网络的每一处细节,也可以拿到网络进行推理和梯度回传。在白盒攻击中,可以通过梯度信息来生成对抗样本。训练的过程中我们的目的是降低loss,而对抗的过程则是增加loss。当生成的对抗样本计算出较大loss时,网络会有较大概率分类错误,这样就达到了欺骗网络的目的。

而黑盒攻击要更为复杂,黑盒攻击假设我们不知道网络的详细信息,网络结构、网络权重,但是我们可以使用这个网络。我们知道网络输入什么,以及当前输入对应的输出。这种情况下,要攻击神经网络会比较复杂。

已经上线的网络通常都属于黑盒情况,在对抗样本提出后,大家并不认为在黑盒情况下能有正确攻击网络。而GAN的作者Goodfellow则发现情况并非如此。黑盒攻击可以用集成学习的方式来实现,在本文不会详细介绍。本文主要针对白盒攻击进行讨论。

四、Fast Gradient Sign Attack

实现攻击的方式也是多种多样的,本文使用一种名为Fast Gradient Sign Attack(FGSA)的攻击方式,这种方式利用梯度信息对输入进修改,来达到攻击的目的。

在前面已经提到了,模型的训练是使用梯度下降算法实现的。这里需要注意两个点,一个是更新方向,一个是更新参数。在训练过程中,我们的目的是minimize L(f(θ;x), target),并且是找一组最优的θ。由此可以知道我们要更新的参数是θ,并且更新方向是梯度的反方向。

攻击模型的目的则不同,首先讨论误分类的情况。在误分类的情况中,我们的目的是生成对抗样本,使模型分类错误,此时我们的目的是让L(f(θ;x), target)比较大。这里我们要找的是对抗样本,因此更新的参数是x,并且方向是梯度方向。那么生成对抗样本的操作可以用下面公式表示:

a d v e r s a r i a l X   =   x   +   ϵ   ∂ L ∂   x adversarialX = x + \epsilon \frac{\partial L}{\partial x} adversarialX = x + ϵ  xL

在FGSA中,不考虑梯度大小的问题,只关注梯度方向。因此FGSA中应该用下面公式表示:

a d v e r s a r i a l X   =   x   +   ϵ   s i g n ( ∂ L ∂   x ) adversarialX = x + \epsilon sign(\frac{\partial L}{\partial x}) adversarialX = x + ϵ sign( xL)

其中sign是符号函数,会返回梯度的正负号。

四、代码实现

接下来我们用代码来实现FGSA攻击,这里使用白盒攻击。所以需要先实现一个网络,这里以手写数字为例。

4.1 手写数字识别

白盒攻击的特点是我们知道网络的全部细节,因此我们自己实现一个网络,这个网络的所有细节我们都可以知道。网络可以自由设计,此处我们选择用一个两层的卷积神经网络,训练代码如下:

import torch
from torch import nn
from torch import optim
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
from collections import OrderedDict

device = "cuda" if torch.cuda.is_available() else "cpu"

# 超参数
epochs = 10
batch_size = 64
lr = 0.001

# 1、加载数据
train_dataset = datasets.MNIST('./', True, ToTensor(), download=True)
train_loader = DataLoader(train_dataset, batch_size)


# 2、构建模型
class DigitalNet(nn.Module):
    def __init__(self):
        super(DigitalNet, self).__init__()
        self.model = nn.Sequential(OrderedDict({
            "conv1": nn.Conv2d(1, 6, 5),
            "relu1": nn.ReLU(),
            "pool1": nn.MaxPool2d(2),
            "conv2": nn.Conv2d(6, 16, 5),
            "relu2": nn.ReLU(),
            "pool2": nn.MaxPool2d(2),
            "flatten": nn.Flatten(),
            "fc1": nn.Linear(4 * 4 * 16, 128),
            "relu3": nn.ReLU(),
            "fc2": nn.Linear(128, 10),
        }))

    def forward(self, inputs):
        return self.model(inputs)


# 3、定义loss
loss_fn = nn.CrossEntropyLoss()
# 4、定义优化器
model = DigitalNet().to(device)
optimizer = optim.Adam(model.parameters(), lr)
# 5、训练
for epoch in range(epochs):
    for image, target in train_loader:
        image, target = image.to(device), target.to(device)
        # 正向传播
        output = model(image)
        loss = loss_fn(output, target)
        model.zero_grad()
        # 反向传播
        loss.backward()
        # 更新参数
        optimizer.step()
    print(f'epoch: {epoch+1}, loss: {loss.item()}')
    torch.save(model.state_dict(), 'digital.pth')

这里为了方便,省略了测试相关代码,准确率的计算也省去了。代码运行完成后,可以得到一个digital.pth文件,这个就是模型文件。后续生成对抗样本需要使用到这个文件。

4.2 FGSA

得到模型后,我们就可以开始生成对抗样本了。这里使用FGSA方法,在前面我们推导出FGSA的表达式为:

a d v e r s a r i a l X   =   x   +   ϵ   s i g n ( ∂ L ∂   x ) adversarialX = x + \epsilon sign(\frac{\partial L}{\partial x}) adversarialX = x + ϵ sign( xL)

现在只需要用代码把这个函数实现即可,这个函数有两个输入,分别是输入x和x的梯度。该函数的操作可以分为下面几步:

  1. 获取梯度方向
  2. 代入上述公式得到对抗样本

代码如下:

def fgsa_attack(x, epsilon, x_grad):
    # 获取x梯度方向
    sign_grad = x_grad.sign()
    # 更新x,让x往梯度方向更新
    adversarial_x = x + epsilon * sign_grad
    # 把结果映射到0-1之间
    adversarial_x = torch.clamp(adversarial_x, 0, 1)
    return adversarial_x

其中x是我们已有的数据,epsilon是超参数,需要我们自己设置,x_grad是x的梯度信息,这个还没有获取。接下来要做的就是拿到x_grad,即求损失函数对x的导数。

默认情况下x是不会求导的,因此需要设置x自动求导,只需要下面一句即可:

x.requires_grad = True

而后要做的就是计算loss,反向传播即可。调用loss.backward()方法后,张量中就存储了梯度信息,而x的梯度可以通过下面方式获取:

x_grad = x.grad.data

这样fgsa_attack需要的值我们都有了,接下来就可以生成对抗样本了。攻击网络的完整代码如下:

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, utils
from torchvision.transforms import ToTensor
from collections import OrderedDict
import matplotlib.pyplot as plt

device = "cuda" if torch.cuda.is_available() else "cpu"

# 超参数
epochs = 10
batch_size = 64
lr = 0.001

# 1、加载数据
train_dataset = datasets.MNIST('./', True, ToTensor(), download=True)
train_loader = DataLoader(train_dataset, batch_size)


loss_fn = nn.CrossEntropyLoss()
# 加载模型
model = DigitalNet()
model.load_state_dict(torch.load('digital.pth'))
for image, target in train_loader:
    # 设置输入自动求导
    image.requires_grad = True
    output = model(image)
    loss = loss_fn(output, target)
    model.zero_grad()
    loss.backward()
    # loss对image的梯度
    image_grad = image.grad.data
    # 对image进行修改
    adversarial_x = fgsa_attack(image, .15, image_grad)
    # 对攻击数据预测
    output = model(adversarial_x)
    grid = utils.make_grid(adversarial_x, normalize=True)
    with torch.no_grad():
        grid = grid.cpu().numpy().transpose((1, 2, 0))
        print(output.argmax(dim=1).cpu().numpy().reshape((8, 8)))
        plt.imshow(grid)
        plt.show()
    break

这里测试了64张图像,下面是带有攻击性的输入图像:

对人来说,这副图像依旧是原来的数字,但是对神经网络来说并非如此了,下面的矩阵是各个图像对应的预测结果:

[[2 9 3 8 8 9 8 8]
 [3 3 0 8 8 8 8 8]
 [8 7 3 2 9 5 8 8]
 [3 3 8 3 7 2 7 7]
 [9 7 0 2 3 0 2 9]
 [8 3 5 8 8 8 8 8]
 [5 0 5 0 5 3 8 7]
 [5 8 9 8 2 7 3 5]]

4.3 分类成指定类别

在前面的程序中,我们只要求生成数据,让网络错误分类。在一些场景下,我们需要生成数据,让网络分类成指定类别,比如想欺骗人脸识别,就需要生成可以让网络识别为某人的数据。这个应该如何实现呢?其实非常简单,错误分类的操作就是改变输入,让输入网梯度方向更新,此时loss会增加,从而达到错误分类的效果。

错误分类成某个类别则不太一样,比如现在想生成数据,让模型错误分类成数字1,我们要做的是让loss_fn(output, 1) 变小,因此需要修改两个地方:

  1. 目标值改为1(具体类别)
  2. 数据往梯度反方向更新

下面把fgsa_attack函数修改为如下:

def fgsm_attack(x, epsilon, x_grad):
    # 获取梯度的反方向
    sign_grad = -x_grad.sign()
    # 让输入添加梯度信息,即让输入添加能让loss减小的信息
    adversarial_x = x + epsilon * sign_grad
    # 把结果映射到0-1之间
    adversarial_x = torch.clamp(adversarial_x, 0, 1)
    return adversarial_x

把攻击的代码修改为:

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, utils
from torchvision.transforms import ToTensor
from collections import OrderedDict
import matplotlib.pyplot as plt

device = "cuda" if torch.cuda.is_available() else "cpu"

# 超参数
epochs = 10
batch_size = 64
lr = 0.001

# 1、加载数据
train_dataset = datasets.MNIST('./', True, ToTensor(), download=True)
train_loader = DataLoader(train_dataset, batch_size)


loss_fn = nn.CrossEntropyLoss()
# 加载模型
model = DigitalNet()
model.load_state_dict(torch.load('digital.pth'))
for image, target in train_loader:
    # 设置输入自动求导
    image.requires_grad = True
    output = model(image)
    # 把目标值修改为1
    target[::] = 1
    loss = loss_fn(output, target)
    model.zero_grad()
    loss.backward()
    # loss对image的梯度
    image_grad = image.grad.data
    # 对image进行修改
    adversarial_x = fgsa_attack(image, .2, image_grad)
    # 对攻击数据预测
    output = model(adversarial_x)
    grid = utils.make_grid(adversarial_x, normalize=True)
    with torch.no_grad():
        grid = grid.cpu().numpy().transpose((1, 2, 0))
        print(output.argmax(dim=1).cpu().numpy().reshape((8, 8)))
        plt.imshow(grid)
        plt.show()
    break

这里做的就是把目标值改为了1,并且调整了fgsa_attack的epsilon值,得到的攻击图像如下:

模型对图像的预测结果为:

[[3 0 1 1 4 8 1 1]
 [1 1 1 1 3 6 1 9]
 [0 1 1 1 1 1 1 1]
 [1 1 8 1 0 1 1 1]
 [5 1 1 1 1 0 1 1]
 [1 1 1 1 3 4 8 1]
 [1 1 1 9 0 8 4 1]
 [0 4 1 1 9 1 5 9]]

虽然结果并非全为1,但是预测结果为1的数量远多于真实为1的数量,这表明此次攻击是成功的。

五、总结

神经网络虽然非常强大,但是对神经网络的理解仍是一个待解决的问题。由于神经网络非常庞大,我们难以把握每一个细节,很难确定网络如何推理出结果,正因为此,一个看似训练良好的模型在应用的实际任务时会出现很多离奇现象。只有理解这些离奇现象为何会发生,才能更好地理解模型,并改进模型。

因为现在大多数网络都是使用梯度下降来更新模型,因此梯度是攻击网络的一个很好的突破点。在上面对网络进行了两种攻击,看似都非常有效。但是白盒攻击的前提是我们能够知道网络具体结构,对网络有完全的控制能力,但是在实际情况中这并不常见,因此也不用过于担心自己的网络会被攻击。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/876690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Node.js学习笔记-04

这第九章也是个大重点 九、玩转进程 Node在选型时决定在V8引擎之上构建,也就意味着它的模型与浏览器类似。 本章关于进程的介绍和讨论将会解决如下两个问题: 单进程单线程并非完美,如今CPU基本均是多核的,真正的服务器&#xf…

2022美亚杯个人赛复现

复现一下2022美亚杯 目录 1 全局搜索 2 UNIX时间戳 3 4 5 6 7 谷歌邮箱 8 谷歌邮箱数据库 9 10 查找URL 的ip 11 12 13 14 15 16 17 18 19 20 21 分析 waze导航 22 23 查看苹果手机接受照片的方式 24 25 26 27 查找备忘录上锁问文件 28 29 30 …

【Sklearn】基于随机森林算法的数据分类预测(Excel可直接替换数据)

【Sklearn】基于随机森林算法的数据分类预测(Excel可直接替换数据) 1.模型原理1.1 模型原理1.2 数学模型 2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果 1.模型原理 随机森林(Random Forest)是一种集成学习方法…

基于dbn+svr的交通流量预测,dbn详细原理

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN+SVR的交通流量预测 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN+SVR用于交通流量预测…

ML在2023年最成功的案例:ControlNet

一、说明 这里说的 ControlNet不是工业控制的控制网络,而是深度学习的神经网络植入某些控制环节,它是 2023 年 ML 领域最大的成功案例之一。这是一种简单,可解释的方式来对扩散模型的输出施加影响的模型。 二、ControlNet 是什么?…

【学习FreeRTOS】第7章——FreeRTOS临界段代码保护及调度器挂起与恢复

1.临界段代码保护简介 临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,适用场合如: 外设:需严格按照时序初始化的外设:IIC、SPI等等系统:系统自身需求用户:用户…

p7付费课程笔记7:G1 GC

目录 前言 什么是G1 GC? 重要语义讲解 标记过程 注意事项 适用场景分析 应用建议 问题 常用配置参数 前言 上次我们讲了CMS GC, 这次我们讲解G1 GC;在开始之前我们要思考下我们为什么学G1 GC?学习后有什么好处? 成为更好的Java开…

安达发APS|生产计划排产软件助力加工制造业智能化转型

随着全球经济一体化的不断深入,市场竞争日益激烈,加工制造企业面临着巨大的生存压力。在这种情况下,企业对于生产计划的精细化管理需求日益迫切。为了适应这一市场需求,安达发推出了专门针对加工企业的APS生产计划排产软件&#x…

四、Linux中cd、pwd以及相对/绝对路径和特殊路径符

1、cd命令: cd命令可以切换当前工作目录,基础语法是: cd [linux路径] (1)、打开Linux的命令提示行,当前工作目录是home,输入“cd /”,可以切换到根目录下,在根目录下输…

限制编辑下的PDF可以转换其他格式吗?这2个方法可行

我们知道,PDF可以通过设置“限制编辑”来保护文件不被随意更改,那PDF设置了“限制编辑”还可以转换其他格式吗? 如果PDF设置的是禁止任何更改的“限制编辑”,那PDF菜单【转换】界面下的格式选项就会呈现灰色状态,无法…

不要服务器和技术代码,怎么做新生录取查询系统?

作为一名老师,我了解学生和家长们对录取情况的关注和期待,所以学校公布录取情况表是一项至关重要的工作。在这篇文章中,我将与大家分享学校公布录取情况表的步骤和流程,以帮助大家更好地了解录取情况。 首先,学校会对…

JS代码混淆加密有什么用?

JS加密、JS混淆,有这些用: 1、前端JS代码,如果不加密,它人可以随便copy、任意修改。自己写的代码,可以轻易成为别人的成果。 对JS代码混淆加密,则可以防止这种他人随意白嫖的问题,代码是自己辛…

你知道什么是Curriculum Training模型吗

随着深度学习技术的飞速发展,研究人员在不断探索新的训练方法和策略,以提高模型的性能和泛化能力。其中,Curriculum Training(课程学习)模型作为一种前沿的训练方法,引起了广泛的关注和研究。本文将深入探讨…

Leetcode链表篇 Day2

203. 移除链表元素 - 力扣(LeetCode) 1.暴力移除:分删除的为头结点和不为头节点 while删除头节点时:直接从下一个结点开始,headhead->next while不是头节点时:从head开始遍历(需记录的为 前继结点pre) 虚…

Nature子刊 |肠道宏病毒组揭示百岁老人长寿秘诀

发表期刊:nature microbiology 发表时间:2023 影响因子:28.3 DOI: 10.1038/s41564-023-01370-6 研究背景 衰老是一种不可逆转的自然过程,随着年龄的增长,机体诸多方面出现功能性下降,与衰老相关的疾病&a…

uniapp一套代码实现多端运行

一、为何使用uniapp uni-app 是一个使用 Vue.js 开发所有前端应用的开源框架,开发者编写一套代码,可发布到 iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)等…

第5章:神经网络

神经元模型 上述定义的简单单元即为神经元模型。 多层网络 误差逆传播算法 标准BP算法:参数更新非常频繁,可能出现抵消现象。积累BP算法:下降到一定程度上,进行下一步会非常缓慢。 过拟合 早停:划分训练集和验证集…

运维监控学习笔记8

在服务器端,我们添加了nginx-server的主机: 在解决Error问题的过程中,我还通过zabbix_get这个命令进行了测试,发现是没有的,后来确认是在web页面配置的过程中,我输错了密码。 yum install zabbix-getzabbi…

电脑怎么修改图片大小尺寸?

电脑怎么修改图片大小尺寸?图片作为我们工作和办公中常用的文件,承载了许多元素和重要内容。而在一些软件和设备应用的过程中,可能会对图片的尺寸有一定的要求,需要我们将图片尺寸进行修改、调整。同时,我们经常在一些…

HDMI接口的PCB布局布线要求

高清多媒体接口(High Definition Multimedia Interface),简称:HDMI,是一种全数字化视频和声音发送接口,可以发送未压缩的音频及视频信号。随着技术的不断提升,HDMI的传输速率也不断的提升&#…