《神经网络与深度学习》蒲公英书:12周学习路线与代码推导指南
2026/9/18 18:02:04 网站建设 项目流程

《神经网络与深度学习》这本书,圈内人一般直接叫它“蒲公英书”。我从前读研到工作后带新人,前后翻过三四遍,每一遍的收获都不太一样。它最大的价值不在于把神经网络(neural networks)讲得多浅显,而在于把神经网络的数学骨架和深度学习(deep learning)的工程实现串成了一条完整的线——书里出现的每个公式,背后基本都能对应到某个真实模型的某个模块。这篇内容想聊的是:这本书该怎么读、哪些章节必须动手推、哪些地方新手容易卡住、配套代码怎么补、以及怎么用十二周左右把它啃下来。不管你是刚接触深度学习入门的新人,还是已经会用框架调参、但说不清反向传播到底在算什么的老手,下面这些经验应该都能帮你省点时间。

1. 先搞清楚这本书的位置:它解决什么问题

国内讲深度学习的材料大致分三档:一类是框架官方文档和实战教程,上手快,但基本不解释为什么这么设计;一类是英文经典教材的翻译版,体系完整,但读起来隔了一层语言和符号习惯;还有一类就是邱锡鹏这本,用中文把从线性模型到深度生成模型的整条链路从头推一遍。它的定位很明确——做“原理”这一层的教材,不做“工具手册”。你读完之后应该具备的能力是:看到一个网络结构,能说出它的前向公式、损失函数、梯度怎么流、容易在哪一层出问题,而不是只会model.fit()

1.1 三类读者的不同打开方式

我观察下来,拿这本书的人大概分三类,读法差别很大。

第一类是零基础转行的,数学只记得高数的一点影子。这类人最容易犯的错是从第一页硬啃到最后一页,读到第4章前馈神经网络就放弃了。我的建议是先跳过后面的概率图模型和深度信念网络,把第2、3、4、5章当成主干,其余章节当成选修。第2章机器学习基础里的偏差方差、最大似然、梯度下降,是后面所有内容的公共语言,这一章必须吃透。

第二类是已经用PyTorch或TensorFlow做过项目的工程师。这类人读书速度快,但容易“看懂了就划过去”。实际上你自以为看懂的反向传播,很可能只是记住了链式法则这四个字。对这类人,最有价值的是把每一章的公式自己在纸上推一遍,再用numpy写一遍实现,用代码去验证推导,比反复读文字有用得多。

第三类是做研究、需要补数学的。泛化误差界、Rademacher复杂度、概率图模型的推断算法这几块,是你真正要花时间的部分,其他章节可以快速过。

1.2 这本书不负责的部分,别指望它

必须提前说清楚几件事,免得读的时候产生不必要的挫败感。

不讲深度学习环境配置。CUDA版本、显卡驱动、conda环境冲突这些问题,书里一个字都没有,而这些恰恰是新手放弃率最高的环节。这块你得另外找资料,或者直接用云平台跑,把环境问题外包出去。

不讲工程部署。模型量化、推理加速、TensorRT、ONNX导出这些,属于另一条技能线。同样,它不讲具体框架的API细节,也不会教你Halcon深度学习工具怎么下载、怎么调参。这本书的抽象层级在框架之上,你需要在读完原理之后,自己回到框架里去对应。

还有一点,书里的实验规模都很小。它用的是可以手推、可以用CPU跑通的小例子,不是ImageNet级别的工程实践。这不是缺点,是取舍——先把原理讲透,规模问题属于工程优化。

2. 全书知识骨架:把它拆成三条主线

很多人读这本书读得累,是因为把它当成十四章线性排列的内容。其实它更像三条平行推进的主线交织在一起,看清楚这三条线,整本书的结构立刻就清晰了。

2.1 章节之间的依赖关系

先把依赖关系理一下,这直接决定你的阅读顺序。

章节核心内容前置依赖建议投入
第1章 绪论神经网络简史、深度学习的定义与趋势快速过
第2章 机器学习基础线性回归、梯度下降、偏差方差、最大似然、贝叶斯微积分、线代、概率重点
第3章 线性模型线性分类、Logistic回归、Softmax、感知机第2章重点
第4章 前馈神经网络神经元、激活函数、反向传播、自动微分第2、3章核心
第5章 循环神经网络RNN、梯度消失爆炸、LSTM、GRU第4章重点
第6章 网络优化与正则化优化器、初始化、归一化、Dropout、早停第4章核心
第7章 注意力机制注意力、自注意力、Transformer第4、5章重点
第8章 无监督学习聚类、降维、自编码器第2章选读
第9章 模型独立的学习方式集成、迁移、多任务、元学习第4章选读
第10章 概率图模型贝叶斯网络、马尔可夫模型、推断概率论按需
第11-13章深度生成、深度强化学习等综合按需

