机器学习线性代数基础:Python代码实战解析

发布时间:2026/9/8 2:54:39
机器学习线性代数基础:Python代码实战解析 简介这份资源是《机器学习线性代数基础Python语言描述》一书的配套代码包适合正在学习机器学习数学基础、希望用Python动手验证线性代数概念的读者。压缩包共53个文件以50个.py脚本为核心辅以1份docx格式的Numpy科学计算库说明、1个score.csv数据文件及1张test.PNG示例图资源整体仅2.48MB轻量便携。代码按第1章至第7章组织覆盖向量、矩阵、特征值、SVD等核心知识点每章提供多个示例程序可直接运行并对照观察输出帮助理解抽象理论与代码实现之间的对应关系。对于阅读原书时希望边学边练、快速跑通示例的读者这套代码能有效节省手动敲码时间并可作为自行扩展实验的起点。目前已有179人浏览学习适合作为配套自学参考资源。 拿到张雨萌老师的《机器学习线性代数基础Python语言描述》配套代码时我最直观的感受是这本书终于把“数学书”和“代码书”的边界打通了。国内讲机器学习的教材不少但涉及数学基础时大多数要么直接堆公式推导要么一笔带过让你去看线性代数课本真正愿意用Python代码把抽象概念一个个“跑”出来给你看的确实不多。而这套配套代码的价值就在于它把向量、矩阵、特征分解、SVD这些机器学习里高频使用的数学工具变成了你可以亲手修改、运行、观察输出的实验对象。我身边有不少朋友在入门机器学习时卡住的往往不是算法本身而是算法背后那一堆矩阵运算和范数符号。你用numpy调一行np.linalg.eig()毫不费力但不明白特征值到底在“分解”什么换到推荐系统、PCA降维、PageRank这些场景时就会发虚。这套代码和书籍的搭配实际是想解决一个问题让机器学习的初学者能“肉眼看到”线性代数在算法里的具体作用。它适合三类人一是刚接触机器学习、数学基础薄弱的自学者二是想补线性代数短板、准备面试的求职者三是教学场景里需要大量示例代码的讲师或培训老师。接下来我会基于这套代码的实际内容从环境搭建、核心模块拆解、实操过程到常见问题完整梳理一遍这套代码的正确打开方式。1. 配套代码到底在讲什么从抽象符号到可运行实验1.1 机器学习里的线性代数为什么绕不开绝大多数机器学习算法最终都能归结为“对矩阵和向量做计算”。线性回归是求解线性方程组的近似解PCA是求协方差矩阵的特征向量神经网络的正向传播本质上是矩阵连乘注意力机制里那堆QKV依然是向量内积和缩放。可以说线性代数就是机器学习算法的“底层汇编语言”。但这门语言有一个比较麻烦的特点教材上的符号系统太抽象了。A^T A、||x||_2、λ_max这些符号在纸面上推导一百遍你可能依然想象不出它们在数据里到底提取了什么。而Python配套代码的好处在于你可以直接构造一个真实的矩阵调用SVD分解然后把分解出来的U、Σ、V矩阵打印出来甚至画成图直观看到奇异值是怎么从大到小排列的、前几个奇异值对应的向量又捕获了什么结构。这种“符号变成数据、公式变成输出”的转变是这套代码最大的价值。1.2 配书代码的学习价值不是“抄一遍”而是“改一遍”很多学习者拿到配套代码后习惯的做法是jupyter notebook里从上到下运行一遍看到输出结果和书上一模一样就觉得自己“会了”。但根据我自己带人的经验哪怕把代码抄写十遍不如认真改动一个参数、观察结果变化来得好。这套代码在设计上其实留了不少“可动手”的口子。比如在讲解向量内积和夹角时代码往往会构造两个具体向量然后输出夹角余弦值。你可以把其中一个向量换成零向量看看会发生什么或者把二维向量扩展到三维、四维验证高维空间里“所有向量都近乎正交”这个反直觉的结论。配套代码不只是一个标准答案库更是一组实验脚手架——用好了你等于拥有一个小型线性代数实验室。2. 跑通配套代码前的环境准备Python工具链的那些“坑”2.1 Python版本与核心依赖库选择这套配套代码基于Python编写核心依赖是numpy、matplotlib部分章节可能用到scikit-learn或pandas。我在实际安装和复现过程中环境配置这块确实踩过一些坑整理一下供大家参考。Python版本建议使用Python 3.8到3.11之间的版本。太老的版本如3.6在安装新版numpy时可能找不到预编译包太新的版本如3.12刚发布时则可能遇到某些依赖库尚未适配的情况。numpy版本不要盲目追求最新版。numpy 1.21到1.24之间比较稳定如果安装了numpy 2.x某些老代码中使用的np.float、np.int这类别名会直接报错这是最常见的兼容性问题。matplotlib建议使用3.5以上版本绘图接口和中文支持更完善。其他可选依赖如果你想把书里某些图形画得更丰富可以安装seaborn做统计图美化如果涉及PCA应用scikit-learn会非常方便。安装命令可以直接用pip install numpy matplotlib scikit-learn如果你在国内容器环境或内网环境安装建议配置好镜像源用清华或阿里云的PyPI镜像能省去不少超时重试的烦恼。安装完成后执行下面这段代码可以快速验证环境是否正常import numpy as np import matplotlib.pyplot as plt a np.array([1, 2, 3]) b np.array([4, 5, 6]) print(向量内积:, np.dot(a, b)) # 简单绘图验证 plt.plot([0, a[0]], [0, a[1]], labela) plt.axis(equal) plt.legend() plt.show()如果内积输出32并且能弹出坐标轴图形说明环境基本OK。这里有两个细节值得注意一是我建议用conda创建独立虚拟环境不要直接装在系统全局因为后面你肯定会装PyTorch、TensorFlow这类重量级库互相污染版本是家常便饭二是绘图时如果中文显示为方块需要额外设置中文字体后面我会专门讲这个问题。2.2 推荐的IDE和运行方式Jupyter Notebook是首选配书代码的定位是“边看边实验”所以强烈推荐使用Jupyter Notebook或Jupyter Lab来运行。原因很简单线性代数的学习强调“分步观察”——一个矩阵分解过程你拆成六个单元格逐个运行每一步都能查看中间矩阵的形态直接用.py脚本一次性跑完观察粒度就太粗了。如果你之前只装了Anaconda打开Anaconda Prompt后输入jupyter lab浏览器会自动弹出工作台界面。在界面里新建一个Python 3内核的Notebook然后把你下载的配套代码.ipynb文件上传进去逐个单元运行即可。如果遇到内核一直连不上或卡死多半是pyzmq版本冲突。解决方法是pip install --upgrade pyzmq另外vscode也是不错的选择安装Python插件和Jupyter插件后可以直接在.ipynb文件里运行单元格而且调试功能比浏览器版Jupyter强很多适合需要单步跟踪的问题。不过对于首次接触这套代码的人Jupyter Notebook的简洁界面会更友好不会一开始就被工具栏和配置文件劝退。3. 核心模块拆解这套代码里最值得反复研究的几块内容3.1 向量与矩阵的表示从Python列表到numpy数组配书代码最开始的部分通常是从“如何用Python代码表示向量和矩阵”切入的。初学者容易把思维停留在小学算术层面用列表套列表硬造矩阵。但实际上numpy数组和Python列表的根本区别在于numpy数组支持向量化计算和广播机制。比如计算两个向量逐元素相乘用列表推导式你要写c [a[i] * b[i] for i in range(len(a))]而用numpy数组只需要c a * b代码量少了更关键的是性能差异——数据规模到百万级时向量化计算可能会快几十倍。配书代码在向量内积、矩阵乘法、转置、逆矩阵这些基础操作上都会给出对比示例我建议你在跑这些代码时特意关注shape属性。一个维度对不上的矩阵相乘会报ValueError这个报错几乎是你未来跟numpy打交道时最常遇到的“朋友”——通过反复调整维度来理解“矩阵乘法要求左矩阵列数等于右矩阵行数”这个规则比背十遍定义都管用。3.2 范数、内积与正交性理解距离和角度的几何意义机器学习模型里范数几乎是度量一切的工具误差是范数正则化是范数向量的“大小”也是范数。配书代码在范数部分通常会演示np.linalg.norm()的多种用法比如计算二范数、一范数和无穷范数。我建议你在跑这部分代码时特别关注一个容易被忽略的概念单位向量与向量单位化。代码里可能会出现把任意向量除以它的范数、得到一个方向相同但长度为1的向量的过程。这在机器学习的特征缩放、权重初始化里都有直接应用。配合matplotlib画出原始向量和单位向量的对比图那种“向量方向不变但大小归一”的几何直觉会一下子建立起来。正交性的部分同样值得深挖。正交向量意味着内积为零也就意味着两向量之间没有线性相关性。配书代码会用一组例子展示正交基在高维空间中具有很好的独立性可以简化很多计算。PCA主成分分析的核心其实就是在数据协方差矩阵的特征向量中找出一组正交基所以这一小节的铺垫意义重大。3.3 特征分解与奇异值分解机器学习的“隐藏引擎”特征值分解和SVD是这套代码的“重头戏”也是很多自学者最容易变成“调包侠”的部分。代码里会用np.linalg.eig()和np.linalg.svd()对同一个矩阵做分解然后详细展示分解结果的shape和数值。这里有一个关键区别值得你反复实验特征分解只适用于方阵而SVD适用于任意矩阵。实际数据里我们的特征矩阵大多是“样本数×特征数”的矩形比如1000个样本、20个特征那就是1000×20的矩阵此时SVD才是通用的分解工具。配书代码通常会用一张图像比如把图片变成像素矩阵来做SVD然后只保留前k个奇异值重建图像让你直观看到“低秩近似”丢掉了什么、保留了什举。这个实验效果非常震撼k10时图像还很模糊k50时已经能辨认轮廓k100时几乎接近原图。这个过程能让你理解为什么PCA能够降维——因为它本质上就是去掉那些奇异值很小、对整体结构贡献很低的方向。4. 实操指南从配书代码到自主实验的完整路径4.1 五步跑通第一个SVD图像压缩实验这里我以配书代码里最有趣的SVD图像压缩实验为例讲解从准备数据到观察输出的完整流程。第一步准备数据。如果你不想找外部图片直接用代码内置的小像素矩阵也完全够用。不过为了效果我建议下载一张64×64的灰度图转换成numpy数组from PIL import Image import numpy as np img Image.open(sample.jpg).convert(L) A np.array(img) print(A.shape) # (64, 64)第二步进行SVD分解U, S, Vt np.linalg.svd(A)注意这里S返回的是一维数组而不是对角矩阵。如果需要矩阵形式可以用np.diag(S)转换。第三步取前k个奇异值重建图像k 10 A_reconstructed U[:, :k] np.diag(S[:k]) Vt[:k, :]这行代码就是SVD压缩的核心公式A ≈ U_k Σ_k V_k^T。代码运行时可以打印S的前10个值你会发现衰减非常快——第一个奇异值可能是几百第二个就变成几十了这正是图像中主要结构集中在前几个奇异值上的证据。第四步可视化对比。把原图和k取不同值的重建图并排画出来import matplotlib.pyplot as plt plt.figure(figsize(8, 4)) plt.subplot(1, 3, 1) plt.imshow(A, cmapgray) plt.title(Original) plt.subplot(1, 3, 2) plt.imshow(A_reconstructed, cmapgray) plt.title(fk{k}) plt.show()第五步观察并记录k10时图像保留了哪些信息边缘是否锐利奇异值小到多少时视觉上开始不可接受把这些问题随手记录下来就是一份非常好的学习笔记。如果你嫌计算太慢或内存占用大可以用sklearn.utils.extmath.randomized_svd来做随机化SVD大数据集上能提速不少。4.2 可视化辅助理解让抽象的数学“看得见”配书代码里大量使用matplotlib绘制向量图、散点图和三维图这一部分非常值得花时间逐行研究。拿向量加法和线性组合来说代码会画出两个箭头向量以及它们的和向量运行之后你会“啊……”一声原来平行四边形法则用坐标表示就是逐元素相加没有任何神秘。再比如矩阵乘法代码可以把矩阵视为线性变换然后画出一组基向量比如x轴和y轴的单位向量在变换前后的位置变化。当矩阵的行列式为负时你会看到基向量的“手性”翻转这比单纯背公式理解深刻得多。可视化还有一个实用小技巧在Jupyter里用%matplotlib inline可以内嵌显示图形但如果你想交互式旋转三维图用%matplotlib notebook或%matplotlib widget更合适。建议两个都试一下找到自己舒服的交互模式。另外注意如果图上中文显示为乱码方块需要在代码开头加上import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] # 或用你系统里的中文字体名 plt.rcParams[axes.unicode_minus] False第二条unicode_minus很关键不设的话坐标轴的负号会显示成一个异常的方块。5. 常见问题与排查技巧实录照着这份清单能省一半时间5.1 环境与依赖问题报错多半就这几类在带学员和实际复现过程中我整理了这套配书代码最常遇到的几个环境类问题集中放在下面问题现象可能原因解决方法ModuleNotFoundError: No module named numpy当前环境没有numpy或用了错误的conda环境conda activate 环境名后重新pip install numpyAttributeError: module numpy has no attribute floatnumpy 2.x移除了旧别名安装numpy1.24.3或把代码里的np.float改成float中文字体显示为方块matplotlib默认字体不含中文使用plt.rcParams[font.sans-serif] [SimHei]配置ValueError: shapes (m,n) and (p,q) not aligned矩阵乘法的维度不匹配打印两个矩阵的shape检查是否满足左列右行Jupyter内核频繁崩溃pyzmq版本冲突或内存不足升级pyzmq减少一次性创建的矩阵规模LinAlgError: Matrix is singular矩阵不可逆行列式为0检查是否有重复行/列加上微小单位阵扰动后再求逆遇到过多次的情况是初学者在conda的base环境里运行但base环境里的Python是系统的pip却是另一个路径的。建议所有项目都用独立环境管理不要默认用base。5.2 理论与实践衔接的误区代码跑通不等于学会运行代码环节没问题之后真正的难点出现在“动手写自己的代码”时。比如配书代码里讲完特征分解后会布置一个“用特征分解求矩阵的n次幂”的小练习。很多学员直接对矩阵做特征分解然后取np.diag(S)**n却忘记要乘回特征向量矩阵。这暴露出一个常见误区知道API的用法但不理解API背后的数学流程。我建议你学每一节时都问自己三个问题这里的输入是什么输出是什么中间走过了什么步骤如果能把三个问题口述清楚说明确实掌握了而不是只“见过”这段代码。还有一个不错的检验方法把代码里的示例矩阵换成实际业务数据。比如你本来在二维人造数据上跑PCA试着把它换成手写数字数据集里的某张图片一样能降维而且重构效果更直观。这种迁移实验做上两三次理论和实践才算真正焊在了一起。写在最后这套代码我推荐怎么用根据我带过的学员和我自己重读这本书的经验一套比较有效的学习路线是先不看代码把书上每章后面的思考题自己拿纸推一遍然后打开配套代码把推不出来的地方在代码里画图观察接着随意改参数观察输出的变化最后合上代码从头自己实现一遍核心函数哪怕是直接调用numpy也比你复制粘贴收获大得多。我在实际使用中发现这套代码的很多范例用了很多人造小数据图形好看、规律明显但它和真实世界的“脏数据”之间还有一段距离。所以学完之后一定要自己去UCI或Kaggle找一个真实数据集把书里的PCA、SVD、线性回归这些方法套上去跑一遍。只有真正从混乱数据中提取出有意义的结构你才会理解线性代数为机器学习提供的那套“坐标系统”到底有多重要。最后分享一个我自己的小习惯每学完一个概念就在笔记本上画一个“数学符号↔numpy函数↔算法场景”的映射表。比如λ_max ↔ np.linalg.eigvals(A).max() ↔ PageRank主特征向量||x||_2 ↔ np.linalg.norm(x) ↔ MSE误差计算。这个表整理完你会发现机器学习的很多公式突然变得具体起来——原来每个数学符号背后都有一个Python函数在等着你而配书代码就是帮你建立这些映射的最好起点。本文还有配套的精品资源点击获取