机器学习数学基石:Gilbert Strang教你用线性代数贯通SVD、PCA与反向传播

📅 发布时间:2026/10/3 19:01:03
机器学习数学基石:Gilbert Strang教你用线性代数贯通SVD、PCA与反向传播
简介《Linear Algebra and Learning from Data》是 Gilbert Strang 所著的英文原版电子书旨在打通线性代数与机器学习、深度学习之间的数学桥梁适合具备一定数学基础的高年级本科生、研究生及数据科学相关研究人员阅读。全书按七大板块展开系统讲解矩阵运算、特征值、奇异值分解等核心概念同时覆盖大规模随机化矩阵计算、低秩与压缩感知、特殊矩阵、概率统计与优化方法并深入介绍深度神经网络的构建、卷积神经网络和反向传播原理配套实例与练习题便于读者巩固理解。资源为单份 PDF 文件压缩包大小约 26.38MB内容完整、排版清晰可直接作为系统学习或查阅参考。已有 232 人学习下载对于希望从数学底层理解机器学习算法、掌握从数据中学习模型的读者是一份颇具价值的经典教材。1. 机器学习数学底子薄Gilbert Strang 这本教材帮你补上最关键的线性代数做机器学习久了你会发现一个尴尬现象调包调参能跑通模型但一旦涉及损失函数收敛、特征降维、权重更新这些核心环节数学底子不够就处处碰壁。很多人回来补课首选 MIT 18.065而 Gilbert Strang 老爷子这本《Linear Algebra and Learning from Data》就是配套教材2019 年由 Wellesley-Cambridge Press 出版。它不是一本纯线性代数书也不是纯机器学习书而是把线性代数、概率统计、优化方法拧成一股绳讲清楚深度学习中每个关键步骤背后的数学动机——矩阵分解怎么帮数据降维、随机梯度下降为什么有效、ReLU 为什么取代 sigmoid 成为默认激活函数。适合手里有本科数学基础、想系统打通机器学习数学关节的从业者和研究生靠短视频和博客补数学是零碎的这本书能帮你把散点连成体系。2. 奇异值分解贯穿全书的“王牌工具”与四个落地点2.1 为什么机器学习里 SVD 比特征值分解更常用如果你只学过传统《线性代数》教材大概率对特征值分解更熟但数据科学里真正的主角是奇异值分解SVD。Strang 在全书中反复强调一个观点对称矩阵可以用特征值分解但现实中的样本数据矩阵几乎不对称行数和列数、行空间和列空间的维度都可能不一致强行套用特征值分解会碰壁。SVD 则对任意矩阵成立A UΣVᵀ左奇异向量 U 张成列空间右奇异向量 V 张成行空间奇异值 σ 按从大到小排列。Strang 特别强调从对称矩阵 S QΛQᵀ 到一般矩阵 A UΣVᵀ 的推广是“我们这代人最重要的数学一步”。对称矩阵用一组正交特征向量就能完全描述但对任意矩阵你需要两套基一套管行空间、一套管列空间。书中用样本协方差矩阵做例子说明对协方差矩阵做特征值分解特征值对应各主成分方向的方差而特征向量就是主成分方向。但如果你面对的是原始数据矩阵直接做 SVD 更自然因为数据矩阵的奇异值平方恰好等于协方差矩阵的特征值两者在数学上等价计算上 SVD 更稳定。2.2 核心定理 Eckart-Young截断 SVD 为什么是最优低秩近似这一节要敲黑板。Strang 在前言里特别点出“Eckart-Young Theorem”是全书最重要的定理之一如果想把矩阵 A 近似成一个秩为 k 的矩阵那么保留前 k 个最大奇异值对应的部分 Σᵢ₌₁ᵏ σᵢuᵢvᵢᵀ是在 Frobenius 范数意义下的最优近似。换句话说你想丢掉一部分信息来压缩数据丢掉哪些丢掉最小的奇异值对应的那些分量损失最小。这个定理在机器学习里到处都在用。PCA 降维的数学依据就是它——把原始数据矩阵截断到前 k 个主成分方向保留最大方差图像压缩也一样把一张图片的像素矩阵做 SVD只保留前几十个奇异值就能用远小于原始存储空间的参数重建出视觉上几乎无差别的图像。Strang 在书中用“秩一矩阵求和”的方式重新表述 SVDA σ₁u₁v₁ᵀ σ₂u₂v₂ᵀ …每一项的“重要程度”由奇异值大小决定这样理解低秩近似特别直观。2.3 用 NumPy 亲手跑一遍截断 SVD 与 PCA 降维光看不练容易飘。我一般建议拿到这本书后第一件事就是在本地用 NumPy 把 PCA 从零实现一遍。这里给你一套可以直接跑的代码数据用 sklearn 自带的鸢尾花数据集目标是降到 2 维可视化import numpy as np from sklearn.datasets import load_iris # 加载数据X 是 150 行 4 列的样本矩阵 iris load_iris() X iris.data y iris.target # 第一步中心化让每个特征均值变为 0 # 这是 PCA 的前提否则第一个主成分会被均值带偏 mean np.mean(X, axis0) X_centered X - mean # 第二步对中心化后的矩阵做 SVD而不是直接对协方差矩阵做特征值分解 # full_matricesFalse 避免生成冗余的零空间向量减小计算量 U, S, Vt np.linalg.svd(X_centered, full_matricesFalse) # 第三步取前 2 个右奇异向量作为主成分方向 # Vt 的行是主成分方向前两行就是最重要的两个方向 W Vt[:2].T # 形状 (4, 2) # 第四步把原始数据投影到主成分空间 X_pca X_centered W # 形状 (150, 2) # 第五步验证解释方差比例 # 奇异值平方除以总平方和 该主成分解释的方差比例 explained_var_ratio S**2 / np.sum(S**2) print(各主成分解释方差比例:, explained_var_ratio) print(前两主成分累计:, np.sum(explained_var_ratio[:2]))有人习惯先算协方差矩阵 np.cov(X.T) 再对它做特征值分解结果在数值上通常一致但直接对数据矩阵做 SVD 更稳。原因在于计算协方差矩阵涉及矩阵乘法会放大数值误差尤其在特征维度高、条件数大的时候直接做 SVD 的数值稳定性明显更好。这一点 Strang 在书中也反复暗示能直接对数据矩阵操作就不要绕一道弯构造协方差矩阵。参数上需要注意的只有一点——full_matricesFalse必须带上否则对于非方阵会生成一块形状很大的全零块浪费内存和计算。2.4 SVD 和 PCA 的边界与容易用错的地方PCA 是个好东西但它有几条使用边界书里虽没有专门列出来但字里行间有提示。第一PCA 是线性方法它只能捕捉数据中的线性结构对非线性流形无能为力。你拿它处理瑞士卷数据投影结果一塌糊涂这时候该想的是 t-SNE 或 UMAP而不是换一个 PCA 变体。第二PCA 之前记得做标准化。如果特征的量纲差异大比如一列是年龄几十、一列是收入几万直接做 SVD结果会被量纲大的特征主导主成分方向基本就是收入方向年龄信息全被淹没了。Strang 讨论协方差矩阵时隐含假设了量纲一致实际数据加工时你得自己做这一步。第三个容易忽略的是中心化。很多初学者直接对原始数据矩阵做 SVD得到的第一主成分不是最大方差方向而是数据中心的方向相当于把均值项当成了信号。必须先减均值再做分解得到的奇异向量才有几何意义。我在带新人复现 PCA 时踩得最多的就是这个坑代码写出来跟教科书一模一样但图不对最后发现是忘了中心化。3. 随机梯度下降与优化Strang 给出的两条核心更新规则3.1 为什么大规模训练不能走全量梯度读完前两章你会觉得矩阵分解好看但真正让深度学习跑起来的是优化。Strang 在第六章点破了关键矛盾损失函数对所有权重求梯度理论上“导数等于零”是最优条件但实际计算中全量梯度的成本高到你无法接受——每更新一次权重都要把全部训练样本过一遍几十万样本的神经网络根本算不动。更麻烦的是Newton 法需要海森矩阵对神经网络来说海森矩阵的规模是权重数量的平方完全不可行。于是随机梯度下降SGD登场。它的核心思想是不用全部样本算梯度只随机抽一小批用这个“有噪声的梯度”近似全量梯度照样能收敛。Strang 特别强调“stochastic”这个词的含义——随机性意味着结果由概率支配而非确定性保证。抽到一批恰好不具代表性的样本时更新方向会偏离正确方向但长期来看噪声会互相抵消整体方向还是对的。这不是玄学是大数定律在优化算法上的延伸。3.2 minibatch 大小与学习率的经验法则SGD 有两个最关键的参数学习率和 minibatch 大小。Strang 在书中没有给出万能公式也不存在但从原理上给出了思考框架。学习率决定了每一步走多远太大了会在最优点附近震荡甚至发散太小了收敛慢到怀疑人生。一个常见做法是用学习率衰减策略训练前期步子大一点快速接近最优区域后期步子小一点精细收敛。具体数值上从 0.1 到 0.001 都有人用要看损失函数的尺度我自己的习惯是先拿 0.01 试跑几百步如果 loss 完全不动就把学习率调大如果 loss 剧烈震荡就调小。minibatch 大小的影响比较隐蔽。批量太大梯度估计很准但计算成本高且容易陷入尖锐极小值泛化性能反而差批量太小梯度噪声大收敛不稳定但有时这种噪声反而帮模型跳出不好的局部极值。实践中 32 或 64 是默认起点不是因为它最优而是多年经验证明它在多数任务上够用。说白了这两个参数的组合没有理论最优解多半靠实验和感觉这就是我在团队里常说的“调参玄学环节”。3.3 从损失函数到反向传播的数学链条反向传播不复杂本质就是链式法则但把它写成矩阵形式需要这本教材的铺垫。设网络输出为 F(v)损失函数记为 L反向传播要算的是 ∂L/∂Aₖ 和 ∂L/∂bₖ也就是损失相对于每一层权重矩阵和偏置向量的梯度。链式法则一层层往回传从最后一层的损失梯度开始乘以当前层激活函数的导数再乘以上一层的输出就得到这一层权重的梯度。Strang 在书中把这件事讲得特别清楚每个隐藏层的输出是 zₖ Aₖvₖ₋₁ bₖ紧接着的非线性激活是 vₖ R(zₖ)所以反向传播的每一环就是两个操作——一个线性变换的转置乘法一个逐元素激活函数导数。为什么矩阵乘法中要用转置因为正向传播是从前到后反向传播的梯度是逆向流动的维度必须通过转置来匹配。用代码写一个简单的两层网络反向传播比看十页公式更直接import numpy as np def relu(x): return np.maximum(0, x) def relu_derivative(x): return (x 0).astype(float) # 输入 4 个特征二分类任务 X np.random.randn(64, 4) y_true np.random.randint(0, 2, (64, 1)) # 初始化权重第 1 层 4-8第 2 层 8-1 # 权重初始化的尺度很重要太大容易梯度爆炸太小容易梯度消失 A1 np.random.randn(4, 8) * 0.1 b1 np.zeros((1, 8)) A2 np.random.randn(8, 1) * 0.1 b2 np.zeros((1, 1)) learning_rate 0.01 # 正向传播记录中间结果反向传播要用 z1 X A1 b1 # 第一层线性变换 v1 relu(z1) # 第一层激活 z2 v1 A2 b2 # 第二层线性变换 y_pred 1 / (1 np.exp(-z2)) # sigmoid 得到概率 # 损失二分类交叉熵 loss -np.mean(y_true * np.log(y_pred 1e-8) (1 - y_true) * np.log(1 - y_pred 1e-8)) # 反向传播从最后一层梯度开始往回推 dz2 y_pred - y_true # 交叉熵sigmoid 的复合梯度形式很简洁 dA2 v1.T dz2 # 第二层权重梯度 db2 np.sum(dz2, axis0, keepdimsTrue) dv1 dz2 A2.T # 梯度穿过线性层 dz1 dv1 * relu_derivative(z1) # 梯度穿过 ReLU dA1 X.T dz1 # 第一层权重梯度 db1 np.sum(dz1, axis0, keepdimsTrue) # 更新权重走一步梯度下降 A1 - learning_rate * dA1 b1 - learning_rate * db1 A2 - learning_rate * dA2 b2 - learning_rate * db2关键点在第一行的 sigmoid 复合梯度交叉熵损失和 sigmoid 激活组合后梯度恰好等于预测值减真实值这是数学上精心设计的结果不是巧合。如果你把损失换成均方误差梯度公式就不是这么简洁了。另外注意 ReLU 的导数——输入大于 0 时为 1否则为 0所以它天然带来稀疏性一部分神经元的梯度为 0这些神经元在本次更新中不参与学习这既降低了计算量也在一定程度上减少了过拟合。3.4 学习率太大或太小失败时看什么信号训练刚开始时loss 曲线是最好的诊断工具。学习率太大时loss 可能出现 NaN数值溢出或者上下激烈跳动根本不收敛学习率太小时loss 非常平稳地缓慢下降可能看起来“很正常”但几百轮只降了一点点——这种最容易被忽视因为它不报错还会让你误以为训练在正常进行。我一般同时跑三个学习率做对比0.001、0.01、0.1看谁先用同样步数把验证集精度拉到最高然后再在这个值附近微调比盲猜省时间得多。4. 神经网络架构从 ReLU 到卷积层的数学语言4.1 前馈网络就是一层层仿射变换加激活函数Strang 对神经网络的定义很简洁深度学习的函数形式是 F(v) L(R(L(R(...(Lv)))))每个 L 是仿射变换 Lv Av b每个 R 是逐元素非线性激活函数。矩阵 A 和偏置向量 b 就是需要学习的所有权重。这个视角对工程师特别有用你不需要把神经网络理解成一个神秘的“黑匣子”它就是数学上定义清晰的复合函数。层数越多函数的表达能力越强能拟合更复杂的模式但代价是参数增多、优化难度加大、过拟合风险上升。全连接层的参数量怎么算输入维度 m 到输出维度 n权重矩阵是 m×n加上 n 个偏置。这个数字涨得极快输入一张 256×256 的灰度图光第一层全连接接 1000 个神经元参数量就是 6500 万。Strang 在第七章里花了篇幅解释为什么卷积网络对图像任务更合适——因为自然图像有个特性局部相关性。像素与相邻像素的关系最紧密距离远的像素几乎无关。全连接层把每个像素跟所有神经元都连起来大量权重是在学习“远处的像素之间的相关性”这些参数既浪费计算也容易过拟合。4.2 ReLU 为什么成了默认激活函数先看激活函数的演进历史。S 形的 sigmoid 在早期很流行但有两个硬伤一是输出均值不为 0导致下一层收到的输入总是正的或总是负的信号在深层网络中传递时效率低二是两边饱和大值和小值区域的梯度几乎为 0反向传播时梯度连乘会指数级缩小这就是“梯度消失”。Strang 在书中指出后来人们发现把光滑但计算复杂的 sigmoid 换成极其简单的 max(0, x) 阶梯函数网络表现反而更好。ReLU 的优势是计算零成本、正区间梯度恒为 1 不存在梯度消失、天然产生稀疏激活。ReLU 有一个隐性缺点需要你在实战中提防——神经元死亡。如果某条路径的输入长期为负梯度恒为 0这个神经元就再也无法从训练中学到东西。数据里出现大面积负值、或者学习率太大时一整个层的神经元都可能“集体阵亡”。常见补救措施有 Leaky ReLU在负数区间给一个很小的斜率如 0.01保证梯度不至于完全归零。Strang 在书中给出了 ReLU 的数学定义但在工程细节上没有展开这个坑要靠实战踩过才能体会。4.3 卷积层的矩阵本质共享权重的大小革命卷积层从数学上看就是在重复使用同一组权重。Strang 给出过一个精妙的视角卷积层的权重矩阵 A 是对角常数矩阵——对角线上的元素反复出现同一个卷积核滑动到图像的不同位置用的都是同一套权重值。对比全连接层动辄百万/千万的参数量卷积层参数量往往只有几千。AlexNet 在 2012 年 ImageNet 上夺冠靠的就是这个思路把深度网络训练成了一件可行的事。对于图像数据卷积核的大小常见 3×3 或 5×5、步长stride、填充padding这三个参数决定了输出特征图的尺寸。公式很简单输出尺寸 (输入尺寸 - 卷积核尺寸 2×padding) / stride 1。这些在书中第七章有讨论虽然不会手把手教你 TensorFlow API但理解了“同一组权重在平移过程中反复作用”这个矩阵视角再去调 CNN 结构会清楚得多——为什么 1×1 卷积可以改变通道数、为什么 stride2 可以替代池化层做下采样这些都能从矩阵形状变化的角度推出来。4.4 过拟合的数学解释与正则化手段这本书前言特意警告过拟合是深度学习最大的危险之一还举了一针见血的例子用 99 次多项式去拟合 100 个点可以做到训练误差几乎为 0但测试集一测就崩。神经网络参数数量动辄比训练样本数量还多理论上完全可以“背下”所有训练样本但没有学到可泛化的模式这正是过拟合的数学本质。常用的正则化手段书里都有讨论。L2 正则化在损失函数上加上权重平方和乘以 λ迫使权重保持小值等价于对权重施加“不要太大”的先验约束。更值得实操的是 Dropout——训练时随机忽略一部分神经元Strang 在第七章把它描述为一种“每次只训练一个更小的网络”的手段多个瘦网络的集成效果优于一个胖网络。Batch Normalization 则是另一种思路它把每层输入重新调整为均值 0 方差 1保证所有层的输入尺度一致训练会稳很多。经验上我先用 Dropout 解决过拟合再用 Batch Normalization 加速收敛这两步加法比盲目堆数据更有效。5. 避坑与排查读这本书和搭模型时的七个常见问题5.1 现象SVD 和特征分解得到的向量对不上原因这两个分解对矩阵的要求不同。特征分解只对可对角化的方阵有效而 SVD 对任意矩阵都成立。当你对一个非对称矩阵做特征分解得到的特征向量并不具备正交性跟 SVD 的奇异向量不是一回事。解决处理数据矩阵时统一用 SVD不要绕道特征分解。只有面对协方差矩阵这种对称矩阵时两者才等价此时也要留意数值误差可能导致微小的不一致。5.2 现象做了 PCA 之后数据解释性变差每个主成分看不出业务含义原因PCA 本质上是在做坐标旋转主成分方向是原始特征的线性组合组合系数通常有正有负业务解释性天然就差。这是方法特性不是你代码写错了。解决如果业务上需要可解释的降维用稀疏 PCA 或因子分析如果只是为模型提速、去噪声PCA 仍然合适别指望每个主成分都有业务名称。5.3 现象SGD 训练时 loss 曲线震荡剧烈甚至出现 NaN原因学习率太大梯度更新步长跨越了损失函数的“悬崖”到达了数值不稳定的区域或者 minibatch 太小个别批次产生了异常大的梯度。解决把学习率降到当前值的 1/10 试跑 100 步观察 loss 是否稳住。同时加梯度裁剪——把梯度向量的模长限制在一个阈值如 5内防止异常批次把权重一步推到火山口。5.4 现象训练集误差很低但测试集误差很高原因过拟合模型记住了训练数据的噪音和细节没有学到可泛化的结构。神经网络参数量大于训练样本数时尤其容易出现。解决先加 Dropout从 0.2 开始试再加权重衰减L2 正则化系数从 0.0001 开始试同时看看训练样本量是否太小——数据增强也是一个思路但图像以外领域这样做要谨慎。5.5 现象模型训练速度极慢loss 下降像蜗牛原因可能是输入特征量纲差异大导致梯度更新方向被大尺度特征控制也可能是网络没有做归一化导致每层输入分布不断漂移。解决先对输入做标准化然后检查 Batch Normalization 是否加在了卷积/全连接层之后。这两个操作有时能把训练速度翻倍。5.6 现象ReLU 网络中大量神经元输出恒为 0权重更新不动原因学习率过大或者权重初始化不当导致某些神经元的输入长期为负ReLU 输出恒为 0梯度也为 0神经元永远不会再更新。解决把学习率调小换用 He 初始化替代标准正态初始化如果仍然大量死亡换 Leaky ReLU 或 ELU。5.7 现象照着书里的公式实现了算法但数值总是跟结果对不上原因书上往往展示的是理想化数学公式工程实现时还差几步数值稳定性处理比如 log 里加极小正数防止除零、矩阵形状的广播规则、浮点误差累积。这些细节书里不会逐一写。解决先用小规模随机数据跑通流程打印每一步中间变量的 shape对照公式的维度要求。shape 全对、数值不对的时候再看有没有忘掉中心化、标准化这类前置步骤。我用这个流程排查过的 bug十有八九都出在自己对公式理解不够透彻。6. 把这本书用起来阅读顺序、配套资源与一个有效的验证习惯6.1 精读顺序建议这本书结构跟传统教材不同不建议从第 1 章线性不动点开始死磕。我自己带人的经验是分三档基础扎实的读者可以从第 I 章奇异值分解读起在最短时间拿下最核心的数学工具基础一般的读者先读第 VII 章神经网络架构从反向传播的复合函数结构倒推出需要哪些数学背景再回去补前面的 SVD、概率统计和优化想解决特定问题的工程师可以直接跳到第 VI 章优化方法把随机梯度下降学透再回头补矩阵理论。书中各部分之间有强烈联系但每章也相对独立跳读完全可行。6.2 配套课程材料与动手路径教材的价值有一半在配套资源。MIT 的 18.065 课程视频可以在 MIT OpenCourseWare 找到Strang 讲的风格非常清晰——板书推导每一个关键定理而且对新手的困惑点预判极准。B 站上有带中文字幕的完整版视频链接在本书摘要里可以找到搜索“18.065”也能定位到。视频配合书的进度看先看视频再精读对应章节效果比单独啃书好得多。动手方面动手时选一个简单数据集把 PCA、SGD、两层网络各实现一遍相当于做一次全线巡检。参考 keras 做情感分类、PyTorch 做图像分类的示例项目也值得花半天过一遍不是为了学框架是看别人怎么把数学转化成工程代码。6.3 一个“从公式到代码”的双向验证习惯强烈建议你养成一个习惯每学完书里的一个算法PCA、SVD 截断、SGD、反向传播在纸上写完数学推导后立刻用 NumPy 把他实现一遍然后在同一份数据集答案做好实验。实现三层网络的推导过程验证是做一次“数学反向传播”和“数值有限差分梯度”的比较def gradient_check(model, X, y, eps1e-6): # 对模型每个参数用有限差分近似梯度与反向传播计算的真梯度对比 # 相对误差小于 1e-5 就说明反向传播实现正确 for name, param in model.params.items(): grad_analytic param.grad grad_numeric np.zeros_like(param.value) it np.nditer(param.value, flags[multi_index]) while not it.finished: idx it.multi_index old_value param.value[idx] param.value[idx] old_value eps loss_plus compute_loss(model, X, y) param.value[idx] old_value - eps loss_minus compute_loss(model, X, y) grad_numeric[idx] (loss_plus - loss_minus) / (2 * eps) param.value[idx] old_value it.iternext() relative_error np.linalg.norm(grad_analytic - grad_numeric) / \ (np.linalg.norm(grad_analytic) np.linalg.norm(grad_numeric)) assert relative_error 1e-5, f{name} 梯度检查未通过: {relative_error}这条代码做了什么事数值梯度是用定义去逼近把某个参数动一个微小量看损失变化了多少相除得到梯度的近似值解析梯度是反向传播算出来的精确值。如果两者相对误差小于 1e-5说明梯度计算正确反向传播链路上没有 bug。这个习惯能一次性验证多个环节前向传播对不对、损失函数对不对、反向传播的矩阵维度乘对没有。从那以后我每次实现新的网络结构前都强制走一遍梯度检查不通过坚决不开始训练。希望这个习惯能帮到你。本文还有配套的精品资源点击获取