我的实际阅读顺序是:1 → 2 → 3 → 4 → 6 → 5 → 7,把第6章优化与正则化提前,是因为第4章讲完前馈网络之后,立刻会遇到“为什么训练不动”“为什么过拟合”这类问题,先把优化和正则化补上,后面读RNN和注意力会顺畅很多。

2.2 三条主线:表示、优化、泛化

表示这条线回答的是“模型长什么样”。从第3章的线性模型出发,到第4章的前馈神经网络,再到第5章的循环网络、第7章的注意力机制,本质都是在对“如何表示输入之间的关系”做不同的假设。前馈网络假设层与层之间全连接,卷积神经网络(CNN)假设局部相关性和平移不变性,循环网络假设时间上的依赖,注意力机制假设任意位置之间都可能相关。热词里那个“图像处理为啥用CNN不用前馈神经网络”的问题,答案就在这条线上:图像是二维的、局部的、平移不变的,全连接把这些结构先验全丢了,参数还爆炸。

优化这条线回答的是“参数怎么找”。第2章的梯度下降、第4章的反向传播、第6章的动量法、AdaGrad、RMSProp、Adam,是同一条线的延续。反向传播只是把梯度算出来的方法,优化器才是决定怎么用这个梯度的策略。

泛化这条线回答的是“为什么训练好了测试却不行”。第2章的偏差方差分解、泛化误差界,第6章的L1/L2正则、Dropout、数据增强、早停,都是在处理这个问题。这三条线交叉着读,你会发现书里的每一章都不是孤立的。

3. 数学推导怎么啃:该推的推,该跳的跳

这本书最劝退的地方就是公式密度。我的经验是:别追求全都推一遍,但有几个东西必须亲手推

3.1 反向传播,至少要自己推三遍

第一遍照着书写,第二遍合上书自己写,第三遍用代码验证。这里的核心是搞清楚链式法则在计算图上的传递方式。

假设一个两层网络,输入 $x$,第一层权重 $W_1$,激活 $h = \sigma(W_1 x + b_1)$,第二层权重 $W_2$,输出 $\hat{y} = W_2 h + b_2$,损失用均方误差 $L = \frac{1}{2}|\hat{y} - y|^2$。反向传播要算的是 $\partial L / \partial W_1$,路径是 $L \to \hat{y} \to h \to W_1$:

$$\frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial h} \cdot \frac{\partial h}{\partial z_1} \cdot \frac{\partial z_1}{\partial W_1}$$

其中 $z_1 = W_1 x + b_1$。这个式子看起来简单,但真正写代码的时候,维度对齐、矩阵转置、求和维度这几个细节非常容易出错。我的建议是:每次推完,立刻用有限差分法验证数值梯度

import numpy as np def numerical_grad(f, x, eps=1e-6): grad = np.zeros_like(x) it = np.nditer(x, flags=['multi_index']) while not it.finished: idx = it.multi_index old = x[idx] x[idx] = old + eps fx1 = f(x) x[idx] = old - eps fx2 = f(x) grad[idx] = (fx1 - fx2) / (2 * eps) x[idx] = old it.iternext() return grad

这段代码不复杂,但它在调试期救了我很多次。梯度如果对不上,八成是某个转置漏了,或者链式法则里少乘了一项。数值梯度的相对误差控制在 $10^{-6}$ 量级以下,基本就可以认为推导和实现没问题了。

3.2 泛化误差界这类内容,理解思想优先

第2章里关于泛化误差界、模型复杂度的部分,推导比较重。我的建议是:先抓住三个量之间的关系——期望风险、经验风险、模型复杂度。泛化误差界说明的是,你能观察到的训练损失和真正关心的期望损失之间,差着一个跟模型容量和数据量相关的项。模型越复杂,这个差距越大;数据越多,差距越小。理解了这句话,后面的Rademacher复杂度、VC维这些东西,知道它们是在量化“模型复杂度”就够了,不必每个不等式都手推。

同理,第10章概率图模型里的EM算法、变分推断,如果你不做相关方向,知道它们解决的是“隐变量存在时如何做最大似然”这个问题即可。真正需要动手的时候再回来补,效率更高。

3.3 深度信念网络这类章节的处理

第11章往后有一些历史性的内容,比如深度信念网络、受限玻尔兹曼机。这些模型在今天的实际工作中出现频率已经不高,但它们是理解“深度模型为什么早年训不动、后来怎么被逐层预训练救活”的重要背景。我读这部分的方式是:只看结构和思想,不推细节。花二十分钟了解它在历史上的位置,比花两天推完它的对比散度算法要划算。

4. 从公式到代码:手写实现才是真正的分水岭

看懂了公式和能写出代码之间,隔着一条很宽的河。我的判断标准很朴素:能不能不看任何参考资料,用numpy从零写一遍前向和反向。写出来了,这章算过关;写不出来,说明还有理解盲区。

