第一次看到画出来的神经网络,一堆小圆圈和箭头,我以为它和传统统计学是两回事。后来我得亲手写一个逻辑回归,于是冒出了这节课的笨问题:逻辑回归是不是神经网络?
简短的回答是:是的。逻辑回归就是只有一个神经元的神经网络。它们不是长得像,也不是亲戚,而是同一个模型,只是有两个名字。既然是同一个神经元,真正有意思的问题就变了:大型网络到底多了什么?什么时候值得为它付出代价?
选一张牌吧:♣ 适合从零开始,♦ 适合知道函数或平均数是什么的人,♠ 适合想看数学记法的人。随时可以换。
一个神经元,两个名字
新手
假设你想猜明天会不会下雨。你看看线索:有云,有风,下午出了太阳。这些线索的分量不一样:云很重要,风有一点影响,太阳则是减分。把每条线索的分量加起来,这个总和就会推动一根指针,从“肯定不会”指向“肯定会”。
这杆秤就是逻辑回归,一种用来回答“是或否”问题的传统统计方法。它同时也是一个神经元,也就是搭建神经网络用的那块积木。同一杆秤,两个名字。
最重要的部分还没讲:学习。一开始,这杆秤不知道每条线索该有多重。你给它看很多过去的日子,每次它猜错,就骂它一顿,它越有把握,骂得越狠。为了少挨骂,秤会一点一点地调整分量。这杆秤还有一个让人安心的特点:不管从哪里开始,最后总会得到同样的分量。
进阶
逻辑回归由三个部分组成。值得一个个弄清楚,因为每个部分都对应一种不同的失败方式。
1. 加权求和。 数据的每一列乘以一个数,也就是它的权重,再全部加起来,外加一个常数。我们把结果叫作得分。模型知道的一切都在这里:如果信号藏在两列的组合里,或者藏在一条曲线里,除非你事先把它构造好交给模型,否则模型看不到。
2. sigmoid。 这是一条 S 形曲线,把任何得分压到 0 和 1 之间:很负的得分接近 0,很正的接近 1,得分为零时正好是 0.5。选它不是为了好看:假设答案是一枚做了手脚的硬币,而手脚的大小取决于一个加权和,推出来的就是这个形状。所以它的输出可以当作概率来读。
3. 惩罚。 它把概率和正确答案作比较,重罚“很有把握却错了”。行话叫损失,这一种具体叫对数损失或交叉熵。为了学习,模型会看惩罚往哪个方向下降,然后把权重往那个方向挪一点,一遍又一遍:这就是梯度下降。
接下来是改变一切的性质:对逻辑回归来说,惩罚只有一个底。不管怎么往下走,都会到达同一个地方,所以随机种子无关紧要。带隐藏层的网络就没有这个保证了:它有很多山谷,最后落在哪里取决于从哪里出发。
我验证过:scikit-learn 的逻辑回归和手工训练的一个神经元,得到的权重一直到小数点后第三位都相同。一个实用细节:很多库默认会加一个把权重往小里压的“刹车”,如果你想解读权重,就把它关掉。
技术
| ♦ 里的说法 | ♠ 里的写法 |
|---|---|
| 得分 | z = wᵀx + b |
| 权重;常数 | w ∈ ℝᵈ;b(偏置) |
| 把得分压到 0 和 1 之间的 sigmoid | σ(z) = 1/(1 + e⁻ᶻ) |
| 概率 | p = σ(z) = P(y = 1 | x) |
| 做了手脚的硬币 | y ~ Bernoulli(p);logit 连接函数(GLM) |
| 惩罚(损失、对数损失) | BCE = −[y log p + (1 − y) log(1 − p)] |
| 惩罚往哪个方向下降 | −∇L = −Xᵀ(p − y)/n |
| 只有一个底 | 凸函数:∇²L = XᵀSX/n ⪰ 0 |
| 把权重往小里压的刹车 | L2 正则化;sklearn 中 C = 1/λ |
逻辑回归是一个广义线性模型:y ~ Bernoulli(p),使用典型的 logit 连接函数,所以 logit(p) = wᵀx + b,p = σ(wᵀx + b)。sigmoid 并不是设计上的选择,而是伯努利分布典型连接函数的反函数。一个用 σ 作激活函数、用二元交叉熵(BCE)训练的神经元,正是这个模型,似然函数也完全相同。
取平均损失 L(w) = (1/n) Σᵢ BCE(yᵢ, σ(wᵀxᵢ)),梯度为 ∇L = Xᵀ(p − y)/n,Hessian 矩阵为 ∇²L = XᵀSX/n,其中 S = diag(pᵢ(1 − pᵢ))。由于 S 的对角线为正,XᵀSX ⪰ 0:损失是凸的;若 X 满秩,则是严格凸的。所以梯度下降、牛顿法或 IRLS 都会到达同一个最优解。数据线性可分时,最优解不存在(‖w‖ → ∞),需要正则化。
我用不加正则化的 scikit-learn(C=np.inf)和一个用梯度下降训练的神经元做了对比:
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
X, y = make_classification(n_samples=2000, n_features=5,
flip_y=0.1, random_state=0)
clf = LogisticRegression(C=np.inf).fit(X, y)
w, b = np.zeros(5), 0.0
for _ in range(20000):
# 一个神经元:线性 + sigmoid
p = 1 / (1 + np.exp(-(X @ w + b)))
# 对数损失的梯度
w -= 0.5 * X.T @ (p - y) / len(y)
b -= 0.5 * (p - y).mean()
# 权重相同
print(clf.coef_[0].round(3), w.round(3))用 scikit-learn 1.9.1,两边的权重一直到小数点后第三位都相同。这不是这组数据碰巧如此:它们是同一个凸优化问题,走两条路解出来而已。
我曾经纠结了一个星期,以为必须在统计和深度学习之间二选一。结果发现,我早就在做只有一个神经元的深度学习了。
谁来制造特征
新手
既然最后那杆秤是一样的,大型神经网络到底特别在哪里?在于秤之前发生的事。
想象一口锅。如果食材已经切好,直接倒进去就行。表格形式的数据就是这样:年龄、金额、访问次数。每一列本身就是一条有意义的线索,秤可以直接称。
一张照片则是一整个土豆。单独一个彩色小点,说明不了照片里有没有猫。总得有人把照片切成有用的线索,比如“这里有耳朵”或者“这像胡须”。神经网络的层做的正是这件事:它们自己学会怎么切。内行把这些制造出来的线索叫作特征。最后,一切都落进同一口锅:还是前面那杆秤。
进阶
既然最后那个神经元是一样的,深度网络多出来的就是这个神经元之前发生的事。一个回答“是或否”的十层网络,它的最后一层就是一个逻辑回归。区别在于,它的输入不是你的列,而是特征:隐藏层从数据中学到的新组合。
经典的例子是异或:正方形四个角上的四个点,每条对角线上的类别相同、两条对角线的类别相反。一个神经元只会画直线,而没有任何直线能把它们分开。但如果给它一列新数据,两列的乘积,这些点就自动分开了。这一列新数据就是一个特征:要么你手工构造,要么由隐藏层来构造。
这引出了我知道的最有用的经验法则。如果你的数据是表格,而且每一列本来就有含义,好的特征已经存在,隐藏层能补充的很少。如果是像素、音频或文本,任何像素的加权和都看不出一只猫:总得有人来制造特征。制造者可以是用你的数据训练的隐藏层,可以是几百棵把票数加起来的树(在表格上叫梯度提升),也可以是一个已经用全世界数据训练好的模型,你只需要调整它的末端。
一个实用细节:在深度学习库里,网络输出的是没有压缩的得分,sigmoid 放在惩罚的计算里面,这样遇到很大的数也不会算崩。
技术
| ♦ 里的说法 | ♠ 里的写法 |
|---|---|
| 隐藏层 | h = tanh(W⁽¹⁾x + b⁽¹⁾) |
| 它们制造的特征 | h ∈ ℝ⁸:学到的表示 |
| 最后那个神经元 | p = σ(w⁽²⁾ᵀh + b⁽²⁾) |
| 两列的乘积 | x₁x₂ |
| 几百棵把票数加起来的树 | p = σ(Σₖ fₖ(x)),梯度提升 |
| 已经用全世界数据训练好的模型 | 预训练嵌入 + 微调 |
| 没有压缩的得分 | logit z;BCEWithLogitsLoss |
一个 L 层的二分类网络可以写成 p = σ(wᵀφ(x) + b),其中 φ = h⁽ᴸ⁻¹⁾ ∘ … ∘ h⁽¹⁾ 与 w 一起学习。给定 φ,最后一层就是以特征 h 为输入的逻辑回归。如今几乎所有二分类器都是如此:在二分类梯度提升中(XGBoost binary:logistic、LightGBM binary),p = σ(Σₖ fₖ(x)),fₖ 是树;在微调的预训练模型中,φ 就是嵌入。
在异或问题中,x ∈ {−1, 1}²,当 x₁x₂ > 0 时 y = 1:在 (x₁, x₂) 空间里没有超平面能把它分开,但在 (x₁, x₂, x₁x₂) 空间里,超平面 x₁x₂ = 0 就够了。实验室里的隐藏层(8 个 tanh 神经元)不需要任何人告诉它找哪个乘积,也能得到等价的边界,代价是 |θ| = 33 而不是 4,失去凸性,而且 W⁽¹⁾ 再也读不懂。
自己试试。异或和圆环是两个经典例子:没有任何一条直线能把这些点分开。选一组数据和一个模型,然后训练:
这个实验里我最喜欢的是中间那一行。在异或上失败的同一个神经元,只要手工给它两个坐标的乘积,马上就全对了。隐藏层不需要任何人告诉它该找什么,也能到达同样的地方,代价是要调 33 个数而不是 4 个,而且你再也读不懂它学到了什么。
sigmoid 为什么退出了隐藏层
新手
如果网络就是“一排很多杆秤”,那每杆秤都用同样的指针,也就是那条 S 形曲线,似乎理所当然。很多年里大家确实这么做,结果并不好。
网络要学习,就会在末端收到一条消息:“你错了这么多”。这条消息得往回传,从最后一层传到第一层,每一层才能调整自己的权重。这就像传话游戏:每一层用了那条曲线,最多只能用四分之一的音量把消息传下去。传过五个人,消息就只剩不到百分之零点五。传过十个人,连一点声音都没有了,前面几层几乎学不到东西。
解决办法是把中间各层的指针换成另一种:消息为正时,它不会把音量调小。那条 S 形曲线并没有退休,而是去当了门卫。它仍然在网络末端说“88% 是”,也在大语言模型内部决定让多少信息通过。
进阶
如果网络就是“很多逻辑回归神经元叠在一起”,那每层都用 sigmoid 似乎理所当然。很多年里大家确实这么做,结果并不好。
原因在于 sigmoid 的斜率。斜率最大只有 0.25,出现在 S 的正中间;到了两端,曲线已经平了,斜率几乎为零。训练网络时,告诉每个权重该往哪里挪、挪多少的信号(梯度)要从最后一层往第一层算,每经过一层就乘上那一层的斜率:这就是反向传播。连着几层 sigmoid,传到第一层的信号,上限就是 0.25 自乘层数那么多次,这还没算权重把它放大或缩小了多少。
到了 10 层,传到最前面的信号还不到百万分之一。前面几层几乎学不到东西。这就是 Hochreiter 在 1991 年描述的梯度消失问题。实践中也同样糟糕:2010 年,Glorot 和 Bengio 训练了有 5 个隐藏层的网络,测试误差用 sigmoid 是 82.61%,用双曲正切是 27.15%,用双曲正切加更好的初始化是 15.60%。在隐藏层里,sigmoid 让位给了 ReLU:一个让正数原样通过、把负数变成零的函数。
sigmoid 并没有消失,只是换了工作。离开隐藏层这条链,它就不会被自己连乘几十次,而它 0 到 1 的取值范围正好适合表示概率或者充当门。
| 位置 | sigmoid 做什么 |
|---|---|
| “是或否”分类器的输出 | 把最后的得分变成概率。这就是网络末端的逻辑回归 |
| 同时预测多个标签的分类 | 每个类别一个独立的 sigmoid:一张照片可以既是“海滩”又是“日落” |
| LSTM 和 GRU 网络里的门 | 决定记忆中有多大比例能通过,从 0 到 1 |
| LLaMA 和 PaLM 里的 SwiGLU | 一个分支通过 sigmoid 决定另一个分支能通过多少 |
技术
| ♦ 里的说法 | ♠ 里的写法 |
|---|---|
| sigmoid 的斜率 | σ′(z) = σ(z)(1 − σ(z)) |
| 最大只有 0.25 | σ′ ≤ ¼,在 z = 0 处取等号 |
| 告诉每个权重该往哪里挪、挪多少的信号(梯度) | δ⁽ˡ⁾ = ∂L/∂z⁽ˡ⁾;∂L/∂W⁽ˡ⁾ = δ⁽ˡ⁾h⁽ˡ⁻¹⁾ᵀ |
| 每经过一层就乘上那一层的斜率(反向传播) | δ⁽ˡ⁾ = diag(σ′(z⁽ˡ⁾)) W⁽ˡ⁺¹⁾ᵀ δ⁽ˡ⁺¹⁾ |
| 0.25 自乘层数那么多次 | (¼)ⁿ |
| 权重把它放大或缩小了多少 | ‖W⁽ˡ⁾‖(谱范数) |
| 更好的初始化 | Glorot/Xavier:Var(W) = 2/(nᵢₙ + nₒᵤₜ) |
| ReLU | ReLU(z) = max(0, z) |
| 门 | g = σ(Wx + b) ⊙ v |
设 h⁽ˡ⁾ = σ(z⁽ˡ⁾),z⁽ˡ⁾ = W⁽ˡ⁾h⁽ˡ⁻¹⁾ + b⁽ˡ⁾,反向传播给出 δ⁽ˡ⁾ = diag(σ′(z⁽ˡ⁾)) W⁽ˡ⁺¹⁾ᵀ δ⁽ˡ⁺¹⁾,第一层的梯度为 ∂L/∂W⁽¹⁾ = δ⁽¹⁾xᵀ。由于 σ′ = σ(1 − σ) ≤ ¼,有 n 个 sigmoid 层时,‖δ⁽¹⁾‖ ≤ (¼)ⁿ ∏ₗ ‖W⁽ˡ⁾‖ · ‖∂L/∂h⁽ⁿ⁾‖。除非权重的范数能抵消每层 4 倍的衰减,梯度会随深度指数衰减(Hochreiter,1991 年和 1998 年)。如果 |z| 落在尾部,σ′ ≈ 0,上界还要低得多。
Glorot 和 Bengio(AISTATS 2010,表 1)在 Shapeset-3×2 上用 5 个隐藏层做了测量:测试误差用 sigmoid 是 82.61%,用 tanh 是 27.15%,用 tanh 加归一化初始化是 15.60%。这种初始化 Var(W) = 2/(nᵢₙ + nₒᵤₜ) 如今叫作 Xavier 或 Glorot 初始化。此外,σ 不是以零为中心的:0.5 的平均激活值会让更新产生偏差,并使高层饱和。ReLU,即 max(0, z),在 z > 0 时导数为 1,打破了这串小于 ¼ 的因子连乘。
离开深层链条,σ 仍有两个角色:一是作为输出的连接函数 p = σ(z),用于二分类和多标签分类(每个类别一个 σ,而不是 softmax);二是作为乘法门。在 LSTM 中,输入门是 iₜ = σ(Wᵢ[hₜ₋₁, xₜ] + bᵢ)。在 SwiGLU(Shazeer,2020)中,FFN(x) = (Swish(xW) ⊙ xV)W₂,其中 Swish(u) = u·σ(βu):LLaMA 和 PaLM 在每个 Transformer 块里都用它。
sigmoid 跟我一样:被赶出了隐藏层,最后在每个大语言模型里当了门卫。
什么时候用什么
做决定时几乎从来不看“问题有多复杂”,而是看你的数据是什么形式、你有多少带正确答案的样本、谁需要理解每一个决定。这棵决策树三个层次都适用:
新手
剥一个橙子,用不着买一台厨房机器人。机器人很贵,装起来费时间,出了问题你也不知道为什么。只有要给全村做面包时,它才划算。
模型也是一样。如果你的数据是表格,而且每一列本来就有含义,那杆老秤通常就够了,而且你还能解释每一个决定:“我说不行,是因为这一列”。如果你的数据是照片、声音或文字,就得有人来切菜,这时候用神经网络才划算。有一条建议永远适用:先试试那杆秤。几分钟就好,它会告诉你,机器人要赢多少才值得。
进阶
表格数据:经典模型通常就够了。 Christodoulou 等人综述了 71 项临床预测研究,其中有 282 组逻辑回归和机器学习的对比。他们用 AUC 衡量表现,也就是模型给一个正例打的分高于一个负例的概率。在偏倚风险低的对比里(也就是做得规范的研究),两者没有差别。只有在偏倚风险高的研究里,机器学习才占上风。我读的是论文摘要,不是全文。在不需要任何人理解决定的大型表格上,把票数加起来的树通常胜过神经网络,而逻辑回归仍然是该最先跑的基准。
图像、音频或文本:特征必须靠学。 但这不一定需要一个巨大的模型。2024 年,Bucher 和 Martini 比较了微调过的小模型(已经训练好,再用几百个自己的样本调整过)和不给示例、只给指令的大语言模型:
四个任务里有两个,最好的不给示例的大语言模型还不如永远猜最常见的类别。据作者说,微调模型有 200 到 500 个带标签的样本就能表现很好。不给示例的大语言模型适合第一天起步,也适合给最初那几百个样本打标签,但通常不是你在生产环境里想要的。
最后提醒一句:一个落在 0 到 1 之间的数,不一定是可信的概率。逻辑回归天生校准良好:它说 80%,大约就有 80% 的时候是对的。现代深度网络就没那么好了,不过事后只做一个调整就能修好。
技术
| ♦ 里的说法 | ♠ 里的写法 |
|---|---|
| 用 AUC 衡量表现 | AUC = P(s(x⁺) > s(x⁻)) |
| 两者没有差别 | Δ logit(AUC) = 0.00,95% CI [−0.18, 0.18] |
| 偏倚风险 | RoB(risk of bias) |
| 永远猜最常见的类别 | 多数类基线 |
| 微调;不给示例 | fine-tuning;zero-shot |
| 把票数加起来的树 | GBDT(XGBoost、LightGBM) |
| 校准良好 | P(y = 1 | p̂ = q) ≈ q;ECE |
| 一个调整 | 温度缩放:p = σ(z/T) |
Christodoulou 等(J Clin Epidemiol,2019):71 项研究,282 组对比。低 RoB(145 组)时,Δ logit(AUC) = 0.00 [−0.18, 0.18];高 RoB(137 组)时,为 +0.34 [0.20, 0.47]。机器学习表面上的优势集中在验证做得最差的地方。我只读了摘要。在一个包含 45 个表格数据集的基准上,Grinsztajn 等(2022)发现,对于中等规模的数据(约一万行),树模型仍是最先进的方法:神经网络难以应对无信息的特征和不规则的目标函数。
在文本上,Bucher 和 Martini(2024)在四个任务上比较了最好的微调模型和最好的零样本生成式大语言模型(GPT-3.5、GPT-4 和 Claude 3 Opus)。其中两个任务里,零样本的结果低于多数类基线(0.73 和 0.50)。据作者说(§5.5),微调用 200 到 500 个标签就能表现很好。
最后的挑战
三句话总结
- 逻辑回归就是只有一个神经元的神经网络:同样的加权求和,同样的 S 形曲线(sigmoid),同样的惩罚。
- 深度学习多出来的是前面那些层,它们负责制造特征;sigmoid 退出这些层,是因为它会把误差信号压没,如今它在输出端和门里工作。
- 如果你的数据是表格,而且每一列本来就有含义,就从逻辑回归开始,几分钟就能跑完,还能告诉你复杂方案要赢多少才值得;如果是像素、音频或文本,就得有人来制造特征。
资料来源
- 逻辑回归作为广义线性模型、sigmoid 作为其典型连接函数:斯坦福 CS229 讲义。对数损失的凸性:Boyd 和 Vandenberghe,Convex Optimization,§7.1.1。
LogisticRegression的默认设置(L2,C=1.0):scikit-learn 文档。- 梯度消失和 sigmoid 导数的最大值:Hochreiter,1991 年的博士论文(PDF,德语)和 1998 年的论文(PDF)。
- sigmoid、tanh 以及带归一化初始化的 tanh 的测试误差:Glorot 和 Bengio,AISTATS 2010,表 1。
- SwiGLU:Shazeer,arXiv:2002.05202;在 LLaMA 和 PaLM 中的使用。LSTM 的门:Hochreiter 和 Schmidhuber,1997。
- 临床预测中机器学习与逻辑回归的对比:Christodoulou 等,J Clin Epidemiol 110, 12(2019),doi:10.1016/j.jclinepi.2019.02.004。只读了摘要。
- 表格数据上树模型与神经网络的对比:Grinsztajn 等,arXiv:2207.08815。
- 微调模型与零样本大语言模型的对比:Bucher 和 Martini,arXiv:2406.08660,表 1 到表 4 及 §5.5。
- 现代网络的校准:Guo 等,ICML 2017,arXiv:1706.04599,表 1。
BCEWithLogitsLoss:PyTorch 文档。
这节课是怎么写成的: 基于我的机器学习笔记,由 Claude 协助整理并写出三个层次,再由 Claude 从西班牙语翻译,正式发布前会经过人工审校。所有数字都在 2026 年 10 月 4 日对照各篇论文的原始表格核对过。神经元实验室在你的浏览器里用梯度下降训练,和 ♠ 层次里的代码一样。插图均为原创。