简介面向人工智能初学者与进阶学习者这套由唐宇迪编著的数学基础资源包系统整理线性代数、概率统计、微积分、最优化、图论、离散数学与动态规划等七大核心模块并配有习题答案与可运行源代码。内容深入向量与矩阵运算、特征值特征向量、贝叶斯定理、导数与梯度、常见优化算法、最短路径及动态规划等关键知识点帮助读者把抽象公式与机器学习、深度学习中的实际应用衔接起来。压缩包约6.41MB以文档与代码组成方便按章节查阅与练习目前已有1927人学习下载。通过对照理论讲解、完成习题并动手运行源码读者能够理解PCA降维、SVD分解、梯度下降法、贝叶斯推断等在AI算法中的具体实现从而提升从数学原理到代码实践的转化能力。1. 人工智能数学基础先跑通代码再回头补推导我印象最深的是带一位转行做算法的同学做作业他背下了最小二乘公式但问为什么在 X^TX 求逆前要加一个很小的正则项就愣住了。这个问题恰恰是这套人工智能数学基础资源里讲得最透的地方高等数学、线性代数、概率统计、最优化四章每一章都有习题答案和配套的演示源代码。答案不是单纯给结论推导步骤旁边就是能直接运行的 demo改一个参数就能看到矩阵奇异时报错、收敛曲线发散成什么样。如果问我这套资源哪个文件最值钱我的答案不是答案文档而是那些 demo 脚本。它适合刚入门 AI、数学推导容易卡壳的开发者也适合面试前想快速把梯度、特征值、贝叶斯这些概念捡起来的人。2. 资源全景目录结构、章节编排与“答案源码”的对应关系2.1 解压之后长什么样拿到手先别急着翻答案建议先把目录结构扫一遍。这套资源按数学模块分目录命名很规整每个目录下基本都是“习题答案 演示脚本”的组合我按常见的解压结构整理如下ai_math_basic/ ├── 01_higher_math/ │ ├── 习题与答案.md │ └── demo_derivative.py ├── 02_linear_algebra/ │ ├── 习题与答案.md │ └── demo_least_squares.py ├── 03_probability_statistics/ │ ├── 习题与答案.pdf │ └── demo_gaussian_nb.py ├── 04_optimization/ │ ├── 习题与答案.md │ └── demo_gradient_descent.py ├── appendix/ │ └── numpy_pandas_ref.ipynb └── requirements.txt这四个模块的划分很经典高等数学解决“怎么求梯度、怎么理解导数”线性代数解决“矩阵运算和数据变换”概率统计解决“不确定性怎么建模”最优化解决“有了目标函数怎么求最优解”。每个模块都不是孤立存在的最优化里的梯度下降依赖高等数学的偏导最小二乘又依赖线性代数里的矩阵求逆读代码时你会不断回到前两个目录做交叉引用这是这套资源编排得比较聪明的地方。2.2 从文件命名反推课程主线这份资源的“答案 源码”并不是双轨并行而是严格对应的。比如02_linear_algebra/demo_least_squares.py对应的是答案里“正规方程推导”那部分04_optimization/demo_gradient_descent.py对应的是“梯度下降收敛性分析”那部分。也就是说每一道比较核心的习题几乎都能找到一段能跑的代码作为验证工具。我习惯拿到资源后先用一条命令把所有 markdown 答案里的公式关键词捞出来建立自己的速查索引grep -n 正则\|SVD\|贝叶斯\|梯度下降\|最小二乘 0*/习题与答案.md输出会直接告诉你每个数学概念出现在哪个目录、哪一行。别小看这一步它让我从一个“按目录翻答案”的状态切换成“按问题定位代码”的状态后者的效率高很多。这道资源的技术栈很轻主体是 Python依赖集中在 NumPy 做矩阵运算、Matplotlib 做收敛过程可视化、scikit-learn 提供 iris 等数据集。这样选择的优势很明显几乎不涉及编译和配置问题装完依赖就能跑二次开发时也容易把某个 demo 抽出来集成到自己的项目里。3. 核心模块拆解三个 demo 看懂答案背后的数学3.1 梯度下降最优化模块的收敛路径可视化04_optimization/demo_gradient_descent.py是整套资源里我最推荐先跑的文件。它用最简单的二次函数演示了梯度下降的完整过程代码会记录每一步更新时 x 的位置画到损失曲线上就是一条彩色收敛路径# demo_gradient_descent.py import numpy as np import matplotlib.pyplot as plt def f(x): return x**2 - 2 * x 1 def df(x): return 2 * x - 2 def gradient_descent(start3.0, lr0.1, epochs50): history [] x start for i in range(epochs): history.append(x) grad df(x) # 当前点的导数决定下山方向 x x - lr * grad # 沿负梯度方向更新lr 控制步长 return np.array(history), x history, final_x gradient_descent() xs np.linspace(-1, 3, 200) plt.plot(xs, f(xs), b-, labelf(x)) plt.scatter(history, f(history), crange(len(history)), cmapviridis) plt.colorbar(labeliteration) plt.xlabel(x) plt.ylabel(f(x)) plt.legend() plt.show()代码的核心就两行grad df(x)计算当前梯度x x - lr * grad做一次参数更新。lr是学习率决定每一步迈多大epochs是迭代次数决定最多走多少步。默认lr0.1时二十步左右 x 就贴近最小值 1.0把lr改成 0.9会看到 x 在最小值附近来回震荡但依然收敛改成 1.5曲线直接发散。这个 demo 对理解后面前向传播、反向传播特别有用。看代码的时候注意一点作者用的是一次函数求导后的解析式而不是数值差分这也提醒我们真正写网络训练时梯度方向解析推导比数值逼近更稳定也更快。3.2 线性代数正规方程与最小二乘02_linear_algebra/demo_least_squares.py演示的是正规方程求解线性回归参数。答案文档里那一长串矩阵推导落到代码里就是三个 API 的事# demo_least_squares.py import numpy as np def least_squares(X, y, reg1e-4): X np.asarray(X) y np.asarray(y).reshape(-1, 1) n_features X.shape[1] I np.eye(n_features) # 正规方程(X^T X reg * I)^{-1} X^T y theta np.linalg.solve(X.T X reg * I, X.T y) return theta.ravel() # 生成 100 条样本真实权重是 [2.0, -3.0] X np.random.rand(100, 2) w_true np.array([2.0, -3.0]) y X w_true 0.1 * np.random.rand(100) theta least_squares(X, y) print(estimated w:, theta)这里有两个值得注意的实现选择。第一是用了np.linalg.solve而不是np.linalg.inv直接求逆再乘上去数值误差更大还会多算一次 O(n^3) 的操作solve直接用 LU 分解解线性方程组内存占用和精度都更好。第二是加了reg1e-4的岭正则项这并非为了惩罚参数而是让X^T X在列相关时不会变成奇异矩阵说白了是数值稳定兜底。我建议你把reg改成 0 再跑一次大概率会在某次随机数据里看到LinAlgError: Singular matrix这个报错比任何公式都能解释“为什么要加正则”。3.3 概率统计高斯朴素贝叶斯的手动实现答案里最容易让人犯晕的是贝叶斯公式那一章的习题绕来绕去都是后验概率。03_probability_statistics/demo_gaussian_nb.py用 iris 数据集实现了一个简化版高斯朴素贝叶斯把公式落成了 Python# demo_gaussian_nb.py import numpy as np from sklearn.datasets import load_iris class SimpleGaussianNB: def fit(self, X, y): self.classes np.unique(y) self.mu {} self.sigma2 {} for c in self.classes: Xc X[y c] self.mu[c] Xc.mean(axis0) self.sigma2[c] Xc.var(axis0) 1e-6 return self def predict(self, X): preds [] for x in X: best_c, best_score None, -np.inf for c in self.classes: # 用 log 概率避免连乘下溢 log_p np.log(0.5) # 先验假设均匀 sigma2 self.sigma2[c] log_p -0.5 * np.sum(np.log(2 * np.pi * sigma2)) log_p -0.5 * np.sum((x - self.mu[c]) ** 2 / sigma2) if log_p best_score: best_score, best_c log_p, c preds.append(best_c) return np.array(preds) iris load_iris() X_train, y_train iris.data[:100], iris.target[:100] X_test, y_test iris.data[100:], iris.target[100:] model SimpleGaussianNB().fit(X_train, y_train) print(accuracy:, (model.predict(X_test) y_test).mean())这个实现里有两个细节值得抠。一是sigma2加了1e-6防止某个特征在某一类里方差为 0 时除零报错。二是概率密度全部在log域计算因为特征多的时候连乘概率会下溢到 0取对数后变成求和数值上安全很多。你如果在面试里被问到“朴素贝叶斯怎么防止数值下溢”这段代码就是现成的回答素材。4. 从零跑通环境配置、最小运行案例与自测脚本4.1 环境准备用 conda 隔离一套干净环境这套资源的依赖不算复杂但 NumPy 版本变动比较多我建议第一步就建一个独立环境别用系统自带的 Python不然容易跟其他项目的包冲突。推荐用 condaconda create -n ai_math python3.9 conda activate ai_math pip install -r requirements.txtrequirements.txt内容基本围绕这几类库NumPy 负责矩阵运算和随机数据生成Matplotlib 负责画收敛曲线和概率分布图scikit-learn 用来加载 iris 数据集和做结果对比pandas 在附录 notebook 里做数据整理pytest 用来跑我后面说的自测脚本。如果在内网或镜像环境下安装把 pip 源换成公司内部源即可。装完依赖后先跑一行命令确认环境没问题python -c import numpy, scipy, sklearn, matplotlib; print(env ok)这里没引入 scipy 的 demo但答案里部分习题答案会调用scipy.optimize.minimize做对比装上不亏。4.2 最小可跑通案例跑通梯度下降可视化从最简的模块开始cd 04_optimization python demo_gradient_descent.py正常运行会弹出一个窗口能看到一条蓝色损失曲线和沿着曲线往下走的彩色散点颜色越黄代表越接近迭代后期。如果你的机器是服务器或者没有图形界面脚本会直接报no display错误这时可以在脚本顶部强制切换 Matplotlib 后端import matplotlib matplotlib.use(Agg) # 不弹窗直接保存图片 import matplotlib.pyplot as plt plt.savefig(gd.png) # 把收敛路径保存成 png改成 Agg 后端后窗口不再弹出代码会在当前目录生成gd.png用任何图片查看器都能看。这一步跑通说明环境基本没问题后面三个模块都能按同样方式逐个执行。4.3 把习题答案变成 pytest 自测脚本答案看过一遍不代表懂了我建议把“看答案”改成“验答案”。最简单的做法是把答案里的核心公式写成断言跑一遍就知道自己的理解对不对。比如看完梯度下降那章可以单独建一个test_gradient.py# test_gradient.py import numpy as np def f(x): return x**2 - 2 * x 1 def df(x): return 2 * x - 2 def test_analytical_gradient(): xs np.random.uniform(-5, 5, 100) approx (f(xs 1e-6) - f(xs - 1e-6)) / (2e-6) assert np.allclose(approx, df(xs), atol1e-5)在终端执行pytest test_gradient.py绿色通过就说明你抄的解析梯度公式没有抄错。这样做的好处是网上很多答案里公式符号抄反了、少了个负号手写验算很难发现但数值对比一跑就知道。建议每个章节学完后都仿照这个模式把核心公式变成 3~5 个 pytest 用例既能复习后续也能当作自己的数学算法回归测试集。5. 避坑指南跑这套资源最容易翻车的五个地方5.1 Matplotlib 中文标签变成方块乱码现象运行 demo 后图片上轴标签和中文字体全部变成一个个空心方块。原因Matplotlib 默认字体配置里没有映射中文字体系统找不到可用的 CJK 字体于是用方框代替。解决在代码开头加上全局字体配置import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False如果是在 Linux 服务器上SimHei 不一定存在先用fc-list :langzh查看系统中文字体名把SimHei替换成实际值比如Noto Sans CJK SC。我在 Ubuntu 上翻车过一次就是因为手动改成了SimHei但系统根本没装这个字体。5.2 梯度下降动画只显示最后一张图看不到收敛过程现象plt.show()弹出来的窗口只有一条曲线和最后一步的散点看不到中间过程。原因脚本里所有历史点都叠加画在了一张图上没有逐帧刷新所以直观上感觉动画缺失。解决改用交互模式刷新plt.ion() for i in range(len(history)): plt.cla() plt.plot(xs, f(xs), b-) plt.scatter(history[:i1], f(history[:i1]), cred) plt.pause(0.05) plt.ioff() plt.show()plt.ion()开启交互模式plt.pause(0.05)让画面停留 50 毫秒这样就能看到点一步步滑向最低点。还有一种更省事的方案是用matplotlib.animation.FuncAnimation一帧一帧保存成 gif适合放进博客或汇报材料里。5.3 NumPy 旧 API 报错module numpy has no attribute float现象运行某个章节代码时报AttributeError: module numpy has no attribute float。原因NumPy 1.24 之后移除了np.float、np.int之类的别名旧教程或旧 demo 里如果直接写np.float就会翻车。解决全局搜索脚本里的np.float和np.int替换成 Python 原生float和int。如果是随机数生成器相关报错把np.random.RandomState换成np.random.default_rng()后者的随机数生成算法更现代推荐新项目统一用新写法。5.4 相对路径加载数据失败FileNotFoundError现象运行demo_least_squares.py或读取data.csv时报文件不存在但文件明明就在脚本旁边。原因在 IDE 或终端里运行时当前工作目录并不是脚本所在的目录相对路径data.csv会基于工作目录解析结果找不到文件。解决在脚本开头把基准路径固定到脚本位置from pathlib import Path BASE_DIR Path(__file__).resolve().parent data pd.read_csv(BASE_DIR / data.csv, encodingutf-8)这样不管用什么方式运行都不会因为工作目录不对而翻车。这也是我拿到任何项目源码后第一个习惯性操作把所有相对路径统一改成基于__file__的路径。5.5 PDF 答案文档复制出来公式乱码现象从 PDF 版习题答案里复制公式到编辑器得到的是x_i^(2)或者干脆是乱码。原因PDF 里的公式通常不是文本层而是矢量图形或者嵌入字体子集复制时拿到的 Unicode 映射是错的。解决优先看同目录下有没有 Markdown 版本的答案比如习题与答案.md如果只有 PDF可以试试pdftotext -layout 习题与答案.pdf -看看文本层是否完整。公式乱码的部分不要硬抠直接把 PDF 截图对照代码看既快又不容易出错。我一般把公式截图存在本地和代码注释放在一起复习时只看图片不看 PDF。6. 二次开发把习题答案改造成你自己的题库引擎这套资源的价值除了刷一遍更在于你能把它变成长期使用的题库。改造思路很简单把答案从 PDF 变成结构化数据再写一个随机抽题和自动判题的脚本。6.1 从答案文档到题库 JSON我习惯先把每章的题目整理成统一结构字段包括章节、主题、难度、答案、验证代码路径{ id: la-001, chapter: 线性代数, topic: 最小二乘与正规方程, difficulty: 3, answer: theta (X^T X lambda I)^{-1} X^T y, code: demo_least_squares.py }code字段是关键它把题目和 demo 脚本绑定起来遇到不会的题可以直接跑代码复现不用翻回资源包找。6.2 随机组卷与自动判题有了结构化数据组卷和判题就很简单了import json import random with open(questions.json, r, encodingutf-8) as fp: bank json.load(fp) def make_paper(chapterNone, n10, seedNone): pool [q for q in bank if chapter is None or q[chapter] chapter] if seed is not None: random.seed(seed) return random.sample(pool, min(n, len(pool))) def check_answer(user_answer, ground_truth, atol1e-4): if isinstance(ground_truth, str): return user_answer.strip().lower() ground_truth.strip().lower() return abs(user_answer - ground_truth) atol数值型答案用容差比较避免浮点误差误判字符串型答案做归一化后比较大小写和首尾空格不会影响结果。seed参数保证同一次组卷结果可复现方便跟同学讨论同一套题。从那以后我每次拿到新资源第一步都改成“跑通所有 demo把答案验证一遍再写进题库”不再直接翻结论。这个习惯帮我过滤了不少网上流传的“抄错答案”也让我把一次性下载的资料真正沉淀成了能反复用的东西。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?