第 3 章 · 第 4 讲 / 共 7 讲

对数几率回归

名字叫回归,干的是分类。核心只有一件事:找一个光滑的「翻译器」,把任意实数变成概率。

约 25 分钟 1 个自测 教材 §3.3

这一讲你会拿到什么

能解释为什么单位阶跃函数不能用、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 函数):

y = 0, 若 z < 0;
0.5, 若 z = 0;
1, 若 z > 0
式 (3.16)

书里的说法:预测值 z 大于零就判为正例,小于零判为反例,恰好等于临界值(0)时可以任意判别。看着很完美,对吧?

但它有个致命问题:不连续。在 z = 0 这一点上,函数值"啪"地一下从 0 跳到 1,中间没有过渡。而广义线性模型要求 g 单调可微——不可导,就没法求梯度,没法用优化算法去训练它。

所以原书说:希望找一个"替代函数"(surrogate function)——能在一定程度上近似阶跃函数,同时单调可微。

对数几率函数:一个"圆滑版"的阶跃

这个替代品就是对数几率函数(logistic function):

y = 11 + e−z 式 (3.17)

它就是深度学习里那个 sigmoid。书里对 sigmoid 的解释是"形似 S 的函数",对数几率函数是其中最重要的代表(第 5 章讲神经网络时会再遇到它)。

z y 1 0.5 0 单位阶跃函数(不连续) 对数几率函数 (光滑的 S 形) z = 0 时 y = 0.5
红色虚线是单位阶跃函数:z 一过 0,输出就从 0 跳到 1,中间是断的。蓝色实线是对数几率函数:整体形状像阶跃,但在 z = 0 附近是连续且陡峭地过渡的,两头逐渐贴近 0 和 1。

动手试试

概率 y = σ(z) = 0.500 | 几率 y/(1−y) = 1.00 | 对数几率 = 0.0
注意最后两个数永远相等——这就是式 (3.19):模型把"对数几率"直接等于了 z。
拖一拖你会发现:z 在 0 附近时,y 对 z 很敏感(稍微一动就变很多);而 z 很大或很小时,y 几乎不动(饱和了)。这个"中间敏感、两头迟钝"的形状,正是它比硬邦邦的阶跃函数好用的原因。

它有三个性质,正好对上需求:

把它当作 g-1 代进式 (3.15):

y = 11 + e−(wTx + b) 式 (3.18)

"对数几率回归"这个名字是怎么来的

把式 (3.18) 变形一下(两边取倒数、移项、再取对数)。这一步书里是"类似于式 (3.14),式 (3.18) 可变化为",我们来真的变一次:

y = 1 / (1 + e−z)
⟹  1 + e−z = 1/y
⟹  e−z = (1−y)/y
⟹  ez = y/(1−y)
⟹  z = ln( y/(1−y) )

而 z 就是 wTx + b,所以:

ln y1 − y = wTx + b 式 (3.19)
概率 y 只能在 (0, 1) 里待着 0 1 0.5 对数几率 ln[ y/(1−y) ] 铺满整条实数轴 −6−4 −20 246 左边挤成一团:概率差一点点,其实是"几乎不可能"和"绝不可能"的天壤之别 右边拉开了:这才配得上用一条直线去拟合
为什么非要取对数?因为 wTx+b 的取值范围是整条实数轴,而概率被关在 (0,1) 的小房间里。取对数几率就是把这间小房子拉成一条大马路——同一个"0.5",拉直之后正好落在原点 0,两边对称展开。这就是"用线性模型去拟合对数几率"的几何含义。

接着把三个术语串起来(这三个名字务必分清):

