引言
对抗训练对于NLP来说,是一种非常好的上分利器,所以,非常有必要加深对对抗训练的认识。
一、对抗训练一般原理
小学语文课上,我们都学习过《矛与盾》这篇课文,
从辩证唯物史观角度来看,矛与盾并没有严格意义上的谁更厉害,谁一直占优。矛盾着的双方又同一又斗争,双方力量此长彼消,不断前进,从而推动事物发展。这也就是对抗训练。
1.对抗样本
两句话,只是部分英文单词发生了改变,但是在我们看来,含义还是几乎不变的,但是就是这种变化,基于BERT的文本分类模型对句子的情感分类居然是完全相反的。
根据研究,我们发现InferSent MultiNLI
模型、ESIM MultiNLI
模型、BERT MultiNLI
模型在SNLI
数据集上面准确率为84%以上,但是在对抗文本上,不管是传统的深度网络还是BERT模型,准确率都只有个位数。尽管BERT模型经过微调可以在不同的下游任务得到好的结果,但仍然是非常容易受到攻击的(模型不鲁棒)。
那么,如何使得模型更加鲁棒呢?比如:
- 我们可以对数据进行处理,将对攻击的防御放到数据处理过程中
- 我们也可以对模型输出的向量表征做一些转换,将防御放在模型的输出端
- 我们也可以将防守放在模型本身上来
二、对抗训练的经典算法
lan Goodfellow提出对抗训练方法,它的思想是在训练时,在原始的输入样本中加上扰动(对抗样本),我们用对抗样本来进行模型的训练,使得模型更加鲁棒
扰动的计算方式定义为:求得模型损失,对于 x x x求梯度,对所求的梯度经过符号函数处理,在乘以一个系数 ϵ \epsilon ϵ
这种对抗训练的方法叫做Fast Gradient Sign Method (FGSM)。
对抗训练其实可以当做正则化,减少模型的过拟合,提升模型的泛化性能。FGSM对抗训练方法应用与CV,cv的输入都是图像,图像输入模型时为RGB三个通道上的像素值,它的输入本身就是连续的,但是NLP的输入是离散的单词序列。那么,我们应该如何在NLP模型上定义对抗训练?
虽然NLP的输入都是离散的单词序列,但是会经过embedding转变成低维空间上的向量表征,我们可以将embedding后的向量表征当成上述对抗训练模型中的 x x x。lan Goodfellow在2017年提出了在连续的embedding上做扰动。
扰动的计算方式为:
- x x x表示文本序列的embedding vectors
这种对抗训练的方法叫做Fast Gradient Method (FGM)。FGM通过一步,就移动到对抗样本上,如果梯度太大,可能会导致扰动过大,对模型造成误导。
FGM对抗训练方法一步得到对抗样本,容易导致扰动过大。Projected Gradient Descent
(PGD)方法限定了扰动的范围,对抗样本并不是一步就得到了,而是通过沿着不同点的梯度走了多步之后再去得到。
其中,
- 小步走:如果沿着梯度走的比较远,则通过投影的方式,投影到球面s上;
- 多步走:生成一个对抗样本是走多步得到的;
这种对抗训练的方法叫做Projected Gradient Descent(PGD)。
三、对抗训练代码实现
1.FGM
class FGM():
"""
定义对抗训练方法FGM,对模型embedding参数进行扰动
"""
def __init__(self, model, epsilon=0.25,):
# BERT模型
self.model = model
# 求干扰时的系数值
self.epsilon = epsilon
self.backup = {
}
def attack(self, emb_name='word_e