AI 安全之对抗样本入门 (4):深度学习基础知识 1.1.4

阅读数:18 2019 年 11 月 30 日 14:52

AI安全之对抗样本入门(4):深度学习基础知识 1.1.4

(反向传递与优化器)

内容简介
第 1 章介绍了深度学习的基础知识,重点介绍了与对抗样本相关的梯度、优化器、反向传递等知识点。
第 2 章介绍了如何搭建学习对抗样本的软硬件环境,虽然 GPU 不是必需的,但是使用 GPU 可以更加快速地验证你的想法。
第 3 章概括介绍了常见的深度学习框架,从 TensorFlow、Keras、PyTorch 到 MXNet。
第 4 章介绍了图像处理领域的基础知识,这部分知识对于理解对抗样本领域的一些常见图像处理技巧非常有帮助。
第 5 章介绍了常见的白盒攻击算法,从基础的 FGSM、DeepFool 到经典的 JSMA 和 CW。
第 6 章介绍了常见的黑盒攻击算法。
第 7 章介绍了对抗样本在目标识别领域的应用。
第 8 章介绍了对抗样本的常见抵御算法,与对抗样本一样,抵御对抗样本的技术也非常有趣。
第 9 章介绍了常见的对抗样本工具以及如何搭建 NIPS 2017 对抗防御环境和轻量级攻防对抗环境 robust-ml,通过这章读者可以了解如何站在巨人的肩膀上,快速生成自己的对抗样本,进行攻防对抗。

深度学习训练过程如图 1-7 所示。

在深度学习模型里面,经常需要使用梯度算法,针对损失函数的反馈不断调整各层的参数,使得损失函数最小化。在训练阶段,真实值就是样本对应的真实标签,预测值就是机器学习模型预测的标签值,这些都是明确的,所以损失函数是可以定义和计算的。机器学习模型训练的过程就是不断调整参数追求损失函数最小的过程。梯度可以理解为多元函数的指定点上升的坡度,假设多元函数可以表示为 f(x,y),那么对应的梯度的定义为:

f(x,y)=(δf(x,y)δx,f(x,y)y)

可见梯度可以用偏导数来定义,通常损失函数就是这个多元函数,特征向量就可以看成这个多元函数的某个点。在训练过程中,针对参数的调整可以使用梯度和学习率来定义,其中学习率也叫作学习步长,物理含义就是变量在梯度方向上移动的长度,学习率是一个非常重要的参数,学习率过大会导致损失函数的震荡难以收敛,过小会导致计算缓慢,目前还没有很成熟的理论来推倒最合适的学习率,经验值是 0.001~0.1。以 α 表示学习率,那么迭代更新参数 x 的方法为:

xk+1=xk+xkα

AI安全之对抗样本入门(4):深度学习基础知识 1.1.4

图 1-7 深度学习训练过程

在求函数的最大值时,我们会向梯度向上的方向移动,使用加号,也称为梯度向上算法。如果我们想求函数的最小值,则需要向梯度向下的方向移动,使用减号,也称为梯度下降算法,比如求损失函数最小值时,对应迭代求解的方法为:

xk+1=xk+xkα

我们通过一个非常简单的例子演示这个过程,假设我们只有一个变量 x,对应的损失函数定义为:

f(x)=x2+2

根据梯度的定义,可以获得对应的梯度为:

f(x)=f(x)x=2x

我们随机初始化 x,将学习率设置为 0.1,整个过程如下:

复制代码
def demo():
import random
a=0.1
x=random.randint(1,10)
y = x * x + 2
index=1
while index < 100 and abs(y-2) > 0.01 :
y=x*x+2
print "batch={} x={} y={}".format(index,x,y)
x=x-2*x*a
index+=1

整个迭代过程最多 100 步,由于我们预先知道函数的最小值为 2,所以如果当计算获得的函数值非常接近 2,我们也可以提前退出迭代过程,比如绝对值相差不超过 0.01。最后果然没让我们失望,在迭代 20 次后就找到了接近理论上的最小点:

复制代码
batch=14 x=0.329853488333 y=2.10880332377
batch=15 x=0.263882790666 y=2.06963412721
batch=16 x=0.211106232533 y=2.04456584141
batch=17 x=0.168884986026 y=2.02852213851
batch=18 x=0.135107988821 y=2.01825416864
batch=19 x=0.108086391057 y=2.01168266793
batch=20 x=0.0864691128455 y=2.00747690748

Keras 里面提供相应的工具返回 loss 函数关于 variables 的梯度,variables 为张量变量的列表,这里的 loss 函数即损失函数:

复制代码
from keras import backend as K
k.gradients(loss, variables)

Keras 也提供了 function 用于实例化一个 Keras 函数,inputs 是输入张量的列表,其元素为占位符或张量变量,outputs 为输出张量的列表:

复制代码
k.function(inputs, outputs, updates=[])

常用的优化器包括 SGD、RMSprop 和 Adam。

  1. SGD