名字式子人话
几率(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 的本义相去甚远,所以本书意译为"对数几率回归",简称对率回归。

为什么它好用:书里给了三条

  1. 直接对分类可能性建模,无需事先假设数据分布。对比一下:朴素贝叶斯(第 7 章)要先假设"数据服从某种分布",如果假设错了,模型就跟着错。对率回归不假设分布,所以"避免了假设分布不准确所带来的问题"。
  2. 得到的是近似概率预测,不是硬邦邦的类别。它输出 0.87,你就知道"这个样本有 87% 的可能是好瓜"。这对很多需要概率辅助决策的任务很有用——比如医疗诊断里,0.51 和 0.99 虽然都判"有病",但处置方式完全不同。
  3. 目标函数是任意阶可导的凸函数。数学性质好,现有的数值优化算法都能直接用。

怎么把 w 和 b 求出来:极大似然法

先把式 (3.18) 里的 y 明确成"类后验概率估计",也就是 p(y=1 | x)——"在已知 x 的条件下,它是正例的概率"。于是式 (3.19) 可以重写为:

ln p(y=1 | x)p(y=0 | x) = wTx + b 式 (3.20)

由于两者加起来必须等于 1,解一下就能分别写出它们:

p(y=1 | x) = ewTx+b1 + ewTx+b 式 (3.23)
p(y=0 | x) = 11 + ewTx+b 式 (3.24)

注意这两个式子和 (3.18) 长得几乎一样,只是分母的指数上少了个负号——因为 (3.18) 那个式子是给"y=1"用的,(3.24) 是 1 减掉它。

极大似然法在干什么(这是全章最值得理解的一步)

想象你在猜一枚硬币的重量分布。你已经掷了 10 次,结果是 7 正 3 反。极大似然法的思路是:既然这事已经发生了,那就找一个参数,让"发生这件事"的概率最大。

放到这里:训练集里每个样本的真实标签 yi 是我们已经看到的既成事实。我们要调的 w、b,应该让"看到这批标签"这件事的概率最大。

所以目标就是最大化"每个样本属于它真实类别的概率"的连乘(独立事件同时发生的概率 = 各自概率相乘)。取对数把连乘变成连加(好算,且不改变最大值的位置),就得到下式。

ℓ(w, b) = ∑i=1m ln p(yi | xi; w, b) 式 (3.25)

书里一句话点明:"即令每个样本属于其真实标记的概率越大越好。" 这就是式 (3.25) 的全部含义。

一个式子同时写两种情况的技巧

麻烦在于:yi 有时候是 1,有时候是 0,难道要分两种情况写?书里用一个很巧的办法绕过去了。先做记号简化:

β = (w; b),  x̂ = (x; 1)  ⟹  wTx + b = βTx̂

又是"把 b 吸收进去"那一招(和 3.2 一模一样)。再令 p1(x̂; β) 表示判为正例的概率,p0 = 1 − p1 表示反例的概率。于是:

p(yi | xi; w, b) = yi p1(x̂i; β) + (1 − yi) p0(x̂i; β) 式 (3.26)
看穿这个式子:它是一个开关

当 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 = 1:  ln p1 = ln eβTx̂1 + eβTx̂ = βTx̂i − ln(1 + eβTx̂i)
若 yi = 0:  ln p0 = ln 11 + eβTx̂ = 0 − ln(1 + eβTx̂i)

看这两行——它们的区别只在于前面那一项在 yi=1 时是 βTx̂i,在 yi=0 时是 0。那正好就是 yi · βTx̂i。所以两种情况可以合并成一行:

ln p(yi | x̂i; β) = yiβTx̂i − ln(1 + eβTx̂i)

最大化这个和,等于最小化它的相反数(加个负号、翻个个儿)。于是得到:

ℓ(β) = ∑i=1m ( − yiβTx̂i + ln(1 + eβTx̂i) ) 式 (3.27)
你可能在别处见过它

式 (3.27) 就是深度学习里天天出现的 binary cross-entropy(二元交叉熵),也叫 log loss(对数损失)。很多人学到这里会有"啊,原来就是它"的感觉。

所以以后看到 PyTorch 里的 BCEWithLogitsLoss,可以放心地理解成:这就是西瓜书的式 (3.27)。

怎么解:没有闭式解,只能迭代

注意一个本质区别:3.2 的线性回归有闭式解(代公式一步算出),而式 (3.27) 因为那个 ln(1+e(·)) 的存在,没法直接解出 β。只能一步步逼近。

好消息是它是"关于 β 的高阶可导连续凸函数",所以梯度下降法、牛顿法这些经典数值优化算法都能用。原书以牛顿法为例:

βt+1 = βt − ( ∂2ℓ(β) / ∂β∂βT )−1 · ∂ℓ(β) / ∂β 式 (3.28)

这个公式别硬背,看它的结构:新位置 = 老位置 − (曲率)-1 × (斜率)。

牛顿法的直觉

梯度下降是"跟着坡度往低处挪一小步"。牛顿法更聪明:它在当前点用一个二次函数(一个碗)去近似目标函数,然后一步跳到这个碗的碗底。因为用了二阶信息(曲率),所以步子更准、收敛更快。

代价是每轮都要算二阶导矩阵(Hessian)并求逆,计算量大。样本多、维度高时就不划算了。

书里给了一阶导和二阶导:

∂ℓ(β) / ∂β = − ∑i=1m x̂i ( yi − p1(x̂i; β) ) 式 (3.30)
∂2ℓ(β) / ∂β∂βT = ∑i=1m x̂ix̂iT p1(x̂i; β)(1 − p1(x̂i; β)) 式 (3.31)

一阶导那个式子有个特别漂亮的读法:"误差 × 特征"。括号里 yi − p1 就是"真实标签减去预测概率",也就是这一条样本的误差;乘以 x̂i 就是"这条样本的特征"。所有样本的"误差×特征"加起来,就是梯度。误差大的样本对参数的拉动更大——这和直觉完全一致。

二阶导那个式子也值得看一眼:因为 p1(1−p1) 永远 ≥ 0(概率在 0 和 1 之间),所以这个 Hessian 是正定的。正定意味着什么?意味着这个碗是"开口朝上"的——确实是个凸问题,牛顿法不会跑偏。

考点(对应习题 3.2)

书里有一道习题:"试证明,对于参数 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 本身不是),所以牛顿法能解。

下一讲:线性判别分析。同样是二分类,但它走的是完全不同的另一条路——不算概率,改找「最好的观察角度」。

卡住了就直接问我 —— 把没看懂的那一句原样抄给我,我单独展开讲,不用客气。