4.1 用numpy写一个两层前馈网络

下面这个例子我改过很多遍,用来做小规模曲线拟合特别合适,也正好对应很多人在做的“BP神经网络拟合曲线”这类实验。

import numpy as np np.random.seed(42) # 造数据:拟合 y = sin(x) 加一点噪声 N = 200 x = np.linspace(-3, 3, N).reshape(-1, 1) y = np.sin(x) + 0.1 * np.random.randn(N, 1) # 网络结构:1 -> 16 -> 1 W1 = np.random.randn(1, 16) * np.sqrt(1.0 / 1) b1 = np.zeros((1, 16)) W2 = np.random.randn(16, 1) * np.sqrt(1.0 / 16) b2 = np.zeros((1, 1)) lr = 0.05 for epoch in range(20000): # 前向 z1 = x @ W1 + b1 h = np.tanh(z1) y_hat = h @ W2 + b2 # 反向 loss = 0.5 * np.mean((y_hat - y) ** 2) d_y = (y_hat - y) / N dW2 = h.T @ d_y db2 = np.sum(d_y, axis=0, keepdims=True) d_h = d_y @ W2.T d_z1 = d_h * (1 - h ** 2) # tanh 的导数 dW1 = x.T @ d_z1 db1 = np.sum(d_z1, axis=0, keepdims=True) W2 -= lr * dW2 b2 -= lr * db2 W1 -= lr * dW1 b1 -= lr * db1 if epoch % 2000 == 0: print(f"epoch {epoch:5d} loss {loss:.6f}")

这段代码里有几个值得说的点。初始化用 $\sqrt{1/n}$ 缩放,不是随手写的,是为了让每层的输出方差保持稳定,这个原则在后面读到Xavier初始化和He初始化时会有正式的推导。d_z1里乘的是1 - h**2,这是tanh的导数,如果把激活换成ReLU,这一项就要换成(z1 > 0)损失里除了N,是因为用了均值而不是求和,这一步经如果搞错,学习率会显得“怎么调都不对”。

同样的实验在Matlab里也能做,热词里“深度学习matlab”“bp神经网络拟合曲线”这类需求挺多。Matlab的优势是工具箱封装得好,fitnet几行就能跑起来,但代价是你看不到反向传播具体在做什么。我的建议是:原理阶段用numpy,工程交付再考虑Matlab或框架,顺序反了,你永远不知道自己到底懂不懂。

4.2 卷积层和im2col:理解CNN到底省了什么

卷积神经网络是这块内容的重点。书上讲卷积的公式不难,难的是理解它在工程上怎么高效实现。现代框架基本都用im2col加矩阵乘法的方式做卷积,把这个搞明白,你对CNN的理解会跳一个层次。

import numpy as np def im2col(x, kh, kw, stride=1): N, C, H, W = x.shape oh = (H - kh) // stride + 1 ow = (W - kw) // stride + 1 cols = np.zeros((N, C, kh, kw, oh, ow)) for i in range(kh): i_max = i + stride * oh for j in range(kw): j_max = j + stride * ow cols[:, :, i, j, :, :] = x[:, :, i:i_max:stride, j:j_max:stride] return cols.transpose(0, 4, 5, 1, 2, 3).reshape(N * oh * ow, -1)

这段代码的核心思想只有一句话:把每个滑动窗口里的数据拉成一个行向量,卷积就变成了一个大矩阵乘法。原始做法是四层循环,慢到没法用;im2col之后调用BLAS,速度能差几十倍。代价是内存占用变大,因为重叠区域被复制了多次——这也是为什么后来的实现会引入Winograd、FFT等更省内存的算法。

理解了这一点,再回头看“图像处理为啥用CNN不用前馈神经网络”这个问题就更具体了:卷积层两个关键特性是局部连接权重共享,参数数量跟图像尺寸无关,只跟卷积核大小和通道数有关。一张 $224 \times 224$ 的图,接一个 $224 \times 224$ 的全连接层需要五万多个参数(乘以隐藏单元数),而 $3 \times 3$ 的卷积核只需要9个参数。这不是量级的差距,是本质的差距。

4.3 自注意力和跨窗口注意力

第7章的注意力机制是必读章节。自注意力的公式不长:

$$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V $$

这里最容易被忽略的是那个 $\sqrt{d_k}$。它的作用是防止点积结果随着维度增大而数值过大,导致softmax进入饱和区、梯度极小。你可以在代码里手动去掉这一项试试,训练会明显变差,这个实验比看十遍推导都管用。

热词里提到的“WSA和跨窗口自注意力”,其实是把全局注意力限制在局部窗口内计算,再通过窗口之间的信息交换来近似全局建模。这么设计的动机是降低计算复杂度:全局自注意力的复杂度是序列长度的平方,窗口化之后降到线性。理解这个动机,比记住具体网络结构重要得多。

