上一章《感知机》只会画一条直线,连 XOR 都学不会。
这一章解决的就是这件事:怎么把一条直线折成任意形状。后面几十章里的大网络,拆到最里面都是这一件小事重复很多遍。
回想 XOR 那四个点:两位输入取 0 / 1,相同 → 0,不同 → 1—— (0,0) 和 (1,1) 的答案一样,(0,1) 和 (1,0) 的答案一样。 画到平面上,就是两个同类点站在一条对角线上,另外两个站在另一条上。 一条直线最多把平面切成两半——它圈得住对角的一半,就圈不住另一半。
所以要动的不是训练方法,是那条线本身:让它能弯。 下面四个格子就是整章的路线图。
这一章在讲什么 · 四张图看完
互动 · 拖滑块,看纸条折起来
把一条直线折弯,再叠起来,就能拼出任意形状。
听上去不像什么大本事,但深度学习全部复杂度的来源就是它。
想象你只有一根笔直的纸条。想拼出一只猫的轮廓,你怎么办?
折它。折一次多一个角,折得够多,纸条就能沿着任意曲线走。
这一章剩下的部分,就是把「折」这件事拆开看清楚:
谁在折(激活函数)、折多少下(宽度)、能不能折出更复杂的形状(深度)。
别看"神经元"这名字唬人,它的全部工作就是三件事: 把输入按重要性加权相加 → 加一点偏置 → 过一道"门槛函数"。 这三件事对应标题里的三个动作:转 = 乘上权重(线变陡或转向)、 推 = 加上偏置(整条线平移)、折 = 过激活函数。 z 就是上面「加权和再加偏置」得到的那个数;下面「转一下、推一下、再折一下」那个互动画的就是它: w 决定它多陡,b 决定它被推到哪里。折的位置在 z = 0 那里,所以折痕也跟着 w、b 挪。
互动 · 一个神经元
输入固定为 x = (0.8, 0.3, −0.5)。蓝线 = 正权重(放大),橙线 = 负权重(压制),线的粗细 = 权重绝对值。
动画 · 一个神经元 = 转一下、推一下、再折一下
互动 · 每个符号管图上的哪一块
n 不在公式里:它是这一层放几个神经元。
把三个输入想成三个评委给的分数。w 是「这位评委说话的分量」,b 是「你本人一开始的偏见」。 神经元做的事就是:把分数按分量加起来,再加上偏见,最后过一道「要不要激动」的门槛。 这个类比管到门槛为止:真的评委不会被训练,而 w 和 b 是网络自己从数据里调出来的。
单独一个神经元的本事很小:门槛之前的部分只能在输入空间里画一条直线,把世界劈成两半。 这道门槛历史上换过几种,结构从来没变,变的只是门槛:
| 门槛 | 画出来 | 装上它的神经元叫什么 |
|---|---|---|
| 阶跃(step) | 一级台阶:越过 0 就跳到 1,否则贴在 0,相当于「及格 / 不及格」 | 感知机(Perceptron),1958 年 |
| Sigmoid | 平滑的 S 形,压到 0~1 | 逻辑回归(Logistic Regression) |
| tanh | 同样是 S 形,压到 −1~1,以 0 为中心 | Sigmoid 的居中版 |
| ReLU | 负数抹成 0,正数原样通过 | 今天几乎所有网络的默认 |
| 无 | 一条直线 | 叠多少层都等于一层(只会画直线) |
因为它最便宜:没有指数运算,只是一次比较。
而且 Sigmoid / tanh 在两头会被「压平」,那里斜率接近 0——
把神经元排成一排叫一层,把好几层接起来就叫 多层感知机(MLP)。
一层里面,每个输入都连到每个神经元——这张密密麻麻的网就是
动画 · 数据在网络上流动
青色小球 = 数据正在往下游传。每一层都会把上一层的输出重新组合一遍。
像工厂流水线:第一层把原料切成块,第二层把块拼成零件,第三层把零件装成部件,最后一层交付成品。越往后,东西越"抽象"、越像最终答案。
把上面的三件事写成一行,就是神经网络里最重要的一个式子: 一层 = 乘一个矩阵,再过一道激活。 它和第 2 节那个式子是同一个东西,只是把「一个神经元」 换成了「一整层」,所以每个符号从「一个数」变成了「一排数」。 这一行摆出来长什么样、矩阵到底怎么乘,放在 数学那节;下面先把每一项对回第 2 节。
| 式子里的一项 | 在第 2 节的标量视角里 | 在「一层」里 |
|---|---|---|
| a⁽ˡ⁻¹⁾ | 三个输入 (0.8, 0.3, −0.5) | 上一层所有神经元的输出,拼成一个向量 |
| W⁽ˡ⁾ | 三个权重 w₁ w₂ w₃ | 一个矩阵,第 i 行就是第 i 个神经元的全部权重 |
| W a | 加权相加 | 矩阵乘法:一次算出整层每一个神经元的加权和 |
| + b⁽ˡ⁾ | 加偏置 b | 每个神经元一个偏置,排成一排,一次加上 |
| σ( ) | 过门槛函数 | 逐元素过一遍激活函数 |
「一层」在上帝视角下就两个动作:乘一个矩阵,再过一道激活。 所以好几层接起来是同一个模板重复 N 遍。后面所有网络(CNN、Transformer)拆到最后都是这一行式子。
这是初学者最容易忽略的一点。如果把激活函数拿掉, 整个网络就退化成一个大矩阵乘法:100 层和 1 层没有任何区别。 下面把这句话变成图:输入是一张规整的方格纸,叠一层 = 整张图乘同一个矩阵; 右边每层再过一次 ReLU——出网还是不是方格、能不能被一个单层顶替,图上直接给答案。
互动 · 叠 L 层,能不能被一个单层顶替?
| 做法 | 数学上等价于 | 能画出什么分界线 |
|---|---|---|
| 1 层线性 + 1 层线性 | W₂(W₁x) = (W₂W₁)x | 还是一条直线 |
| 1 层线性 + 100 层线性 | 还是一个大矩阵 | 还是一条直线 |
| 线性 + ReLU + 线性 | 不能再合并成一个矩阵 | 能弯! |
激活函数就是那道“折痕”。 没有折痕,你把纸翻来覆去叠 100 遍,它还是平的。
ReLU 之所以流行,就是因为它是最便宜的折痕:max(0, x),负数抹零,正数直通。
第 7 节那个训练器:把激活函数切成「无」再重训,分界线死活就是一条直线,误差也降不下去。
为什么?一行代数就说完了。把两层摊开写:
因为线性模型能拿到的最好成绩就只有那么高:它把平面切成两半, 而 XOR 的答案偏偏一半对一半——最优点处两边错分点互相抵消,梯度归零。 它不是「还没降下去」,是已经降到它够得着的最低点了。
第 2 节的一个神经元,到第 3 节变成了「一整层」:每个符号从「一个数」升级成「一排数」。 这一节把这一层摊开算清楚——式子长什么样、里面的矩阵怎么乘、乘出来是什么形状、一共装了多少个数。 第三笔账就是参数量:第 4 节的塌缩和第 12 节的爆炸,都要从这张表里领走答案。
先看那个「乘」。一层里坐着 h 个神经元,每个神经元都拿到同一排输入 a。 把它们的权重一行一行摞起来就是 W:W 的第 i 行,就是第 i 个神经元的 n 个权重。 算第 i 个神经元的加权和,就把第 i 行和 a 逐对相乘、再全部加起来—— n 对数字乘出 n 个积,加起来是 1 个数;h 行都算一遍,就得到 h 个数,排成输出的向量。 所以 W 是 h 行 n 列,a 是 n 个数,乘出来是 h 个数:中间那个 n 一进一出,被「吃掉」了。
| 这一层是谁 | 进来几个数 | W 的形状 | 出去几个数 | W 里数的个数 |
|---|---|---|---|---|
| 一个神经元(第 2 节) | n | (1 × n) 一排 | 1 | n |
| 一层 h 个神经元(第 3 节) | n | (h × n) | h | h × n |
| 再接一层 k 个 | h | (k × h) | k | k × h |
| 图片拉直了进来(第 12 节) | 3s² | (256 × 3s²) | 256 | 256 × 3s² |
怎么读:W 的行 = 本层神经元个数,列 = 进来数的个数,乘出去的长度 = 行数。
参数量 = W 里数的个数 = 行 × 列(每个神经元再加 1 个偏置)——第 12 节「边长一涨参数就爆」
就是因为列数 = 3s²,跟着边长的平方走。表里的 (n,) 读作「一排 n 个数」。
互动 · W 的一行 × 输入 = 输出的一个数
两层为什么天生能接,形状上就写着:W₁ 是 (m×n)、W₂ 是 (k×m), 中间那个 m 正好首尾相接,乘完还是一个 (k×n) 的矩阵—— 第 4 节那行 W₂(W₁x) = (W₂W₁)x 在形状上永远合法。
乘矩阵、加偏置,这两步都改不了「直」这件事: 方格进来是斜的,出去还是斜的,平行线永远平行。 这一类「只转只推、不折」的动作叫仿射——两个仿射叠起来仍然是仿射, 这就是第 4 节那句「100 层等于 1 层」的全部内容。
过激活函数是另一种动作。它把「所有点按同一套规则动」换成了 「按每个点自己在哪儿,分别决定动不动」——直线到这一步才有了弯的可能。 它也是一层里唯一不是乘加的动作:ReLU 这种每个数只做一次比较,算得极便宜, 时间主要花在把数据搬进搬出上(暗线 D 那一栏会用到这一点)。
「折」是唯一能改变形状的动作,而它折一次只多出一条新边。 于是「能折出多复杂的形状」这个问题就变成了「一共折了多少次」—— 折的次数正是后面两节分别在买的量:宽度(下一节)买一次能折多少下, 深度(第 6 节)买同样多的折痕能省下多少参数。
折痕有了(第 4 节),层数先不动——只把一层里的神经元摆得足够多,能拼出什么?
结论比想象的强:在有限区间上,任何一条连续曲线都能拼出来。原理朴素得像画折线图:一个 ReLU 神经元贡献一个拐点,拐点足够密,折线就和原曲线重合了。
互动 · 用拐点拼出一条曲线
上面每条折线都能写成同一张蓝图,就是若干个 ReLU 加起来:
这就是万能逼近定理说的事:一个隐藏层、足够多的神经元,能把任意连续曲线逼到任意精度。 它没说要多少个——上面那个互动里,把拐点数拖到 6 以上,读数第一行的末尾会多出一句 「把拐点减半再算一遍,最大误差是现在的几倍」:在「波浪」「复合」上,这个倍数在 1.9~3.6, 拐点越多,整体越大、越接近 4 倍;反过来看,拐点翻一倍,误差降到三分之一左右,越多越接近四分之一。 想再精确十倍,拐点大约得多三倍。 「尖峰」「阶跃」上拖一拖还会碰到反例:拐点没放在尖角上时,多了拐点误差反而变大。 至于实际搭网络时一层放几个,是拿验证集(从数据里单独留出来、不参加训练、专门用来检验的一份)试出来的(《超参怎么选》讲);定理只保证「够多就行」。
上一节的定理只说「够宽就行」,没说要多宽。 这是它最容易被误读的地方:能逼近,不等于能便宜地逼近。
拿一张纸条试试。想让它有 8 段,可以一道一道单独折 7 下,这是上一节的办法:一层里排 7 个神经元,每个管一道折痕。 也可以对折、再对折、再对折:三次,展开就是 8 段。 每对折一次,段数翻一倍。
网络里的「对折」就是多叠一层。下面每一层只有 2 个 ReLU,合起来正好把输入对折一次
(2·ReLU(x) − 4·ReLU(x − ½):第一个 ReLU 让线以斜率 2 往上爬,
爬到 x = ½ 时 y 刚好到 1;从那里起第二个 ReLU 再减掉斜率 4,净斜率变成 −2,线折回来。
顶点是 (½, 1),两头都落在 0)。
叠 k 层,输出就是一条 2k 段的锯齿。
互动 · 同样多的神经元:叠起来对折,还是排成一层
一层里多放一个神经元,只多一道折痕;多叠一层,是把前面所有折痕再对折一遍。 段数涨了多少,图上两张曲线的读数已经说完了,这里只留一句话:同样的效果,深的便宜得多—— 深度学习叫「深度」,原因在这里。
把这张图和上一节放在一起,万能逼近定理的边界就清楚了:
| 定理说 | 定理没说 |
|---|---|
| 一层就够:宽度不限,有限区间上的任意连续函数都能逼近 | 要多少个神经元。上面那条锯齿,一层要 2k−1 个,叠起来只要 2k 个 |
| 存在一组参数能表达这个函数 | 梯度下降找不找得到那组参数。存在 ≠ 找得到 |
下面的网络是 2 → 6 → 1,在你的浏览器里跑
互动 · 实时训练
背景色 = 网络认为某点属于哪一类:蓝 偏向蓝色点,橙 偏向橙色点。
XOR 的规矩就是第 1 节那四个点:坐标相同 → 0,不同 → 1。 图上把 0/1 的正方形放大挪到原点两边(0 → 负数、1 → 正数),于是「相同」就成了「两个坐标同号」; 画在平面上,左上和右下是一类,左下和右上是另一类,一刀切不开。 隐藏层的 6 个神经元各自切一刀,合起来围出一个「十字」,把对角的两块圈出来。
还有一种看法:隐藏层是在多造出一个方向。想象平面上的点是贴在地面的纸片,一条直线怎么也分不开; 要是让其中一类飘起来、另一类沉下去,中间横放一块板子,就分开了。
互动 · 多出一个方向,一块板子就分开了
上一节你看到分界线从直线弯成了曲线。但隐藏层并不是在"画曲线",它在切空间。
每个 ReLU 神经元就是一刀:在平面上画一条直线,一侧"开"、一侧"关"。 一刀切不出什么,但八刀拼起来,就能围出一个弯弯曲曲的区域。 拖动滑杆看刀一把把加上去。
互动 · 一个神经元就是一刀
分工是这样的:隐藏层负责把平面切成很多块,每个神经元只报告「这个点在我这一刀的哪一侧」; 输出层看这些开 / 关的组合下结论,它自己在这套新坐标里仍然只画一条直线。 多一层为什么更强,下一节看:第二层的刀,切在第一层造出来的坐标上。
上一节的刀全是直的。如果只能切直线,那多切几层又能多出什么花样?
关键在于:第二层的输入已经是第一层的输出,原始的 x、y 只出现在第一层。 它的"直线"是画在第一层造出来的坐标系里的,所以落回原图会沿着第一层的刀痕 折断成折线。下一层再折一次,依此类推。
互动 · 同一批刀,隔一层就弯了
在一层里加刀,区域数只按平方涨:N 条直线最多切出 N(N+1)/2+1 块。 数法是:第 N 条线最多和前面 N−1 条各交一次,被切成 N 段,多切出 N 块; 从 1 块开始累加 1+2+…+N,就是那个式子。 多叠一层,上一层切出的每一块都会被重新切一遍,区域数往上翻。 这就是第 6 节那条锯齿的平面版:一维里是「对折一次,段数翻倍」,二维里是「隔一层,刀就弯了」。
学习的过程就一句话:算出每个参数对最终错误的"责任"有多大,然后按责任大小往回微调。
动画 · 四步走一遍,看误差怎么一层层往回分
公司项目搞砸了(预测错了)。老板先骂总监,总监把锅分给各组,组长再分给每个员工。 每个人分到多少,看他那一环对结果的影响有多大:锅每往下传一级,就乘上那一级的分量。 误差反向传播走的就是这条路线;「按锅扣多少工资」的那个比例,就是学习率。 这个类比管到分锅为止:真公司里锅会被推卸,链式法则算出的每一份都不多不少。
反向传播不是神经网络"回头看"或"思考"。它只是链式法则的一次高效应用,解决的是"怎么用最少的计算量算出所有梯度"。梯度指路,然后参数自己往下滑一点点。
这个全连接层心里认着一句话:每个输入都可以连到每个神经元。 后面每一种新网络,都是把这句话松一松,松掉的正好是它用不上的那部分连接。
把它拆细一点,「全连接」其实是两句假设叠在一起: ① 每对输入和神经元都可能有关系,一根线都不能少连; ② 每对关系长什么样都各不相同,每根线都得有自己的权重。 贵就贵在第 ② 句:n 个输入接 h 个神经元,就是 n×h 个数,一个都省不掉。 后面每一种新网络动的都是这两句话——下面把三种连法画在一起, 连线数和权重数当场数给你看。
互动 · 同一层神经元,三种连法
| 换成它 | 它松开了哪条假设 | 换来什么 | 什么时候你才需要它 |
|---|---|---|---|
| MLP(本章) | 什么都不松:每个输入连到每个神经元 | 最通用,也最贵 | 输入是一排没有空间顺序的特征(表格数据先看第 12 节) |
| CNN(卷积网络) | 「远处的像素也直接相关」:只连邻居,而且同一个核扫过全图 | 参数几乎不随图片变大 | 输入有空间结构:图片、音频频谱、任何网格 |
| RNN(循环网络) | 「每个位置用各自的权重」:所有时刻共用同一套 | 序列多长都吃得下 | 输入是变长的序列 |
| LSTM / GRU | 在 RNN 之上再松一条「每一步都把记忆整个重写」:多开一条只做加减的记忆通道,门控决定留什么 | 能记住更早的事 | 序列很长,而且早先的信息后面还要用 |
| Transformer | 「谁跟谁相连由设计者定」:连谁改由数据自己算 | 任意两个位置直接对话,而且能并行 | 长依赖,而且想把 GPU 喂满 |
最容易混的是 MLP 和 全连接层:全连接层是一块零件(一个矩阵 + 一个偏置), MLP 是好几块全连接层中间夹着激活函数叠起来。 今天很少拿纯 MLP 当主干,它藏在别的网络里:CNN 最后负责下判断的那几层、 Transformer 每一层里那个「前馈网络」,都是一个两层的 MLP。
所以这张表里没有「谁比谁强」。它们都还是「乘一个矩阵,再过一道激活」这一行式子, 区别只在谁连谁。下一节讲的,就是「谁连谁」定得太满要付什么代价。
MLP 对输入什么都不假设(上一节表格第一行)。好处是什么都能学,代价是每一样都得从数据里学。 账单最先在图片上寄来,它催生了 CNN。
假设一张 224×224 的彩色图(3 通道),接一层只有 256 个神经元的隐藏层,需要多少参数? 把账拆开数:图片先拉直成一排数,224×224×3 = 150,528 个;全连接要求每个输入连到每个神经元, 所以每个神经元都挂着 150,528 个权重,256 个神经元就是 150,528 × 256。 参数量 = 这个矩阵里数的个数(再加每个神经元 1 个偏置)——矩阵多大, 数学那节的形状账已经写好:W 是 (256 × 3s²),行 × 列就是答案。拖下面的边长,看它怎么长。
互动 · 参数量对比
CNN 那个数字跟图像多大完全无关,这是权值共享的威力,更后面的《CNN 卷积神经网络》细说。
两边的数法一致,都算上了偏置:MLP = 3s²×256 + 256;CNN = 3×3×3×64 + 64 = 1,792。对比参数量时口径必须一样:只算权重会少算一层偏置,算出来的比值会偏。
MLP 把图片拉平成一串数字,每个像素都有自己专属的权重。 所以把猫往右挪 10 个像素,输入完全变了,网络就懵了。 但"这是一只猫"这件事,和它在左边还是右边毫无关系。
四笔账都是「什么都不假设」换来的:
| 代价 | 具体表现 | 什么时候真的会痛 → 换什么 |
|---|---|---|
| 参数随输入平方涨 | 224×224 彩色图,第一层就是 3,854 万个参数(上面那个滑块) | 输入是图片、频谱这类大网格 → 卷积(更后面的《CNN 卷积神经网络》) |
| 不认位置 | 左上角和右下角的像素是两个无关的数,猫挪一下输入就全变了 | 同一个东西会出现在不同位置 → 卷积 + 池化 |
| 中等规模表格打不过树模型 | 45 个表格数据集(约一万行)的基准里,梯度提升树普遍更好:没用的列会干扰 MLP,它也不在乎每一列原来的意思 | 几千到几万行的业务表格 → 先试 XGBoost 这类树模型 |
| 连乱标签都背得下 | 把训练标签全部打乱,大网络照样能在训练集上做到 100% | 数据少、标注脏:训练集上的高分可能只是记住了 → 《过拟合与正则化》 |
这一章站在「⑥ 层层组合」上(第一性原理那页的七条线,回答「深度学习为什么能行」):上一章一条直线切不开 XOR, 这一章把很多层叠起来,每层只多 2 个神经元,折痕却成倍地涨。 下面第二张表换了一套编号——六条暗线,回答的是另一个问题:拆开一个方法时,该问哪六件事。
去第 4 节把「叠几层」从 0 拖到 4:左边没有激活,永远能被一个单层顶替;右边第一层就折了。这是「折痕从哪来」。
再去第 6 节把「叠几层」拖到 8:上面 16 个神经元折出 256 段,下面同样 16 个只有 17 段。这是「深度让折痕成倍地涨」。
| 暗线 | 这一章的回答 |
|---|---|
| A 信息流动 | 门口只收一排数:(n,) 就是「n 个数排成一行」,出来还是排成一行。
图片本来是方的(高 × 宽 × 通道),必须先拉直才能进门(Flatten)——
拉直那一步把「谁挨着谁」扔了,而且扔了捡不回,所以 MLP 永远认不出挪了位置的猫(第 12 节) |
| B 什么被牺牲了 | 空间结构和平移不变性。左上角和右下角的像素被当成两个无关的数。 代价极其具体:参数从"固定几个"变成"随图片尺寸平方增长" |
| C 参数账本 | 上一层 n 个、这一层 h 个神经元:h × n 个权重加 h 个偏置(数学那节的表)。
一张 224×224 彩色图第一层就是 3,854 万;一个 3×3 卷积核只有 3×3×3 = 27 个权重,差在「每个输入都连」这一句假设上 |
| D 跑在什么上 | 算力受限的那一类:MLP 的主体就是矩阵乘,显卡的算力主要花在它上面。 但一次算多大一批、能不能把显卡喂饱,是另一笔「搬运 vs 计算」的账,在 《硬件与算力账本》里算。 激活函数这种逐元素操作,时间则主要花在搬数据上。 |
| E 它假设了什么 | 假设特征之间可以任意组合:每个输入都连到每个神经元,不做任何结构假设。 这是最弱的假设,所以它最通用,也最需要数据。 CNN 在它之上加了「只和邻居相关、到处一个样」;Transformer 改成「谁和谁相关,由数据当场算」(第 11 节) |
| F 违背了哪个直觉 | 「一层就够,为什么还要深」。万能逼近定理说一层足够,但深度能用指数级更少的参数达到同样的效果。 「够」和「划算」是两件事——差多少,看第 6 节那张图上两张曲线的读数 |
它接住了上一章的什么:感知机(《感知机》)只会画一条直线, 撞上 XOR 就死。这一章用「多叠几层 + 折弯」解决了它。
它给下一章留了什么:这一章的折痕全来自《激活函数》——它凭什么缺不了,正是下一章要拆的。而把图片当一串无序数字、参数爆炸、还不认位置,是更后面《CNN 卷积神经网络》要解决的。
MLP 就是「乘一个矩阵,折一下」叠很多遍,什么形状都拼得出。
所以真正的问题从「能不能」变成了「划不划算」:深比宽划算,带假设比不带划算。更后面的《CNN 卷积神经网络》,是你会遇到的第一个带着假设的网络。
上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。