论文地址:https://arxiv.org/pdf/2211.05826.pdf
相关博客
【自然语言处理】【文本生成】CRINEG Loss:学习什么语言不建模
【自然语言处理】【文本生成】使用Transformers中的BART进行文本摘要
【自然语言处理】【文本生成】Transformers中使用约束Beam Search指导文本生成
【自然语言处理】【文本生成】Transformers中用于语言生成的不同解码方法
【自然语言处理】【文本生成】BART:用于自然语言生成、翻译和理解的降噪Sequence-to-Sequence预训练
【自然语言处理】【文本生成】UniLM:用于自然语言理解和生成的统一语言模型预训练
【自然语言处理】【多模态】OFA:通过简单的sequence-to-sequence学习框架统一架构、任务和模态

近些年来,随着 Transformers \text{Transformers} Transformers的崛起,语言模型和对话代理变的越来越强大,以至于可以进行各种交互。然而,采用标准的语言模型训练、缩放模型尺寸和大量的训练数据仍然有大量的问题无法解决。特别地,模型仍然会遭受毒性和偏见的影响、缺乏连贯性以及不能解决用户的意图。相反,越来越多的工作正在研究如何将这些信息融入训练目标中,从而超越标准的语义建模目标函数。
在本文中,研究一种设定:训练集中包含一组正样本(语言模型训练中经常使用)和一组负样本(模型不应该生成的)。本文提出了新的学习方法,
CRINGE(ContRastive Iterative Negative GEneration)
\text{CRINGE(ContRastive Iterative Negative GEneration)}
CRINGE(ContRastive Iterative Negative GEneration)损失函数,作为一种在这种数据上训练且概念简单的方法,其易于实现并比现有的方法性能好。正样本使用常用的最大似然方法。负样本的训练则是受Jiang et al.启发并进行泛化的"监督对比学习目标函数",并且不需要任何架构的改变,仅对损失函数进行最小的改变。上图1展示了
CRINGE
\text{CRINGE}
CRINGE损失函数在单个负序列上的概念图。由于该损失函数允许在负样本上高效的训练,通过在模型自己生成样本分类上训练来迭代的改善生成结果。
本文在三个具有正、负训练样本的任务上展示了该方法的效果。三个任务分别是:完全生成任务 (safe generation) \text{(safe generation)} (safe generation)、矛盾避免任务 (contradiction avoidance) \text{(contradiction avoidance)} (contradiction avoidance)和开发域任务导向对话任务 ( open-domain task-oriented conversation ) (\text{open-domain task-oriented conversation}) (open-domain task-oriented conversation)。此外,本文与广泛的baseline进行了比较。一般来说, CRINGE \text{CRINGE} CRINGE损失函数单次迭代就超过了大多数的baselines。在本文提出的迭代方式上应用 CRINGE \text{CRINGE} CRINGE,可能看到额外的改善,并在所有的三个任务上带来最优的效果。
使用负样本来训练语言模型有几种实现方式。Welleck et al.提出了unlikelihood训练,其在训练目标中添加了一个额外的项,降低了负token相较于其他token的概率。他们表明这是检索语言模型中重复生成的有效方法。Jiang et al.也提出了对比学习目标函数来缓解文本退化。他们认为将前面
M
M
M个上下文token与正标签对比,有助于避免不期望的token,相较于unlikelihood训练。这个方法在减少正样本生成时的重复上很有效,但是其不能在任意的负样本上工作,因为其对任意给定的负token需要正确的正token。本文当前的工作就是受该方法的启发,并将其泛化到负样本训练上。
一个完全不同但流行的从负样本中学习的方法是训练一个分类器或者重排模型。本文中,并不是去更新模型参数,而是训练一个额外的模型来评估生成。通过使用语言模型来生成多个候选,重排器去决定那个候选分数最高。Nie et al.训练重排器以避免生成矛盾的问题。Nakano et al.发现在某些场景中重排可能优于强化学习。
模型指导方法,像 PnP \text{PnP} PnP、 GeDi \text{GeDi} GeDi、 FUDGE \text{FUDGE} FUDGE、 PACER \text{PACER} PACER,在解码过程中对每个token都使用该模型,而不是在最终的生成上使用额外的模型。因此,第二个模型期望的属性被用于指导语言模型的生成。近期的 DIRECTOR \text{DIRECTOR} DIRECTOR模型不使用第二个模型,在相同的架构上共享语言模型和分类指导头。其在多个任务上都工作的很好,但是缺点是需要架构变化并且不能够轻易的应用在现有的模型上。
Unlikelihood训练通过在模型自己的生成样本上训练来迭代的改善重复生成的问题。在人类偏好上训练语言模型已经成功应用在摘要、对话等任务上。Lu et al.使用生成的样本训练一个消除不期望行为的语言模型。他们标记和量化模型生成的样本,并通过在序列前添加奖励token来执行条件训练。
InstructGPT
\text{InstructGPT}
InstructGPT模型来自人类反馈的强化学习来将语言模型对齐至instructions。
CRINGE \text{CRINGE} CRINGE损失函数是一种在正、负序列上训练模型的方法。对于正样本,利用常见的最大似然方法。负样本则通过语言模型预测的top token之一和序列的每个token进行对比。上图展示了如何在负样本序列上进行训练。
更正式的来说,最终的优化目标由两项组成:正样本序列的交叉熵和负样本序列的
CRINGE
\text{CRINGE}
CRINGE。前者就是标准的使用方法,对于来自正样本序列
x
x
x的token
x
t
x_t
xt:
L
C
E
t
=
−
log
p
(
x
t
∣
x
<
t
)
=
−
log
exp
(
s
x
t
)
∑
x
′
∈
V
exp
(
s
x
′
)
LtCE=−logp(xt|x<t)=−logexp(sxt)∑x′∈Vexp(sx′)
其中
s
i
s_i
si表示模型为token
i
i
i输出的logit。对于负样本,将序列中的每个token与正token进行对比。在训练数据中通常会提供负样本序列,但是不知道对于给定序列中的负token,其可替换的正token应该是哪个。本文的方法是从模型当前的top-k预测中采样(若负token在top-k中,则忽略负token)。这里,通过模型预测的top-k logits的softmax构造的类别分布进行采样。选择对比loss为
L
C
r
t
=
−
log
exp
(
s
+
)
exp
(
s
+
)
+
exp
(
s
x
t
−
)
=
l
o
g
(
1
+
exp
(
s
x
t
−
−
s
+
)
)
LtCr=−logexp(s+)exp(s+)+exp(sx−t)=log(1+exp(sx−t−s+))
其中,
s
x
t
−
s_{x_t^-}
sxt−表示提供的负样本标注token的logit分数,
s
+
s^+
s+从模型top-k预测中采样的正token。该方法背后的直觉是使用模型作为近似的数据库来提供可选的正token。或者,从另一个角度看,确保已知的负token排名低于模型认为排名top-k的token。算法1提供了单次预测的伪代码。
算法1:对于单个负token的 CRINGE \text{CRINGE} CRINGE损失函数
需要:一个token索引序列 x < t \textbf{x}_{
x<t 、一个标注的负token x t − x_t^- xt−、一个生成模型 f θ f_\theta fθ、一个标量 k k k;
- 将序列输入至模型并得到每个token的分数,即 s ← f θ ( x < t ) \textbf{s}\leftarrow f_\theta(\textbf{x}_{
s←fθ(x<t) ;- 获得索引不为 ≠ x t − \neq x_t^- =xt−的top-k token预测分数,即 [ s + , 1 , … , s + , k ] ← t o p k ( s ) [s^{+,1},\dots,s^{+,k}]\leftarrow topk(\textbf{s}) [s+,1,…,s+,k]←topk(s)
- 从上面的集合中采样正token,即 s + ← softmax_sample ( [ s + , 1 , … , s + , k ] ) s^+\leftarrow\text{softmax\_sample}([s^{+,1},\dots,s^{+,k}]) s+←softmax_sample([s+,1,…,s+,k]);
- 拼接正、负token分数,并按照 L C r t \mathcal{L}_{C_r}^t LCrt计算损失函数,即 l o s s ← n n . C r o s s E n t r o p y L o s s ( [ s + , s x t − , 0 ] ) loss\leftarrow nn.CrossEntropyLoss([s^+,s_{x_t^-},0]) loss←nn.CrossEntropyLoss([s+,sxt−,0]);
为了同时在正负样本上进行训练,采用两个损失函数的加权求和
L
=
L
C
E
+
α
L
C
r
\mathcal{L}=\mathcal{L}_{CE}+\alpha\mathcal{L}_{C_r}
L=LCE+αLCr
其中,
α
\alpha
α是控制负样本影响的超参数。
CRINGE
\text{CRINGE}
CRINGE损失函数很容易实现,并仅需要在损失函数上进行简单的修改。
提出的 CRINGE \text{CRINGE} CRINGE损失函数允许在正样本和负样本上高效的训练模型。这使得通过学习自己生成的分类来迭代改善模型成为可能。这里遵循简单的策略,完成模型训练,标记模型在训练集上的生成,然后使用增强的训练集重复这个过程。模型生成的标签可以在整个循环中人工评估来获得,本文提出在原始的正、负样本上训练分类器,并使用自动标记的样本,类似于强化学习中的奖励模型。使用以下流程:
在本文的实验中,发现即使仅迭代两轮也能够带来显著的效果改善。伪代码如算法2所示。
算法2: CRINGE \text{CRINGE} CRINGE训练循环
需求:一个具有正、负序列的数据集 D 0 \mathcal{D}_0 D0,一个生成模型 f θ f_\theta fθ,一个为文本序列分配二元标签的函数 c c c(一个人或者一个在 D 0 \mathcal{D}_0 D0上训练的分类器)
- 使用原始数据集初始化 D \mathcal{D} D,即 D ← D 0 \mathcal{D}\leftarrow\mathcal{D}_0 D←D0;
- for Iterations=1,N do
- 使用 CRINGE \text{CRINGE} CRINGE损失函数在数据集 D \mathcal{D} D上训练模型直至收敛,即 f θ ← t r a i n ( D ) f_\theta\leftarrow train(\mathcal{D}) fθ←train(D)
- 使用模型从原始训练数据集 D 0 \mathcal{D}_0 D0的提示(prompts)生成序列,即 x ^ ← f θ ( D 0 ) \hat{\textbf{x}}\leftarrow f_\theta(\mathcal{D}_0) x^←fθ(D0)
- 将模型生成的序列标注伪正样本或者负样本,即 y ^ ← c ( x ^ ) \hat{\textbf{y}}\leftarrow c(\hat{\textbf{x}}) y^←c(x^)
- 将标注完的模型生成序列添加至现有数据集中,即 D ← D + ( x ^ , y ^ ) \mathcal{D}\leftarrow\mathcal{D}+(\hat{\textbf{x}},\hat{\textbf{y}}) D←D+(x^,y^)