ML-For-Beginners 强化学习实战:为“彼得与狼“引入能量与疲劳机制,构建更真实的 Q-Learning 世界

ML-For-Beginners 强化学习实战:为“彼得与狼“引入能量与疲劳机制,构建更真实的 Q-Learning 世界 ML-For-Beginners 强化学习实战为彼得与狼引入能量与疲劳机制构建更真实的 Q-Learning 世界【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners本篇技术指南基于 ML-For-Beginners 课程第 8 章强化学习与 Q-Learning的课后作业展开讲解如何把彼得与狼Peter and the Wolf这个玩具环境改造成一个包含**能量energy与疲劳fatigue**状态的更真实世界并相应地重设计奖励函数、重写随机游走基线、重新训练 Q-Learning 策略最后对比两者在胜/负局数上的差异。读完本文你将掌握如何扩展强化学习中的状态空间表示、如何把领域规则翻译成奖励函数、如何评估与调优 Q-Learning 训练过程并可直接在课程自带的 notebook.ipynb 与 rlboard.py 基础上动手复现。任务背景从理想世界到真实世界在课程主体 8-Reinforcement/1-QLearning/README.md 中彼得可以在一个width x height的方形棋盘上自由移动而几乎不会疲惫或饥饿他的目标只是找到苹果同时避开水和狼。课程用Q-Learning让彼得学会一条高效路径把随机游走时 3040 步的平均路径缩短到 36 步。而本作业要求在此基础上更进一步让世界更真实。彼得不光要走到苹果旁还必须照顾自己的体力状态最终找到并击杀狼。这一改动会带来三方面的连锁反应状态不再只是人在哪状态需要同时包含棋盘位置、能量与疲劳三个维度奖励函数需要重写把 5 条新规则翻译成数值信号训练成本显著上升因为与狼交战并获胜是稀有机会作业明确提醒需要更多 epoch 和更长的训练时间。世界规则五条新规则与胜负判定作业 assignment.md希腊语版见 translations/el/8-Reinforcement/1-QLearning/assignment.md为这个世界定义了五条规则从一处移动到另一处彼得会损失能量、积累疲劳吃苹果可以恢复能量在树或草地绿色格子下休息可以消除疲劳即走进带有树/草的棋盘位置彼得需要找到并击杀狼击杀狼需要满足一定的能量与疲劳水平否则会输掉战斗。不难发现规则的语义与课程棋盘上的格子类型一一对应。在 rlboard.py 中每种格子由一个枚举常量表示见Board.Cellrlboard.py第 43-49 行class Board: class Cell: empty 0 water 1 wolf 2 tree 3 apple 4empty空地彼得可以行走water水不可行走落入即溺水wolf狼危险目标本作业中需要击杀tree树/草休息场所消除疲劳apple苹果进食场所恢复能量。官方解答 solution/assignment-solution.ipynb 给出的胜败判定非常直观当能量大于疲劳时彼得能赢下战斗否则失败。这一判定将被同时用于随机游走模拟和奖励函数两个环节。状态空间设计三种可选的表示方案原版课程中Q-Learning 的状态就是彼得的棋盘位置因此 Q 表是一个width x height x len(actions)的 numpy 数组每个格子记录四种动作上/下/左/右的吸引力Q np.ones((width,height,len(actions)),dtypenp.float)*1.0/len(actions)引入能量与疲劳后状态的含义变了。作业提示了三种实现路线用元组表示状态形如(Board, energy, fatigue)的三元组为状态定义专门的类可以继承自Board把能量/疲劳封装进对象直接修改Board类本身把能量/疲劳字段加进 rlboard.py 的Board。官方解答选择了方案 2——新建一个独立的state类见assignment-solution.ipynb第 104-134 行class state: def __init__(self,board,energy10,fatigue0,initTrue): self.board board self.energy energy self.fatigue fatigue self.dead False if init: self.board.random_start() self.update() def at(self): return self.board.at() def update(self): if self.at() Board.Cell.water: self.dead True return if self.at() Board.Cell.tree: self.fatigue 0 if self.at() Board.Cell.apple: self.energy 10 def move(self,a): self.board.move(a) self.energy - 1 self.fatigue 1 self.update() def is_winning(self): return self.energy self.fatigue这段实现恰好把五条规则逐一代码化构造与初始化默认能量 10、疲劳 0若initTrue则在棋盘上随机选取空地作为起点复用Board.random_start()见 rlboard.py 第 121-126 行update()走到水里直接判死走到树/草地清零疲劳规则 3吃到苹果恢复能量到 10规则 2move()每走一步energy - 1、fatigue 1对应规则 1is_winning()energy fatigue时才能战胜狼规则 5。注意一个实现细节官方解答的 Q 表仍然只以(x, y)位置为索引Q[x,y,ai]能量/疲劳并没有被展开成额外的 Q 表维度。这意味着能量/疲劳通过状态机与奖励函数参与学习而不是进入 Q 表索引。如果选择方案 1元组状态并希望 Q 表真正感知体力差异就需要把 Q 表扩展成更高维数组这也是作业留给大家的发挥空间之一。奖励函数设计把领域规则翻译成数值信号原版课程 README.md 的奖励函数是位置驱动的move_reward -0.1 goal_reward 10 end_reward -10 def reward(m,posNone): pos pos or m.human if not m.is_valid(pos): return end_reward x m.at(pos) if xBoard.Cell.water or x Board.Cell.wolf: return end_reward if xBoard.Cell.apple: return goal_reward return move_reward在更真实的世界里这个函数必须升级为状态驱动。官方解答给出的新版本是def reward(s): r s.energy-s.fatigue if s.at()Board.Cell.wolf: return 100 if s.is_winning() else -100 if s.at()Board.Cell.water: return -100 return r对照五条规则这个奖励函数的设计逻辑非常清晰情境奖励值对应规则普通移动energy - fatigue连续奖励规则 1消耗能量、积累疲劳击败狼is_winning()为真100规则 4、5输掉战斗能量不足-100规则 5溺水-100世界规则水中不可行走设计上的关键点在于非终结状态的奖励不再是固定常数而是energy - fatigue这个连续量。这相当于鼓励彼得高能量、低疲劳地行动——能量越高、越不疲劳获得的即时奖励越大反之则会逐步受到负向激励。它把体力管理内嵌进了每一步的回报里而不是等走到终点才一次性结算。值得一提的还有稀疏奖励问题与狼交战的概率很低绝大多数 episode 都在中途因溺水或能量耗尽而结束模型几乎接触不到±100的大额奖惩。课程 README 也强调过在大多数情况下我们只在游戏结束时获得实质性的奖励算法必须依靠 Q 表把导致最终正回报的中间步骤的价值回溯记牢——这正是 Bellman 方程要解决的核心问题。随机游走基线重写模拟与胜负统计作业明确要求保留负责随机游走策略的代码并在最后用它与 Q-Learning 结果做对比。因此第一步是重写walk与print_statistics官方解答第 162-210 行def random_policy(state): return random.choice(list(actions)) def walk(board,policy): n 0 # number of steps s state(board) while True: if s.at() Board.Cell.wolf: if s.is_winning(): return n # success! else: return -n # failure! if s.at() Board.Cell.water: return 0 # died a actions[policy(m)] s.move(a) n1 walk(m,random_policy)注意这里与 rlboard.py 内置的Board.walk第 174 行起有三处重要差异原版walk遇到苹果即返回成功return n新版本则把苹果视为补给站而非终点游戏只有三种结局战胜狼返回正步数、输给狼返回负步数、溺水返回 0每一步都通过s.move(a)同步更新能量/疲劳而不是只更新位置新版本在模拟层就用is_winning()判定战斗结果。统计函数也相应地把胜负拆开计数def print_statistics(policy): s,w,n 0,0,0 for _ in range(100): z walk(m,policy) if z0: w1 elif z0: n1 else: s1 print(fKilled by wolf {w}, won: {s} times, drown: {n} times) print_statistics(random_policy)官方解答的一次运行输出为Killed by wolf 5, won: 1 times, drown: 94 times由于随机性每次运行的具体数字会不同。这说明在纯随机策略下彼得绝大多数时候约 94%会溺死在水中几乎无法完成找到狼并击杀的目标——这正是 Q-Learning 需要改进的基线。Q-Learning 训练循环算法不变状态更复杂作业反复强调学习算法本身几乎不需要改动变的只是状态的定义方式。官方解答保留了原版课程的全部核心组件Q 表初始化仍为width x height x 4四个方向动作等概率初始化概率化辅助函数probs把 Q 值向量转换为动作概率eps1e-4防止全等向量除以零见课程 README.md code block 7def probs(v,eps1e-4): v v-v.min()eps v v/v.sum() return v训练循环官方解答第 278-312 行与原版结构一致但有几处针对新世界的调整lpath [] for epoch in range(10000): s state(m) n0 cum_reward 0 while True: x,y s.board.human v probs(Q[x,y]) while True: a random.choices(list(actions),weightsv)[0] dpos actions[a] if s.board.is_valid(s.board.move_pos(s.board.human,dpos)): break s.move(dpos) r reward(s) if abs(r)100: # end of game lpath.append(n) break alpha np.exp(-n / 3000) gamma 0.5 ai action_idx[a] Q[x,y,ai] (1 - alpha) * Q[x,y,ai] alpha * (r gamma * Q[xdpos[0], ydpos[1]].max()) n1值得展开的几个关键点动作选择探索 vs 利用random.choices(..., weightsv)按 Q 值比例采样动作。训练初期 Q 值全相等等价于随机游走随着学习推进越来越倾向选择 Q 值高的动作但仍有概率探索未知路径。这正是课程 READMEExploit vs. explore一节的精髓。合法性检查新版本在选动作时用is_valid循环重试保证彼得不会走出棋盘边界而原版训练代码是通过m.move(dpos, check_correctnessFalse)故意允许越界来终止 episode 的——这是新老实现的差异之一。学习率衰减alpha np.exp(-n / 3000)。n 是当前 episode 内已走步数3000 是衰减常数比原版np.exp(-n / 10e5)衰减快得多。原因是新世界每局步数更多、体力约束更强需要更快收敛课程 README 也指出训练后期应让 Q 表只做小幅修正避免写坏已经学好的系数。折扣因子gamma 0.5与课程示例一致用来权衡即时奖励与未来奖励。终止条件abs(r)100即遇到狼胜/负或水此时 episode 结束并记录路径长度。Epoch 数官方解答使用10000是原版 5000 的两倍且每轮训练输出进度。作业明确提示因为击杀狼是稀有机会可以预期训练时间远长于原版必要时还需继续加大 epoch。训练完成后可以用m.plot(Q)把 Q 表可视化每个空格内的线段方向表示该状态下的首选移动方向图中可以看出彼得学会了有目标地朝狼或苹果移动而不是随机乱撞。评估与对比Q-Learning vs 随机游走训练结束后用与随机游走相同的print_statistics评估 Q 学习出的策略。官方解答使用概率化策略按 Q 值比例采样而非贪心取最大值这样可以兼顾探索def qpolicy(m): x,y m.human v probs(Q[x,y]) a random.choices(list(actions),weightsv)[0] return a print_statistics(qpolicy)官方解答的一次运行输出为Killed by wolf 1, won: 9 times, drown: 90 times与随机游走基线won: 1, drown: 94, killed by wolf: 5对比可以得出两条关键结论溺水率有所下降从约 94% 降到约 90%说明 Q-Learning 学到了一定的避水倾向战胜狼的次数从 1 次提升到 9 次获胜局数提升约 9 倍而被狼反杀的次数也从 5 次降至 1 次——说明策略开始懂得养精蓄锐后再决战这正是奖励函数energy - fatigue与±100战果奖惩共同作用的结果。需要强调上述数字只是某一次运行的结果由于训练与评估都带随机性每次复现会有波动作业的评估标准Rubric要求的也是**Q-Learning 能显著改善随机游走的结果**这一相对结论而不是某个绝对数值。解答还提示如果发现彼得仍不能稳定击杀狼可以继续尝试调整超参数。超参数调优让稀有机会被真正学会作业末尾特别提醒你可能需要调整超参数尤其是 epoch 数量。结合官方解答与课程 README.md 的学习过程分析可调的关键旋钮有超参数官方解答取值原版课程取值调整方向与影响Epoch 数100005000击杀狼是稀疏事件epoch 不足时 Q 表可能从未见过狼可继续加大学习率衰减常数3000alpha np.exp(-n/3000)10e5常数越小衰减越快、收敛越早但也可能过早锁定次优策略训练后期应只做微调折扣因子 γ0.50.5越大越看重未来回报适合需要先蓄力后决战的长期规划每局步数上限未显式限制挑战任务建议 100可防止彼得在空旷区域无限徘徊从而饿死课程 README 对学习过程的三点观察同样适用且更具启发性平均路径先增后减初期一无所知时容易困在坏状态水/狼随着知识积累开始探索更远路径变长学会后路径重新变短但探索行为仍会让路径偶尔偏离最优路径长度可能突然跳升这说明 Q 表系数可能在某个时刻被新值覆盖overwrite而退化训练后期应依靠更小的学习率来抑制这种扰动收敛质量高度依赖超参数学习率、学习率衰减与折扣因子共同决定了训练的成功率与稳定性超参数优化本身就是一个值得单独研究的话题。评估标准Rubric怎样的答卷才算合格作业附带的评分标准Rubric从三个层次给出了明确的验收口径标准优秀合格需改进内容提交的 notebook 包含新世界规则的定义、Q-Learning 算法以及必要的文字说明且 Q-Learning 相比随机游走显著提升了成绩notebook 已提交Q-Learning 已实现并能改进结果但提升不显著或 notebook 文档化不足、代码结构混乱尝试了重新定义世界规则但 Q-Learning 无法工作或奖励函数未完整定义对照此标准一份完整的解答至少应包含新世界规则的代码化state类或等价实现重写后的奖励函数reward(s)保留随机游走策略及其统计代码作为基线Q-Learning 训练循环与 Q 表可视化末尾的对比结论用print_statistics分别跑随机策略与学习策略给出胜负局数的定量对比。运行环境与文件指引要复现本作业你需要课程目录中的两个文件8-Reinforcement/1-QLearning/notebook.ipynb课程主 notebook作为解答的起点作业要求在其基础上修改奖励函数并重跑学习算法8-Reinforcement/1-QLearning/rlboard.py棋盘环境模块提供Board类、格子枚举与可视化state类可以直接放在 notebook 中也可以像解答那样引用它。课程 README.md 的Prerequisites and Setup一节也提醒若在云端运行 notebook需要把rlboard.py放到与 notebook 相同的目录下二者位于同一目录。官方参考解答位于 solution/assignment-solution.ipynb其中完整给出了state类、随机游走统计、新奖励函数与 10000 epoch 的训练循环可作为对照实现与调参起点。通过本次练习你实际完成了一次典型的强化学习工程流程定义领域规则 → 设计状态表示 → 设计奖励函数 → 建立随机基线 → 训练与评估 → 超参数调优。这套方法论同样适用于其他需要资源管理 稀有成功事件的现实任务例如机器人节能导航、游戏角色的体力规划、库存与配送调度等场景。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考