资讯详情

人工智能数学基础:习题答案与NumPy代码验证实战

📅 2026/10/30 15:54:52 | 华诺云谱 👁 阅读
人工智能数学基础:习题答案与NumPy代码验证实战
简介这份面向人工智能学习者与转岗从业者的数学基础资料包围绕唐宇迪相关课程内容整理重点解决线性代数、概率论与统计、微积分、最优化理论等知识“看得懂却不会用”的问题并借助习题答案与配套源代码把公式推导落到编程实践中。压缩包约6.41MB上游文件总数与类型明细暂无有效数据从资源构成看包含习题解答与代码示例便于对照学习。已有1930人学习说明其在AI数学入门与复习场景中具有一定参考价值。读者可系统梳理向量矩阵、概率分布、梯度下降、牛顿法、图论与动态规划等核心概念并通过答案核对思路、通过代码观察算法实现适合作为课程配套练习、面试前数学复习和项目建模前的知识查漏材料。1. 从一份“数学补课包”说起这套资料到底给谁用有个做算法的朋友转行第二年模型调不动的时候回头翻人工智能数学基础发现当年课堂上的公式全成了黑匣子——知道梯度要下降说不清为什么沿负梯度方向走最快知道要算特征值手推一遍就卡在行列式展开。他后来拿到这套配套资料包习题答案和源代码放在一起对照着啃两周把卡了半年的几个点捋顺了。这份资源适合两类人一类是正在学人工智能数学基础、课后习题做不下去想核对推导过程的学生另一类是已经上手写模型、但底层数学只有模糊印象的工程开发者想用可运行的代码把公式重新“摸”一遍。资料按章节组织答案给推导代码给验证两边对着看比单啃教材省力。2. 资料包结构拆解习题答案与源代码怎么对上号拿到压缩包先别急着全解压到桌面先看清分层逻辑。这类配套资料一般按“章—知识点—题号”三层组织答案文档和代码文件用同一套编号能不能对上号直接决定后面阅读效率。2.1 目录分层与文件命名规律解压后的结构大致是这样不同章节的题量不一样但骨架一致math-for-ai/ ├── ch02_linear_algebra/ │ ├── answers/ │ │ ├── 2-1_matrix_basic.md │ │ ├── 2-5_eigen.md │ │ └── 2-8_svd.md │ └── code/ │ ├── ex2_1_matrix_basic.py │ ├── ex2_5_eigen.py │ └── ex2_8_svd.py ├── ch03_calculus/ │ ├── answers/ │ └── code/ ├── ch04_probability/ │ ├── answers/ │ └── code/ ├── requirements.txt └── README.md命名上有一条规律值得记住章节号-题号_知识点英文缩写。前半段是定位后半段是检索用的。答案文档用.md存方便直接在编辑器里看公式渲染代码文件用ex前缀跟答案的题号一一对应。我一般先扫一遍answers目录把文件名当目录页用哪题想深挖再去code里找同名文件。这个习惯比从头读到尾快得多尤其是第二遍复习的时候。有一类文件容易看漏某些章节下面会有extra/或者appendix/目录放的是教材正文里没编号的补充例题编号可能是2-x1这种。这些题往往对应更完整的工程实现别跳过。2.2 答案文档与代码文件的映射关系答案文档里通常有三段结构题目复述、推导过程、结论。代码文件对应的是第三段的验证。举个典型例子答案里写“矩阵 A 的特征值为 λ₁3, λ₂1”代码里就会构造这个 A 然后调np.linalg.eig打出来对比。这种一对一关系是这份资料最有价值的地方——它把“我推出来的对不对”变成了可执行的问题。但不是所有题都有代码。纯推导题比如证明某个不等式成立通常只有答案文档代码目录里找不到同名文件。我建议做个简单判断answers里有的、code里没有的标记为“纯推导”读的时候专注逻辑链两边都有的优先跑代码跑通再回头读推导理解成本会低很多。还有一种情况一个代码文件对应多道题。比如ex3_2_gradient.py里可能同时验证了 3-2、3-3、3-4 三题的结论因为它们共用同一个函数和同一组数据。这时候看代码开头的注释通常会写明“对应习题 3-2 / 3-3 / 3-4”。养成先看文件头注释的习惯能省掉不少来回翻找的时间。如果发现答案和代码的结论对不上先别怀疑自己。这类资料常见的偏差是答案用手算精确值代码用浮点近似两者在小数点后几位有差异是正常的。判断标准看相对误差量级在1e-8以内就当一致。2.3 环境准备与第一次跑通代码基本是 Python NumPy 的组合少量章节会用到 SciPy 和 Matplotlib 画图。不要直接在系统 Python 里装容易和已有环境打架。建个独立环境把依赖一次装齐# 建独立环境Python 版本别太低3.8 以上基本都能跑 python -m venv venv_math source venv_math/bin/activate # Windows 用 venv_math\Scripts\activate # 装依赖numpy 和 scipy 是必需的 pip install numpy scipy matplotlib # 锁定版本避免后续 pip 升级把代码跑崩 pip freeze requirements.lock装完之后先别急着跑具体章节把requirements.txt里的版本对一遍。这类资料包常见的坑是作者写代码时的 NumPy 是 1.x你装到 2.x 之后某些 API 行为变了比如np.float这类别名被移除直接报AttributeError。碰到这种两个选择把 NumPy 降到 1.26 附近或者手工把代码里的旧别名改掉。环境好了之后先跑一个最简单的验证脚本确认链路通import numpy as np # 构造一个 2x2 矩阵验证环境是否正常 A np.array([[2.0, 1.0], [1.0, 2.0]]) # 对称矩阵特征值必然是实数 eigvals, eigvecs np.linalg.eig(A) print(特征值:, eigvals) print(特征向量:\n, eigvecs) # 验证 A v lambda * v残差应接近 0 for i in range(len(eigvals)): v eigvecs[:, i] residual A v - eigvals[i] * v print(f第 {i} 个特征向量残差范数: {np.linalg.norm(residual):.2e})这段代码干了三件事构造矩阵、求特征分解、用定义式Av λv反验。最后那行残差范数是关键它把“特征向量算得对不对”变成了一个数值指标正常输出应该在1e-15量级。如果跑到这里就是一堆nan或者残差是1e-1级别说明环境或者代码有问题先解决再往下走。np.linalg.eig返回的eigvals是特征值数组eigvecs是按列存放的特征向量矩阵取第 i 个向量要用eigvecs[:, i]这个索引方向搞反是新手高频错误。residual那个变量名可以改但建议保留打印格式里的科学计数法1e-15和1e-3一眼就能分出对错比直接打浮点数直观。3. 核心模块实战把线性代数与微积分的推导写成可执行代码数学资料最容易读成“看懂了但不会用”。这一层的关键是把每个公式落到一次具体的计算上让代码替你检查推导。下面挑三个在人工智能里出现频率最高的点按资料包的思路走一遍。3.1 矩阵运算与特征值分解从笔算到 NumPy 校验线性代数章节的习题里特征值分解是重灾区。手算 3x3 矩阵的特征多项式就已经很烦算完还得解三次方程。代码的价值不是替你算而是让你确认自己算的那个 λ 到底对不对。import numpy as np # 3x3 对称矩阵手算特征多项式从这里开始 A np.array([[4.0, 1.0, 1.0], [1.0, 3.0, 0.0], [1.0, 0.0, 2.0]]) # 检查对称性对称矩阵的特征值一定是实数 assert np.allclose(A, A.T), 矩阵不对称特征值可能是复数 eigvals, eigvecs np.linalg.eig(A) # 对称矩阵理论上特征值为实数取实部规避浮点噪声 eigvals np.real(eigvals) print(特征值:, np.sort(eigvals)) # 特征值之和等于迹之积等于行列式这两个是必查的恒等式 trace_err abs(eigvals.sum() - np.trace(A)) det_err abs(eigvals.prod() - np.linalg.det(A)) print(f迹校验误差: {trace_err:.2e}) print(f行列式校验误差: {det_err:.2e}) # 特征向量正交性检查对称矩阵不同特征值对应的特征向量必然正交 V np.real(eigvecs) gram V.T V print(特征向量内积矩阵:\n, np.round(gram, 6))这段的重点在后面三个校验不是np.linalg.eig本身。np.trace(A)是矩阵的迹等于所有特征值之和np.linalg.det(A)是行列式等于所有特征值之积。这两个恒等式是手算之后最省事的自检手段误差在1e-12以内就说明特征值算对了。最后的V.T V得到的是特征向量之间的内积矩阵对称矩阵的情况下应该接近单位阵对角为 1非对角为 0这一步能查出特征向量是否真的正交。参数上有一点要注意np.linalg.eig不保证返回顺序所以想比对具体某个 λ 对应的向量得先排序或者按索引找。我一般用np.argsort(eigvals)拿到排序索引再同时重排特征值和特征向量避免两者错位。如果跑到assert就挂了说明构造的矩阵本身不是对称的回头检查录入。这类手输矩阵的题翻车八成是因为某个元素符号写反了。3.2 梯度下降与导数的数值验证微积分章节在人工智能里的落点基本就是梯度。资料里的推导会告诉你f(x)怎么求代码要回答的是“我求的这个导数公式对不对”。最稳的办法是中心差分用数值梯度去逼近解析梯度import numpy as np def f(x): # 目标函数选一个导数好推的f(x) x^3 - 2x^2 1 return x**3 - 2 * x**2 1 def grad_analytic(x): # 手推的解析梯度3x^2 - 4x return 3 * x**2 - 4 * x def grad_numeric(x, h1e-6): # 中心差分精度比前向差分高一个量级 return (f(x h) - f(x - h)) / (2 * h) # 在若干个点上比对解析梯度和数值梯度 for x in [-1.0, 0.0, 0.5, 1.5, 2.0]: ga grad_analytic(x) gn grad_numeric(x) rel_err abs(ga - gn) / max(abs(ga), abs(gn), 1e-12) print(fx{x:4} 解析{ga:8.4f} 数值{gn:8.4f} 相对误差{rel_err:.2e})h的取值是个技术活。取太大差商逼近不准取太小f(xh) - f(x-h)两个相近的数相减会产生有效数字丢失。1e-6是个比较稳的折中相对误差一般在1e-10到1e-8之间。如果某个点上误差突然跳到1e-3量级大概率是那个点的梯度值本身接近 0分母太小把误差放大了——这时候看绝对误差更合理。max(abs(ga), abs(gn), 1e-12)里的1e-12是防止除零梯度恰好为 0 的点比如x0如果直接用相对误差会炸。有了这个校验器后面手推任何复杂函数的梯度都能套进来验。资料里那些多元函数的偏导题可以逐个变量做中心差分把其他变量固定住思路完全一样。我一般会把grad_numeric单独抽成一个工具函数放在utils.py里做二次开发时反复用。顺带说一句梯度下降本身def gradient_descent(start, lr0.1, steps50, tol1e-8): x start history [x] for _ in range(steps): g grad_analytic(x) if abs(g) tol: # 梯度足够小认为收敛 break x x - lr * g # 沿负梯度方向更新 history.append(x) return x, history x_star, path gradient_descent(start3.0, lr0.1) print(f收敛点: {x_star:.6f}, 迭代次数: {len(path)-1})lr是学习率tol是收敛阈值steps是硬性上限防止死循环。这个函数f(x) x³ - 2x² 1有两个驻点x0极大、x4/3极小从3.0出发应该收敛到4/3附近。从-1.0出发就会掉进0这个极大值点这是数学本身的坑不是代码的——资料里的相关习题正好用来说明“梯度下降只能找到局部最优”跑一遍比背结论印象深。3.3 概率分布与最大似然把公式落到采样上概率章节的习题里最大似然估计是最容易“会推不会用”的部分。答案里给的是求导令其为零这一步代码要做的是用采样数据反过来验证这个估计量。import numpy as np rng np.random.default_rng(42) # 固定种子保证结果可复现 # 伯努利分布成功概率真实值设为 0.3 p_true 0.3 n 200 samples rng.binomial(1, p_true, sizen) # 伯努利的最大似然估计就是样本均值这里直接算 p_hat samples.mean() print(f真实 p{p_true}, 估计 p_hat{p_hat:.4f}, 样本量{n}) # 用对数似然函数验证把 p 扫描一遍看极大值点在哪 ps np.linspace(0.01, 0.99, 200) # 对数似然 L(p) k*log(p) (n-k)*log(1-p)k 为成功次数 k samples.sum() log_lik k * np.log(ps) (n - k) * np.log(1 - ps) p_mle ps[np.argmax(log_lik)] print(f扫描得到的极大似然点: {p_mle:.4f})rng.binomial(1, p_true, sizen)生成 n 个 0/1 样本1表示成功。samples.mean()直接给出闭式解的估计值k * np.log(ps) (n-k) * np.log(1-ps)是对数似然在参数空间上的扫描。两条路得到的结果应该一致差在小数点后三位以内。如果不一致先检查k是不是用samples.sum()算的。ps的取值范围要避开 0 和 1否则log(0)会给-inf。这个细节在真跑的时候很容易被忽略尤其是教材上用闭区间写公式的时候。高斯分布那一节同理把np.log换成高斯对数似然然后在(mu, sigma)二维网格上取argmax能直观看到似然曲面的形状。这类“扫描 取极大”的写法虽然笨但胜在不用推解析解也能验证结论资料里凡是标注了“可用数值方法验证”的题都能套这个模板。4. 排查手册跑这份资料时最容易翻车的五处这份资料包本身不复杂但“能打开”和“能跑对”是两回事。下面五条是我在实际操作里反复遇到的按现象、原因、解决依次写清楚。4.1 报AttributeError: module numpy has no attribute float现象代码在import numpy之后、执行到某一行突然挂掉报错信息指向np.float或np.int、np.bool。原因资料里的代码是较早版本写的那几个别名在 NumPy 1.24 之后被标记弃用2.0 之后彻底移除。新版环境直接跑旧代码必然报这个。解决全局搜一遍np.float、np.int、np.bool替换成内置的float、int、bool。数量不多的话手工改最省事文件多就写个正则批量替换但改完必须逐一跑一遍因为某些地方可能是np.float64被误伤。4.2 矩阵维度对不上shapes not aligned现象A B或者np.dot(A, B)报维度不匹配提示里给出的两个形状看着像能乘但就是不行。原因两个可能。一是从答案文档里抄矩阵时行数或列数漏了一行二是 NumPy 里一维数组既不是行向量也不是列向量(3,)和(3,1)是两回事跟(3,3)乘的时候行为不同。解决在每次乘法前加print(A.shape, B.shape)先看清形状。一维数组想当列向量用显式写A.reshape(-1, 1)想当行向量用写A.reshape(1, -1)。别指望 NumPy 自动推断把形状写死能省掉一半调试时间。4.3 特征值结果和答案对不上差一个符号现象手算得到λ 2代码打出来是-2或者特征向量整体反向。原因特征向量的方向本来就不唯一v和-v都是合法解不同库或者同一库的不同版本返回的方向可能相反。特征值符号错了才是真错但很多人看到向量反了就以为全错了。解决比对特征值时只看数值比对特征向量时用np.allclose并允许符号翻转比如验证A v和λ * v是否同向共线或者直接算abs(v.T v_ref)是否接近 1。只要Av λv成立方向无所谓。4.4 对数似然算出-inf或nan现象概率章节的对数似然函数跑到某一步变成-inf后面全废。原因np.log(p)里p取了 0 或者负数。用np.linspace(0, 1, n)生成扫描点时端点 0 和 1 必然出现如果p是模型输出也可能因为数值误差压到负数。解决生成扫描区间时留边写成np.linspace(1e-6, 1-1e-6, n)对模型输出加个np.clip(p, 1e-12, 1-1e-12)。同时顺手加一句assert np.all(p 0)在出问题的前一步就拦下来比等nan扩散出去再回头查快得多。4.5 画图窗口一闪而过或者中文全变方框现象Matplotlib 脚本跑完图窗口刚出现就关闭或者标题里的中文显示成方块。原因前者是没有调plt.show()或者脚本以非交互模式运行后者是默认字体不含中文字形。解决脚本末尾显式加plt.show()在无界面环境下改用plt.savefig(out.png, dpi150)存盘再打开看。中文显示的问题在画图前统一设置字体比如指定一个系统里有的中文字体名并关闭axes.unicode_minus之外的负号兼容问题。写在这个项目里就是初始化画图库的时候一次性配好别每张图重复设。5. 二次开发把答案包改成自己的练习题与验证流水线资料包读完之后最容易发生的退化是“看懂了但过两个月全忘”。真正能留下来的是自己搭的那套验证流程。我的做法是把每个知识点的校验函数抽出来变成一个可复用的断言库新学一个公式就往里加一条。具体分三步。第一步把第 3 章那几段验证代码抽成独立函数统一放在verify.py里每个函数只做一件事给定输入返回解析结果和数值结果的比对结论。第二步用pytest把它们串起来一个知识点一个测试用例跑一次全套就知道哪块生疏了。第三步把这些函数当模板遇到新公式先想“能不能用中心差分验”“能不能用迹和行列式验”能就立刻写进库。知识点校验手段容差参考矩阵求逆A inv(A)与单位阵比对1e-10特征分解迹、行列式恒等式1e-12导数公式中心差分1e-8积分结果数值积分交叉验证1e-6概率估计扫描对数似然取极大1e-3这套东西搭起来之后回头看那份资料包的视角就变了——从“一堆要背的题”变成“一堆待验证的假设”。哪道题的答案你看不懂就把它的结论写成断言让代码告诉你它成不成立。这是我的血泪经验光读答案会产生强烈的“我懂了”的错觉写断言的那一刻才会暴露真正的空白。还有个技巧值得说一句把代码里的随机种子固定下来np.random.default_rng(42)这种写法一开始就写上。数学验证最怕“上次跑对了这次跑错了”种子一变结果就飘排查起来非常玄学。固定种子之后任何一次结果异常都是代码或理解的问题不是运气问题。从那以后我每次看数学资料都强制自己先把结论写成一条能跑的断言跑通了才算过。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