语言模型(Language Model,LM),即给出一句话的前k个token,希望它可以预测第k+1个token是什么,即给出一个第k+1个token可能出现的概率的分布 p ( x k + 1 ∣ x 1 , x 2 , . . . , x k ) p(x_{k+1}|x_1,x_2,...,x_k) p(xk+1∣x1,x2,...,xk)。
本文试图理清Language Modeling的评估指标基本计算过程和指标含义,目的有二:
(1)本文介绍的评估指标对于机器学习或者NLP从业人员来说是比较常用,但未必系统学习过、未必能说清楚这些指标之间的关系和指标本身的含义,掌握这些知识不管是对工作、求职面试都是有帮助的。
(2)企图设计新的指标为本人进一步的AGI模型的建模研究做铺垫,这是主要的。
在language modeling中,要评价训练模型的好坏,可以通过度量模型预测序列Q和真实序列P的分布之间的差异来评价。相对熵的定义恰好就是度量两个分布差异的,相对熵又称Kullback-Leibler散度(简称KL散度)。那实际language modeling及其他机器学习问题中为什么很少用相对熵而用交叉熵呢?用关于信息熵、相对熵、交叉熵的定义、关系及推导可以参考本人另一篇文章《度量方法总结》。此处不再详细介绍,下面直接给出几个主要计算公式。
信息熵H(P(X)):
H ( P ( X ) ) = E [ f ( x i ) ] = − ∑ i n P ( x i ) l o g P ( x i ) \begin {alignedat}{2} H(P(X))&=E[f(x_i)] \\ &=-\sum_i^n P(x_i) log\ P(x_i) \end {alignedat} H(P(X))=E[f(xi)]=−i∑nP(xi)log P(xi)
相对熵 D K L ( P ( X ) ∣ ∣ Q ( X ) ) D_{KL}(P(X)||Q(X)) DKL(P(X)∣∣Q(X)):
D K L ( P ( X ) ∣ ∣ Q ( X ) ) = ∑ i = 1 n P ( x i ) l o g ( P ( x i ) Q ( x i ) ) \begin {alignedat}{2} D_{KL}(P(X)||Q(X)) = \sum_{i=1}^nP(x_i)log(\frac{P(x_i)}{Q(x_i)}) \end {alignedat} DKL(P(X)∣∣Q(X))=i=1∑nP(xi)log(Q(xi)P(xi))
交叉熵 H ( P ( X ) , Q ( X ) ) H(P(X),Q(X)) H(P(X),Q(X)):
H ( P ( X ) , Q ( X ) ) = − ∑ i = 1 n P ( x i ) l o g ( Q ( x i ) ) \begin {alignedat}{2} H(P(X),Q(X)) = −∑_{i=1}^{n}P(x_i)log(Q(x_i)) \end {alignedat} H(P(X),Q(X))=−i=1∑nP(xi)log(Q(xi))
三者之间的关系:
D K L ( P ( X ) ∣ ∣ Q ( X ) ) = − H ( P ( X ) ) + H ( P ( X ) , Q ( X ) ) \begin {alignedat}{2} D_{KL}(P(X)||Q(X)) =-H(P(X))+H(P(X),Q(X)) \end {alignedat} DKL(P(X)∣∣Q(X))=−H(P(X))+H(P(X),Q(X))
引用香农在信息论中的一句话:“Entropy can be interpreted as the average number of bits required to store the information in a variable.”这句话意思就是说当我们的熵,也就是Entropy越小时,存储信息需要的bits数越少,因为信息的结构更有序了。
从bits数视角看:
信息熵H(P(X))是存储真实序列P所需的平均bit数;
相对熵 D K L ( P ( X ) ∣ ∣ Q ( X ) ) D_{KL}(P(X)||Q(X)) DKL(P(X)∣∣Q(X))是基于预测的Q序列来编码真实序列P所需要的额外bit数;
交叉熵 H ( P ( X ) , Q ( X ) ) H(P(X),Q(X)) H(P(X),Q(X))是存储真实序列P所需的平均bit数与基于预测的Q序列来编码真实序列P所需要的额外bit数的总和。
从评价语言/模型的角度说,如果基于预测的Q序列来编码真实序列P所需要的额外bit数越少,即相对熵越小,那么模型从从真实序列P中学习到的知识也越多。
从优化的角度说,相对熵和交叉熵都能达到相同的优化效果,但交叉熵计算更简单一些。
在language modeling中,BPC也是衡量预测序列Q和真实序列P之间差异的指标,只不过做了一下平均。BPC和Cross-Entropy之间有如下计算关系:
BPC = 1 T ∑ i = 1 T H ( P ( X ) , Q ( X ) ) \text{BPC} = \frac {1} {T} \sum^T_{i=1} H(P(X),Q(X)) BPC=T1i=1∑TH(P(X),Q(X))
也就是说BPC/BPW是cross-entropy对字符/单词长度T的平均,可以很容易地得出它的信息论含义:
基于预测的Q序列来编码P序列所需要的额外bit数在句子长度上的平均,也就是平均每一个字母/单词需要额外的bit数。这也是它名字的由来,也是我们为什么要从存储bit数量的角度来解释Cross-Entropy。
注意:T这里是字符/单词的个数,不是token的数量,因为不同编码方式下token可能是不一样的。
PPL也是用来衡量语言模型好坏的指标。它主要是根据每个词来估计一句话出现的概率,并用句子长度n作normalize,PPL的计算公式推导:
PPL = 2 H ( P ( X ) , Q ( X ) ) = 2 1 n ∑ i = 1 n H i ( P ( X ) , Q ( X ) ) = 2 1 n ∑ i = 1 n ∑ j = 1 n − P ( x j ) log 2 Q ( x j ) = 2 − 1 n ∑ i = 1 n log 2 Q ( x i ) = ( ∏ i = 1 n Q ( x i ) ) − 1 n = p ( x 1 , x 2 , . . x n ) − 1 n \begin {align} \text{PPL} &=2^{H(P(X),Q(X))} \\ &= 2^{\frac{1}{n} \sum_{i=1}^n {H_i(P(X),Q(X))}}\\ &= 2^{\frac{1}{n} \sum_{i=1}^n \sum_{j=1}^n -P(x_j) \log_2^{Q(x_j)}}\\ &= 2^{-\frac{1}{n} \sum_{i=1}^n \log_2^{Q(x_i)}}\\ &= (\prod_{i=1}^n{Q(x_i)})^{-\frac{1}{n}}\\ &= p(x_1,x_2,.. x_n) ^{-\frac{1}{n}}\\ \end {align} PPL=2H(P(X),Q(X))=2n1∑i=1nHi(P(X),Q(X))=2n1∑i=1n∑j=1n−P(xj)log2Q(xj)=2−n1∑i=1nlog2Q(xi)=(i=1∏nQ(xi))−n1=p(x1,x2,..xn)−n1
这里有几点细节需要注意理解:
所以,语言模型评估时我们可以用perplexity大致估计训练效果,作出判断和分析,但它不是完全意义上的标准,具体问题还是要具体分析。
def evaluate(model, val_dataloader, config):
model.eval()
total_val_loss = 0
with torch.no_grad():
for step, batch in enumerate(val_dataloader):
batch[0].clone().detach().to(config.device)
batch[1].clone().detach().to(config.device)
loss, logits = model(batch[0], token_type_ids=None, attention_mask=(batch[0] > 0), labels=batch[1])
if isinstance(model, torch.nn.DataParallel):
loss = loss.mean()
total_val_loss += loss.mean().item()
average_val_loss = total_val_loss / len(val_dataloader)
perplexity = math.exp(average_val_loss)
return loss, perplexity
[1].Evaluation Metrics for Language Modeling,2019.10.18
[2].Perplexity of fixed-length models.
[3].一文搞懂Language Modeling三大评估标准, 硅谷谷主
[4].https://zhuanlan.zhihu.com/p/114432097
[5].https://blog.csdn.net/qq_41775769/article/details/121796159