尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

人工智能原理习题复现指南:从课后答案到可运行代码

发布时间:2026/9/26 20:43:05

资讯中心
01
ARTICLE

人工智能原理习题复现指南:从课后答案到可运行代码

人工智能原理习题复现指南:从课后答案到可运行代码
简介这份资源是王万森《人工智能原理及其应用》第四版的课后习题参考答案面向高校人工智能课程学习者、备考学生及需要梳理知识框架的自学者帮助解决课后练习无从下手、概念理解模糊的问题。压缩包内共1个docx文档约343KB按章节组织答案覆盖人工智能概述、确定性知识系统等核心内容。文档对智能的定义与能力构成、形象思维与抽象思维及灵感思维的区分、图灵实验的判定规则、人工智能发展各阶段、符号主义与联结主义及行为主义三大学派特点、机器思维与机器学习及机器感知等应用领域以及一阶谓词逻辑、产生式、语义网络、框架结构等知识表示方法均给出条理清晰的解答并配有谓词公式表示等典型例题的推导过程。目前已有1560人学习下载适合用于课后对照复习、期末梳理考点与考研初试知识点巩固。1. 从“课后习题答案”到真正吃透人工智能原理一份可复现的自学路径很多人搜“人工智能原理及其应用王万森第版课后习题答案”其实心里想的不是抄答案而是想找一条能验证自己有没有学懂的路径。教材里的习题往往横跨搜索、推理、学习三大块光看答案没用换个参数就翻车。我当年也是从对着答案抄起步的后来发现真正管用的是把每道题当成一个小实验给定输入、跑出输出、再改条件看结果怎么变。这篇笔记就按这个思路把教材里最常考的几类习题拆成能动手复现的步骤适合正在跟这门课、准备考试或者想补AI基础的人。你不需要额外买什么工具一台能跑Python的电脑就够。2. 把教材习题拆成可运行的最小实验环境与三类核心题型2.1 为什么先搭环境再谈答案教材里的习题分三类搜索类八数码、传教士与野人、推理类谓词逻辑、归结、学习类感知机、BP网络。这三类在纸面上都是符号推演但真正理解它们需要看到中间状态。我一般会建一个干净的Python环境只装numpy和matplotlib避免版本冲突。用conda或者venv都行关键是固定版本因为不同numpy版本在矩阵运算上的默认行为偶尔有差异做感知机习题时可能因为广播规则导致结果对不上。# 创建独立环境避免和系统包冲突 python -m venv ai_hw source ai_hw/bin/activate # Windows用 ai_hw\Scripts\activate pip install numpy1.26.4 matplotlib3.8.4这里固定numpy 1.26.4是因为它在矩阵乘法和广播上的行为稳定很多老教材的习题答案默认按这个语义。matplotlib只用来画学习曲线不装也能跑但看着曲线收敛比盯着数字直观得多。环境建好后建议在项目根目录放一个hw文件夹每道习题一个.py文件文件名用题号比如hw_3_2.py方便回头查。2.2 搜索类习题以八数码为例的最小可运行框架八数码是教材里出现频率最高的搜索题考的无非是BFS、DFS、A*三种。很多人答案背得滚瓜烂熟但真让他写一个能跑出路径的代码就卡住。我一般先写一个状态表示和移动生成函数再套不同的搜索策略。状态用元组表示0代表空格这样可以直接塞进set去重。import heapq goal (1, 2, 3, 4, 5, 6, 7, 8, 0) def neighbors(state): 返回所有合法移动后的状态以及移动代价这里恒为1 idx state.index(0) r, c divmod(idx, 3) result [] for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]: nr, nc r dr, c dc if 0 nr 3 and 0 nc 3: nidx nr * 3 nc lst list(state) lst[idx], lst[nidx] lst[nidx], lst[idx] result.append((tuple(lst), 1)) return result def h_misplaced(state): 启发函数1不在目标位置的数字个数 return sum(1 for i in range(9) if state[i] ! 0 and state[i] ! goal[i]) def h_manhattan(state): 启发函数2曼哈顿距离之和 total 0 for i, v in enumerate(state): if v 0: continue gr, gc divmod(v - 1, 3) r, c divmod(i, 3) total abs(r - gr) abs(c - gc) return total def astar(start, heuristic): A*搜索返回路径和扩展节点数 open_list [(heuristic(start), 0, start, [start])] closed set() expanded 0 while open_list: f, g, state, path heapq.heappop(open_list) if state in closed: continue closed.add(state) expanded 1 if state goal: return path, expanded for nxt, cost in neighbors(state): if nxt not in closed: ng g cost heapq.heappush(open_list, (ng heuristic(nxt), ng, nxt, path [nxt])) return None, expanded这段代码的关键在启发函数的选择。h_misplaced简单但扩展节点多h_manhattan更紧但计算稍慢。教材习题经常让你比较两种启发函数对A的影响你直接改astar的第二个参数就能跑出对比数据。注意closed集合必须在弹出时判断不能在入堆时判断否则可能错过更优路径——这是A实现里最常见的翻车点。跑的时候用一个可解初始状态比如(1,2,3,4,5,6,0,7,8)观察扩展节点数差异。2.3 推理类习题归结原理的手动推演与代码验证归结原理的习题通常给一组子句让你证明某个结论。纸面上画归结树容易漏分支我一般用Python把子句集表示成集合的列表然后写一个简单的归结循环把所有可能的归结式生成出来直到出现空子句。这样既能验证答案又能看清哪一步是关键的。def resolve(ci, cj): 对两个子句做归结返回所有可能的归结式 results [] for lit in ci: if -lit in cj: new_clause (ci - {lit}) | (cj - {-lit}) results.append(frozenset(new_clause)) return results def resolution(clauses): clauses是frozenset的列表返回是否推出空子句 clauses [frozenset(c) for c in clauses] while True: new [] n len(clauses) for i in range(n): for j in range(i1, n): for r in resolve(clauses[i], clauses[j]): if len(r) 0: return True if r not in clauses and r not in new: new.append(r) if not new: return False clauses.extend(new)这里用整数表示文字正数代表正文字负数代表负文字。比如子句{1, -2}表示“1或非2”。resolve函数只处理互补对每次归结去掉一个互补对保留其余文字。教材习题里常考的“每个学生要么喜欢数学要么喜欢物理”这类自然语言转子句你手动转完塞进clauses列表就能跑。注意归结法的完备性依赖于不断添加新子句所以循环里要把new合并回clauses否则可能提前终止。跑一个经典例题[{1,2}, {-1,3}, {-2,3}, {-3}]应该返回True。3. 学习类习题的参数怎么设感知机与BP网络的实操细节3.1 感知机习题学习率与迭代次数的边界感知机习题通常给几个二维点让你手算权重更新过程。手算容易但真跑起来会发现学习率选不好就震荡。我一般用下面的代码框架把每次迭代的权重和误分类点打印出来和教材答案对照。import numpy as np def perceptron(X, y, lr0.1, max_iter100): X: (n, d), y: (n,) 取值为1/-1 w np.zeros(X.shape[1]) b 0 for epoch in range(max_iter): errors 0 for xi, yi in zip(X, y): if yi * (np.dot(w, xi) b) 0: w lr * yi * xi b lr * yi errors 1 if errors 0: print(f第{epoch1}轮收敛) return w, b print(达到最大迭代次数仍未收敛) return w, b关键参数是lr和max_iter。教材习题默认学习率为1但实际数据尺度大时用1会震荡我一般从0.1试起。max_iter设100足够因为感知机收敛定理保证线性可分时有限步收敛但步数上界和数据间隔有关。跑的时候用X np.array([[3,3],[4,3],[1,1]])y np.array([1,1,-1])观察第几轮收敛。如果换成不可分数据比如加一个噪声点就会看到永远不收敛这时候需要设max_iter并接受一个近似解。3.2 BP网络习题隐藏层节点数与激活函数的选择BP网络习题一般给一个简单的异或问题或者函数逼近让你设网络结构。教材答案往往只给最终权重不告诉你为什么选3个隐藏节点。我一般会跑几组对比看隐藏层节点数对收敛的影响。import numpy as np def sigmoid(x): return 1 / (1 np.exp(-x)) def sigmoid_deriv(x): return x * (1 - x) def train_xor(hidden3, lr0.5, epochs10000): X np.array([[0,0],[0,1],[1,0],[1,1]]) y np.array([[0],[1],[1],[0]]) np.random.seed(42) W1 np.random.randn(2, hidden) * 0.5 b1 np.zeros((1, hidden)) W2 np.random.randn(hidden, 1) * 0.5 b2 np.zeros((1, 1)) for e in range(epochs): # 前向 z1 X W1 b1 a1 sigmoid(z1) z2 a1 W2 b2 a2 sigmoid(z2) # 反向 dz2 (a2 - y) * sigmoid_deriv(a2) dW2 a1.T dz2 db2 np.sum(dz2, axis0, keepdimsTrue) dz1 (dz2 W2.T) * sigmoid_deriv(a1) dW1 X.T dz1 db1 np.sum(dz1, axis0, keepdimsTrue) W2 - lr * dW2 b2 - lr * db2 W1 - lr * dW1 b1 - lr * db1 return a2 for h in [2, 3, 4, 5]: out train_xor(hiddenh) print(f隐藏节点{h}: {out.ravel().round(3)})隐藏层节点数设为2时异或问题经常陷入局部极小输出接近0.5设为3以上基本能收敛到接近0和1。学习率0.5是经验值太大震荡太小收敛慢。教材习题如果只给一个答案你可以用这段代码验证不同初始化的影响——np.random.seed换个数结果可能不同这就是神经网络训练里的玄学部分。注意sigmoid_deriv的输入是激活后的值不是加权和这是反向传播里最容易写错的地方。4. 避坑与排查课后习题复现时最容易翻车的五个点4.1 现象A*搜索跑不出结果一直循环原因closed集合在入堆时就去重导致同一个状态以不同代价入堆时被错误跳过或者启发函数不满足一致性条件时重复扩展。解决把去重放在弹出时并且确保启发函数不高估真实代价。如果启发函数高估A*可能找不到最优解但不会死循环死循环通常是closed逻辑写反了。4.2 现象归结原理代码返回False但教材说能推出空子句原因子句表示时把文字的正负号搞混或者归结时只处理了一个互补对就返回没有生成所有可能的归结式。解决检查每个子句的frozenset里是否同时有lit和-lit如果有该子句本身是永真式应该直接删掉。另外归结时应该对每一对互补文字都生成归结式而不是找到一个就停。4.3 现象感知机训练时权重越来越大不收敛原因数据不是线性可分的或者学习率设得太大导致震荡。解决先画散点图看数据分布如果确实不可分就设最大迭代次数并接受近似解。学习率从0.01开始试观察误分类点数量是否下降。如果下降后反弹说明学习率过大。4.4 现象BP网络输出全是0.5损失不下降原因隐藏层节点太少导致欠拟合或者权重初始化全部为零导致对称性无法打破。解决隐藏层至少设3个节点权重用随机小值初始化不要用零。另外检查激活函数是否可导sigmoid在饱和区导数接近零可以换tanh或者ReLU试试。4.5 现象教材答案里的权重和代码跑出来的不一样原因教材可能用了不同的初始化、不同的迭代顺序或者不同的停止条件。解决不要纠结完全一致重点看最终误差是否降到可接受范围。如果教材给的是手算一轮的结果你代码里跑一轮打印出来对比即可。如果差异很大检查学习率、初始化范围和是否打乱样本顺序。5. 从习题到小项目用教材里的算法做一个可验证的迷你系统把课后习题串起来可以做一个“八数码求解器归结证明器异或分类器”的迷你工具箱。我一般会写一个命令行入口输入题号就调用对应的函数输出中间过程和最终结果。这样复习的时候不用翻代码直接跑一遍就能回忆起来。# mini_tool.py import sys from hw_3_2 import astar, h_manhattan, h_misplaced from hw_4_1 import resolution from hw_5_3 import train_xor def main(): if len(sys.argv) 2: print(用法: python mini_tool.py [8puzzle|resolution|xor]) return task sys.argv[1] if task 8puzzle: start (1,2,3,4,5,6,0,7,8) path, expanded astar(start, h_manhattan) print(f路径长度: {len(path)-1}, 扩展节点: {expanded}) elif task resolution: clauses [{1,2}, {-1,3}, {-2,3}, {-3}] print(可满足 if not resolution(clauses) else 不可满足推出空子句) elif task xor: out train_xor(hidden3) print(f异或输出: {out.ravel().round(3)}) if __name__ __main__: main()这个工具的价值在于把分散的习题变成可重复验证的实验。你改一个参数跑一遍看输出变化比对着答案抄十遍都管用。我自己的习惯是每学完一章就把这一章的习题代码整理成一个模块加一个if __name__ __main__的测试入口。过一个月回头跑如果还能跑通并且结果符合预期说明真记住了。如果跑不通看报错和中间输出往往能发现自己当时理解错的地方。希望这个路径能帮到你少走点我当年对着答案硬背的弯路。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。