5. 学习节奏与配套资源的组合拳

书厚,内容多,没有节奏安排很容易半途而废。下面这个十二周安排是我带人时用得最多的一套,供参考。

5.1 十二周推进表

周次阅读范围动手任务产出标准
1第1、2章推导最小二乘、手写梯度下降能解释偏差方差分解
2第3章实现Logistic回归与Softmax能在小数据集上收敛
3-4第4章numpy实现两层前馈网络+数值梯度校验梯度误差小于1e-5
5-6第6章对比SGD、Momentum、Adam画出收敛曲线对比
7-8第5章手写RNN、实现LSTM门控能解释梯度消失
9-10第7章实现单头自注意力能与框架结果对齐
11第8、9章复现一个自编码器理解表示学习
12复习+专题自选一个方向深挖写一篇复盘

这张表的关键不在于时间分配,而在于每周都必须有可验证的产出。读完一章不算完成,代码跑通、结果对得上才算。

5.2 课件、习题和实践怎么配合

配套的课件和习题质量很高,尤其是习题,很多是让你补全推导或者验证某个性质的。我的用法是:先看PPT建立框架,再读书补细节,最后做习题验证。这个顺序比直接读书效率高,因为PPT把结构先给你搭好了,读书的时候不会迷路。

习题里有一部分偏理论,比如证明某个损失函数的凸性、分析某个优化器的收敛条件。这类题如果卡住超过一小时,可以先跳过,把时间留给代码实现。理论推导的收益是长期的,而代码能力的收益是即时的,两者在不同阶段权重不一样。

还有一个容易被忽视的资源是复现别人的代码。GitHub上有不少对这本书的章节复现,挑star多的看。看别人怎么组织张量维度、怎么做数值稳定处理,比你自己闷头写一遍收获更大。

6. 卡点实录:新手最常踩的坑

这部分是我觉得最值钱的部分,都是实际带人时反复出现的问题。

6.1 常见问题速查表

症状常见原因排查方向
损失不下降学习率过大或过小从1e-3开始,按10倍缩放试
损失变NaN除零、log(0)、梯度爆炸加eps、检查log的输入范围
训练好测试差过拟合加正则、Dropout、早停
梯度计算对不上转置错、少乘激活导数用数值梯度逐项比对
收敛极慢初始化不合理、没做归一化换Xavier/He初始化、加BN
参数不更新梯度被detach、学习率为0打印梯度范数检查
显存爆掉batch过大、中间变量未释放减小batch、用no_grad
结果每次都不一样随机种子未固定固定seed并记录

6.2 几个不常见但很致命的细节

第一,epoch和step的区别。热词里“深度学习epoch”出现频率很高,说明这个概念确实容易混。一个epoch是完整遍历一次训练集,一个step是一次参数更新。batch size为32、训练集有3200条数据时,一个epoch等于100个step。学习率调度的策略通常是按epoch或者按step来的,搞混了会导致实际训练量差几十倍。

第二,验证集和测试集不能混。我见过有人用测试集调超参数,最后报出来的准确率虚高好几个点。正确的做法是训练集训参数、验证集调超参、测试集只用一次。

第三,BatchNorm在训练和推理时行为不同。训练时用当前batch的均值和方差,推理时用滑动平均。如果你手写推理流程时忘了切eval模式,结果会飘得很厉害,而且这种错误很难一眼看出来。

第四,梯度裁剪不是万能的。它在RNN上确实能救急,但如果你需要频繁裁剪,说明学习率或者初始化本身有问题,先解决根因。

第五,注意力掩码很容易写错。Padding位置的注意力权重必须被mask成负无穷,否则模型会关注到无意义的填充符。这类bug不会报错,只会让效果变差,排查起来很费时间。

7. 写在最后的一点个人体会

这本书我最大的体会是:它的价值在读第二遍的时候才真正显现。第一遍你会被公式淹没,觉得处处是难点;第二遍你已经有了代码经验,回来看那些推导,会发现作者在很多地方其实给了非常明确的动机提示,只是第一遍读的时候没接住。比如第6章讲优化器,为什么要从SGD一步步推到Adam,每一步都在解决前一步的什么缺陷,这个逻辑链第一遍读是看不出来的。

另外,别把这本书当成孤立的读物。热词里出现的联邦深度强化学习、图神经网络、3D卷积、人声分离这类方向,书里有的讲了、有的只是带过。正确的做法是把它当成一张地图,主干路线铺好之后,具体方向自己顺着往下挖。真正的工作里,你需要的往往不是把某一章读透,而是知道遇到什么问题时该翻回哪一章。

如果只让我给一条建议:每周至少写一百行跟这本书相关的代码。公式会忘,推导会忘,但肌肉记忆不会。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询