第 3 章 · 第 4 讲 / 共 7 讲
对数几率回归
名字叫回归,干的是分类。核心只有一件事:找一个光滑的「翻译器」,把任意实数变成概率。
能解释为什么单位阶跃函数不能用、sigmoid 好在哪;能说清几率和对数几率;能讲出极大似然的直觉、式 (3.26) 那个「开关」技巧,以及式 (3.27) 是怎么来的、为什么它是凸的。
到这里,3.2 已经能预测实数了。可分类任务的答案只有 0 和 1。缺的不是模型,是一个「翻译器」——这一讲就用上一讲结尾那个接口,把回归改造成分类器。
3.3 对数几率回归名字叫回归,干的是分类
上一节解决的是"输出一个实数"。可如果任务是分类呢?比如判断"是不是好瓜",答案是 0 或 1。
原书在这里只用了一句话转折:"答案蕴涵在式 (3.15) 的广义线性模型中:只需找一个单调可微函数将分类任务的真实标记 y 与线性回归模型的预测值联系起来。"
把这句话拆开:线性模型算出来的 z = wTx + b 是个实数(可能是 −7.3,可能是 0.02,也可能是 1.4),而我们要的 y 只能是 0 或 1。所以缺的不是模型,缺的是一个"翻译器"——也就是式 (3.15) 里那个 g-1。
先想想"最理想的翻译器"长什么样
最符合直觉的翻译显然是:z 是正的,就判 1;z 是负的,就判 0。这就是单位阶跃函数(unit-step function,也叫 Heaviside 函数):
0.5, 若 z = 0;
1, 若 z > 0 式 (3.16)
书里的说法:预测值 z 大于零就判为正例,小于零判为反例,恰好等于临界值(0)时可以任意判别。看着很完美,对吧?
但它有个致命问题:不连续。在 z = 0 这一点上,函数值"啪"地一下从 0 跳到 1,中间没有过渡。而广义线性模型要求 g 单调可微——不可导,就没法求梯度,没法用优化算法去训练它。
所以原书说:希望找一个"替代函数"(surrogate function)——能在一定程度上近似阶跃函数,同时单调可微。
对数几率函数:一个"圆滑版"的阶跃
这个替代品就是对数几率函数(logistic function):
它就是深度学习里那个 sigmoid。书里对 sigmoid 的解释是"形似 S 的函数",对数几率函数是其中最重要的代表(第 5 章讲神经网络时会再遇到它)。
动手试试
注意最后两个数永远相等——这就是式 (3.19):模型把"对数几率"直接等于了 z。
它有三个性质,正好对上需求:
- z = 0 时 y = 0.5(和阶跃函数在临界点的 0.5 对上了);
- z → +∞ 时 y → 1;z → −∞ 时 y → 0(两头饱和);
- 在 z = 0 附近变化最陡——"最陡"意味着最敏感,不确定性最大的地方它给出最干脆的判断。
把它当作 g-1 代进式 (3.15):
"对数几率回归"这个名字是怎么来的
把式 (3.18) 变形一下(两边取倒数、移项、再取对数)。这一步书里是"类似于式 (3.14),式 (3.18) 可变化为",我们来真的变一次:
⟹ 1 + e−z = 1/y
⟹ e−z = (1−y)/y
⟹ ez = y/(1−y)
⟹ z = ln( y/(1−y) )
而 z 就是 wTx + b,所以:
接着把三个术语串起来(这三个名字务必分清):
| 名字 | 式子 | 人话 |
|---|---|---|
| 几率(odds) | y / (1−y) | 把 y 看作"样本是正例的可能性",那 1−y 就是反例的可能性。这个比值就是"正例的可能性是反例的几倍"。若 y=0.8,几率就是 4 倍。 |
| 对数几率 (log odds / logit) |
ln[ y/(1−y) ] | 对几率再取对数。取对数是为了把 (0, +∞) 这个区间"拉直"成整个实数轴,这样才能用 wTx+b 去拟合它。 |
| 对数几率回归 (logistic regression) |
式 (3.18) | 因为式 (3.18) 实际上是在用线性回归的预测结果去逼近真实标记的对数几率,所以得名。 |
① 它不是"回归"。虽然名字里有回归,但它是一种分类学习方法。原书特意强调了这一点。别被名字骗了。
② "对数几率函数" ≠ "对数函数"。书里专门加了个注:注意对数几率函数与 ln(·) 不同。前者是 1/(1+e−z) 这个 S 形曲线,后者是我们熟悉的 ln。名字像,东西完全两回事。
另外书里解释了这个译名的来历:有文献译作"逻辑回归",但中文"逻辑"和 logistic / logit 的本义相去甚远,所以本书意译为"对数几率回归",简称对率回归。
为什么它好用:书里给了三条
- 直接对分类可能性建模,无需事先假设数据分布。对比一下:朴素贝叶斯(第 7 章)要先假设"数据服从某种分布",如果假设错了,模型就跟着错。对率回归不假设分布,所以"避免了假设分布不准确所带来的问题"。
- 得到的是近似概率预测,不是硬邦邦的类别。它输出 0.87,你就知道"这个样本有 87% 的可能是好瓜"。这对很多需要概率辅助决策的任务很有用——比如医疗诊断里,0.51 和 0.99 虽然都判"有病",但处置方式完全不同。
- 目标函数是任意阶可导的凸函数。数学性质好,现有的数值优化算法都能直接用。
怎么把 w 和 b 求出来:极大似然法
先把式 (3.18) 里的 y 明确成"类后验概率估计",也就是 p(y=1 | x)——"在已知 x 的条件下,它是正例的概率"。于是式 (3.19) 可以重写为:
由于两者加起来必须等于 1,解一下就能分别写出它们:
注意这两个式子和 (3.18) 长得几乎一样,只是分母的指数上少了个负号——因为 (3.18) 那个式子是给"y=1"用的,(3.24) 是 1 减掉它。
想象你在猜一枚硬币的重量分布。你已经掷了 10 次,结果是 7 正 3 反。极大似然法的思路是:既然这事已经发生了,那就找一个参数,让"发生这件事"的概率最大。
放到这里:训练集里每个样本的真实标签 yi 是我们已经看到的既成事实。我们要调的 w、b,应该让"看到这批标签"这件事的概率最大。
所以目标就是最大化"每个样本属于它真实类别的概率"的连乘(独立事件同时发生的概率 = 各自概率相乘)。取对数把连乘变成连加(好算,且不改变最大值的位置),就得到下式。
书里一句话点明:"即令每个样本属于其真实标记的概率越大越好。" 这就是式 (3.25) 的全部含义。
一个式子同时写两种情况的技巧
麻烦在于:yi 有时候是 1,有时候是 0,难道要分两种情况写?书里用一个很巧的办法绕过去了。先做记号简化:
又是"把 b 吸收进去"那一招(和 3.2 一模一样)。再令 p1(x̂; β) 表示判为正例的概率,p0 = 1 − p1 表示反例的概率。于是:
当 yi = 1 时:第二项被 (1−1)=0 干掉,只剩 1 · p1 = p1。✓
当 yi = 0 时:第一项被 0 干掉,只剩 1 · p0 = p0。✓
所以这一个式子自动"选"了正确的那一项。为什么要这么写?因为后面求导时,一个有统一表达式的函数才好求导;分情况讨论就得写两遍,非常难看。这个技巧在机器学习里到处都是,值得记住。
化简成最终形状(书里跳了,这里补上)
把式 (3.26) 代入式 (3.25),用式 (3.23)(3.24) 展开。分两种情况看 ln p 长什么样:
若 yi = 0: ln p0 = ln 11 + eβTx̂ = 0 − ln(1 + eβTx̂i)
看这两行——它们的区别只在于前面那一项在 yi=1 时是 βTx̂i,在 yi=0 时是 0。那正好就是 yi · βTx̂i。所以两种情况可以合并成一行:
最大化这个和,等于最小化它的相反数(加个负号、翻个个儿)。于是得到:
式 (3.27) 就是深度学习里天天出现的 binary cross-entropy(二元交叉熵),也叫 log loss(对数损失)。很多人学到这里会有"啊,原来就是它"的感觉。
所以以后看到 PyTorch 里的 BCEWithLogitsLoss,可以放心地理解成:这就是西瓜书的式 (3.27)。
怎么解:没有闭式解,只能迭代
注意一个本质区别:3.2 的线性回归有闭式解(代公式一步算出),而式 (3.27) 因为那个 ln(1+e(·)) 的存在,没法直接解出 β。只能一步步逼近。
好消息是它是"关于 β 的高阶可导连续凸函数",所以梯度下降法、牛顿法这些经典数值优化算法都能用。原书以牛顿法为例:
这个公式别硬背,看它的结构:新位置 = 老位置 − (曲率)-1 × (斜率)。
梯度下降是"跟着坡度往低处挪一小步"。牛顿法更聪明:它在当前点用一个二次函数(一个碗)去近似目标函数,然后一步跳到这个碗的碗底。因为用了二阶信息(曲率),所以步子更准、收敛更快。
代价是每轮都要算二阶导矩阵(Hessian)并求逆,计算量大。样本多、维度高时就不划算了。
书里给了一阶导和二阶导:
一阶导那个式子有个特别漂亮的读法:"误差 × 特征"。括号里 yi − p1 就是"真实标签减去预测概率",也就是这一条样本的误差;乘以 x̂i 就是"这条样本的特征"。所有样本的"误差×特征"加起来,就是梯度。误差大的样本对参数的拉动更大——这和直觉完全一致。
二阶导那个式子也值得看一眼:因为 p1(1−p1) 永远 ≥ 0(概率在 0 和 1 之间),所以这个 Hessian 是正定的。正定意味着什么?意味着这个碗是"开口朝上"的——确实是个凸问题,牛顿法不会跑偏。
书里有一道习题:"试证明,对于参数 w,对率回归的目标函数 (3.18) 是非凸的,但其对数似然函数 (3.27) 是凸的。"
这句话的意思要拎清:式 (3.18) 那个 y = 1/(1+e−(wTx+b)) 本身,作为 w 的函数是"非凸"的(它是 S 形,有上有下)。但我们真正优化的不是它,而是式 (3.27) 那个对数似然——后者是凸的。
所以"对率回归是凸优化问题"这句话,必须限定在"用对数似然做目标"这个前提下。说漏了就不严谨。
随堂自测 · 3.3
为什么不能直接把单位阶跃函数当作广义线性模型里的 g-1?
式 (3.15) 要求 g 单调可微。阶跃函数在 z=0 处直接跳变,导数不存在,因此无法求梯度、无法优化。输出只有 0 和 1 恰恰是它的优点(正是我们要的),不是问题;而且它在 0 点附近不是"平缓",是"剧烈跳变"。
本讲小结
- 阶跃函数理想但不连续不可导,所以换成 sigmoid:形状像阶跃,光滑,两头饱和。
- 把式子反过来就是 ln[y/(1−y)] = wTx+b——用线性模型去拟合「对数几率」,名字由此而来。
- 极大似然:让「看到这批真实标签」的概率最大。式 (3.26) 用一个乘法把两种情况合成一个式子。
- 式 (3.27) 就是深度学习里的 log loss / 交叉熵;它是凸的(而 3.18 本身不是),所以牛顿法能解。
下一讲:线性判别分析。同样是二分类,但它走的是完全不同的另一条路——不算概率,改找「最好的观察角度」。
卡住了就直接问我 —— 把没看懂的那一句原样抄给我,我单独展开讲,不用客气。