Skip to content

CLM

因果语言模型 Causal Language Modeling

因果语言模型,这里的思想是预测一个给定句子中的蒙面标记,但与MLM不同,这个模型被只考虑发生在它左边的单词来做同样的事情(理想情况下,这个可以是左的或者右的,想法是使它是单向的)。

设一句话被分成 token 序列

x=(x1,x2,,xT).

CLM 想做的事,是给整句话一个概率:

pθ(x1,x2,,xT).

但直接一次性建模整个联合分布很难,所以它用一个最自然的办法:概率链式法则。也就是把整句话的概率拆成“一个接一个预测”的条件概率:

pθ(x1,x2,,xT)=t=1Tpθ(xtx<t),

其中 x<t 表示第 t 个位置之前的所有 token。对第一个 token,可以把它理解成“给定一个起始符 BOS”或者“空上下文”。这就是 GPT 类模型最核心的数学形式:整句概率被分解成一连串“下一个 token 概率”。

一个例子

我 今天 去 北京

那么它的概率就被拆成

p();p(今天);p(我,今天);p(北京我,今天,去).

也就是说,CLM 学的根本不是“整句长什么样”,而是:

每走到一个位置,只根据左边已经出现的内容,预测下一个 token。

CLM 的损失函数

既然模型要尽量给真实句子更高概率,那最直接的训练目标就是最大化训练集上真实句子的概率。设训练集是 D,那目标就是

maxθxDlogpθ(x).

把上面的链式分解代进去:

logpθ(x)=logt=1Tpθ(xtx<t)t=1Tlogpθ(xtx<t).

于是最大化对数似然,就等价于最大化

xDt=1Tlogpθ(xtx<t).

深度学习里通常写成“最小化负对数似然”,所以 CLM 的 loss 就是

LCLM=xDt=1Tlogpθ(xtx<t).

这就是为什么大家常说:CLM 本质上就是 next-token prediction 的交叉熵。 因为对每个位置,它都在做一次“从整个词表里选对下一个 token”的 softmax 分类。GPT-2 论文就是从这种链式分解出发来定义语言建模的。

如果再把 softmax 展开,就更具体了。设模型在位置 t 输出一个词表 logits 向量 ztR|V|,那么对任意词 vV

pθ(xt=vx<t)=exp(zt,v)uVexp(zt,u).

真实答案是 xt 时,这个位置的 loss 就是

tCLM=logpθ(xtx<t)logexp(zt,xt)uVexp(zt,u).

把所有位置加起来,就是整句的 CLM loss。你会发现,它和普通分类的 cross-entropy 长得一模一样,只不过这里是“每个位置都做一次分类”。这也解释了为什么训练代码里经常是“输入右移一位、label 左移一位”:模型看前缀,标签是下一个 token。

为什么 CLM 一定要用 causal mask

上面这个公式里最关键的限制是:

pθ(xtx<t)

它只能看左边,不能看右边未来的 token。不然就等于考试偷看答案了。

Transformer 论文里对 decoder 说得很明确:decoder 的 self-attention 只能让位置 t 看到自己以及更早的位置;对未来位置的连接,会在 softmax 前被 mask 成 ,这样就保住了 autoregressive(自回归)性质。

所以可以把 CLM 的结构理解成:

  • 数学上:做的是 p(x)=tp(xtx<t)
  • 结构上:用 causal mask 强制第 t 个位置只能看左边
  • 训练上:每个位置都预测下一个 token
  • 推理上:一个 token 一个 token 往后生成

4. 为什么 CLM 天生适合“生成”

因为 CLM 训练时学的,和生成时做的,是同一件事。

训练时,它学:

给定前缀,预测下一个 token。

推理时,它也做:

先根据前缀采样一个新 token,再把这个 token 接到后面,继续预测下一个。

所以它可以自然地一步一步生成:

x1x2x3xT.

而且由于它直接建模了整句的联合概率,句子的对数概率也能直接写成

logpθ(x)=t=1Tlogpθ(xtx<t).

这就是为什么 CLM 的 perplexity 很自然:

PPL(x)=exp(1Tt=1Tlogpθ(xtx<t)).

GPT-2 论文也明确把语言模型评测写成“平均负对数概率的缩放或指数化版本”。