你应该有多惊讶?
从一种人人都懂的感受开始:惊讶。如果朋友告诉你“今早太阳升起来了”,你几乎什么都没学到——你本来就确定。如果他说“沙漠里下雪了”,你会立刻坐直;那太不可能了,所以它携带了大量新信息。信息论把这种直觉变成一个数字。规则简单又符合直觉:一个结果*越*不可能,它真的发生时就*越*令人惊讶——携带的信息也*越*多。
于是我们想要一个量:当概率很小时它很大,当结果确定时它衰减到零。能办到的选择就是概率为p的结果的惊讶度:惊讶 = log(1/p)。当p = 1(确定)时,惊讶为log(1) = 0——毫无新意。当p极小时,1/p极大,于是惊讶很大。取以2为底的对数,就以比特为单位来度量它:一个你用一次公平掷硬币(p = 1/2)就能猜中的结果,恰好携带1比特。
为什么用对数,而不直接用1/p?因为惊讶应该能*累加*。如果两件互不相关的事都发生了,它们的概率相乘(p·q),但直觉上你的总惊讶应该是各自惊讶之*和*。对数正是那个把乘法变成加法的函数:log(1/(p·q)) = log(1/p) + log(1/q)。正是这一条性质,使得对数在这一隅数学里无处不在——你将看到,也包括你训练分类器所用的损失。
熵:平均意义上的惊讶
单个结果有它的惊讶度。而一整个[[random-variable|随机变量]]——比如明天的天气,或一句话里的下一个词——有*许多*可能的结果,每个都有自己的概率。最自然的概括,就是长期来看你会感到的平均惊讶:用每个结果出现的频率,给它的惊讶度加权求平均。这个平均值就是[[information-entropy|熵]]。熵越高,信息源越不可预测;熵越低,就越可预测。
这正好接回本阶前面讲过的[[expectation-and-variance|期望]]:熵不过是惊讶的*期望值*。具体地,对于概率为p1、p2、……的各结果,熵 = pi · log(1/pi) 之和。一枚公平硬币的熵为1比特——在两个选项之间最不确定。一枚99%朝上的偏硬币熵要小得多,因为多数时候你早就知道答案。一枚永远正面朝上的硬币熵为0:没有任何可学的。
交叉熵:当你的模型猜错了概率
熵假设你知道真实概率。但模型并不知道——它只有*猜测*。把真实分布记作p(自然实际怎么做),把模型猜出的分布记作q(你的模型预测什么)。交叉熵问的是:如果你用q的概率来度量惊讶,而结果其实是按p到来的,那么你平均会感到多少惊讶?它就是“你相信q、而现实遵循p”所付出的平均惊讶。
关键事实来了,而且很温和:交叉熵*总是不小于*真实的熵,且只有当q与p完全吻合时才与熵相等。任何不吻合都要多付惊讶。所以,如果你想让模型的q映照现实的p,你只需把交叉熵*往下压*——把它逼向由真实熵设下的地板。这正是训练循环所做的事。
剩下的那段差距——交叉熵减去真实的熵——有它自己的名字:[[kl-divergence|KL散度]]。可以把它读作“用错分布所多付的*额外*惊讶”。当q = p时KL为零,q越偏离它越大,所以它表现得像一段从“你的信念”到“真相”的距离。一个诚实的提醒:它*不是*真正的距离——KL(p, q)一般不等于KL(q, p)。它是不对称的,这正是人们说“散度”而非“度量”的原因。
为什么交叉熵是分类问题的默认损失
现在收获来了。一个分类器输出标签上的[[probability-distribution|概率分布]]——通常经由[[softmax|softmax]],它把原始分数压成一组为正、加起来等于1的数。这就是模型的q。而单个带标签样本的真相p简单到极点:正确类别上概率为1,其余全为0(一个“独热”向量)。把这个p代入交叉熵,几乎一切都消掉了:单个样本的损失就变成 log(1 / q_正确)——模型分给正确答案的那份惊讶。
把它读成一种激励。如果模型既自信又正确(q_正确接近1),惊讶接近0——几乎不罚。如果它既自信又*错误*(q_正确接近0),损失会朝无穷飙升。对数狠狠惩罚自信的错误,奖励有分寸的自信。在整个数据集上最小化这个损失,就是“训练一个分类器”的日常含义——在二分类里,它和你在评估中会遇到的[[log-loss|对数损失]]是同一回事,也是[[logistic-regression|逻辑回归]]内部的引擎。
它之所以是*默认*而非众多选项之一,还有更深的理由。最小化交叉熵在数学上等同于[[maximum-likelihood-estimation|极大似然]]——选择那组让观测数据最可能出现的参数,正是本阶前面引入的原则。所以交叉熵不是某人随手挑中的公式;它就是“让训练数据尽可能可能”写成式子后的样子。这份出身,加上它的梯度与softmax配合得极好,正是它成为[[loss-function|损失函数]]首选反应的原因。
# one labeled example, C classes # logits : raw model scores, length C # y : index of the true class q = softmax(logits) # model's predicted distribution, sums to 1 loss = -log(q[y]) # = log(1 / q[y]) = surprise on the true class # confident & right -> q[y]~1 -> loss~0 # confident & wrong -> q[y]~0 -> loss huge # average loss over the dataset is what training minimizes
在实战中读懂它——以及一个提醒
现在你会到处认出这些观念。语言模型就是通过最小化“下一个词元是什么?”上的交叉熵来训练的——而[[perplexity|困惑度]],那个领域的招牌数字,不过是交叉熵取指数后,报成一个有效分支因子(“模型困惑的程度,就好像它在N个词里均匀乱猜”)。困惑度更低、交叉熵更低、平均惊讶更少:这是同一个量的三种视角。
还要记得前面说的KL的不对称——它在悄悄塑造行为。当模型把概率放在真相为零之处时去罚它(一个方向的KL),和当它漏掉了确实会发生的结果时去罚它(另一个方向的KL),是不一样的。用交叉熵训练实际上用的是其中一个方向,这往往让模型倾向于“覆盖住真相”,而不是把全部赌注押在一个答案上。你不需要公式也能保留这个直觉:惊讶是货币,而一个好模型在诚实允许的范围内,花得越少越好。
这就是本阶最后一站的完整脉络。惊讶是log(1/p)。熵是平均惊讶——一个源中无法回避的不确定性。交叉熵是相信错误分布所付出的平均惊讶,KL散度是其中可以避免的那部分多余,而一个分类器的训练,就是把交叉熵往下挤——这不过是极大似然换了件外衣。手握向量、概率、微积分,如今再加上信息,你已经可以满怀真正的信心去读这条阶梯的其余部分了。