SGD 即随机梯度下降法,是最基础的优化方法。普通的训练方法需要重复不断地把整套数据放入神经网络中训练,这会消耗大量计算资源。SGD 则会把数据拆分后再分批不断地放入神经网络中来计算。每次使用批数据,虽然不能反映整体数据的情况,不过却在很大程度上加速了神经网络的训练过程,而且也不会丢失太多准确率1

1 https://ptorch.com/news/54.html

SGD 支持动量参数,支持学习衰减率,函数的定义如下:

复制代码
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)

其中比较重要的参数如下:

  • lr:学习率。
  • momentum:动量参数。
  • decay:每次更新后的学习率衰减值。
  1. RMSprop

RMSprop 是面对递归神经网络时的一个良好选择,函数的定义如下:

复制代码
keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=1e-06)

其中比较重要的参数如下:

  • lr:学习率。
  • epsilon:大于或等于 0 的小浮点数,防止除 0 错误。
  1. Adam

Adam 是一种可以替代 SGD 的一阶优化算法,它能基于训练数据迭代地更新神经网络权重,是目前最受欢迎的优化算法之一,定义如下:

复制代码
keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)

其中比较重要的参数如下:

  • lr:学习率。
  • epsilon:大于或等于 0 的小浮点数,防止除 0 错误。

下面我们以迭代生成对抗样本的例子来感性认识一下不同优化器的计算收敛速度,代码路径为:

复制代码
https://github.com/duoergun0729/adversarial_examples/code/1-case1-pytorch.ipynb

首先,定义全局变量,其中 adam_original_loss、sdg_original_loss 和 RMSprop_original_loss 分别代表迭代过程中不同优化算法对应的损失函数的值:

复制代码
adam_original_loss = []
sdg_original_loss=[]
RMSprop_original_loss=[]
epoch_range=[]

加载测试图片,并缩放到长和宽均为 224:

复制代码
#获取计算设备,默认是 CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
#图像加载以及预处理
image_path="../picture/cropped_panda.jpg"
orig = cv2.imread(image_path)[..., ::-1]
orig = cv2.resize(orig, (224, 224))
img = orig.copy().astype(np.float32)

对图像数据进行标准化处理,由于攻击的图像分类模型是基于 ImageNet2012 数据集进行预训练的,因此需要使用 ImageNet2012 数据集特有的均值 mean 和标准差 std 进行标准化:

复制代码
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
img /= 255.0
img = (img - mean) / std
img = img.transpose(2, 0, 1)
img=np.expand_dims(img, axis=0)
img = Variable(torch.from_numpy(img).to(device).float())

实例化 alexnet 模型并加载预训练的参数。在使用迭代优化的过程中,整个模型的参数不变化,反向传递仅调整原始图像的内容:

复制代码
#使用预测模式主要影响 dropout 和 BN 层的行为
model = models.alexnet(pretrained=True).to(device).eval()
#获取分类标签
label=np.argmax(model(img).data.cpu().numpy())
print("label={}".format(label))
#图像数据梯度可以获取
img.requires_grad = True
#设置为不保存梯度值,自然也无法修改
for param in model.parameters():
param.requires_grad = False

使用定向攻击,攻击目标的标签值为 288,最大迭代次数为 100:

复制代码
loss_func = torch.nn.CrossEntropyLoss()
epochs=100
target=288
target=Variable(torch.Tensor([float(target)]).to(device).long())

迭代优化的计算过程中,根据预测结果与定向攻击目标计算损失值,并通过手工调用反向传递过程,更新原始图像:

复制代码
for epoch in range(epochs):
# 梯度清零
optimizer.zero_grad()
# forward + backward
output = model(img)
loss = loss_func(output, target)
label=np.argmax(output.data.cpu().numpy())
adam_original_loss+=[loss]
epoch_range += [epoch]
#手工调用反向传递计算,更新原始图像
loss.backward()
optimizer.step()

分别实例化不同的优化器,记录 100 次迭代优化过程中损失值的变化,如图 1-8 所示,当使用相同的学习速率对同一图片进行迭代优化生成定向攻击样本时,RMSprop 和 Adam 明显快于 SGD:

复制代码
fig, ax = plt.subplots()
ax.plot(np.array(epoch_range), np.array(adam_original_loss), 'b--',
label='Adam')
ax.plot(np.array(epoch_range), np.array(RMSprop_original_loss), 'b-',
label='RMSprop')
ax.plot(np.array(epoch_range), np.array(sdg_original_loss), 'b:',
label='SGD')
legend = ax.legend(loc='best', shadow=True, fontsize='large')
legend.get_frame().set_facecolor('#FFFFFF')
plt.xlabel('Iteration Step ')
plt.ylabel('Loss')
plt.show()

AI安全之对抗样本入门(4):深度学习基础知识 1.1.4

图 1-8 相同条件下不同优化算法的收敛速度

AI安全之对抗样本入门(4):深度学习基础知识 1.1.4

购书地址 https://item.jd.com/12532163.html?dist=jd

评论

发布