用二十一点对比Q-Learning、Sarsa与DQN:强化学习算法特性与工程实践指南

用二十一点对比Q-Learning、Sarsa与DQN:强化学习算法特性与工程实践指南
简介一份面向强化学习初学者与Python开发者的二十一点变体算法实验资源覆盖蒙特卡洛MC、SARSA以及SARSA的线性函数逼近三类经典方法可直接运行主程序调用测试函数一次性执行全部算法并可视化对比结果帮助快速建立强化学习算法的实验认知。压缩包共8个文件含6个Python脚本、1个Markdown说明文件和1个pickle数据文件整体仅14KB轻量便携。代码按环境模拟、算法实现、结果绘图、策略配置与工具函数清晰分层环境模块提供交互逻辑算法模块包含MC、SARSA及线性函数逼近绘图模块输出值函数与学习曲线策略部分内置epsilon-greedy机制工具模块负责均方误差计算和状态特征转换pickle文件可直接加载已保存的价值函数用于后续分析。项目结构非常适合逐模块阅读与二次改造已有1006人学习/下载可作为理解强化学习核心概念、动手复现实验或扩展二十一点策略研究的参考基础。 说起强化学习的入门项目很多人第一反应就是CartPole、GridWorld这类教科书环境。我一开始也是这么过来的直到把二十一点拉进来以后才意识到这个看似简单的牌局其实是一个被严重低估的实验沙盘。这个项目做下来我用了几种主流强化学习算法去训练智能体玩二十一点的变体规则——包括加了双倍下注、分牌这些衍生玩法——最后对比它们在收敛速度、长期收益和行为稳定性上的表现。整个过程走下来收获比想象中大得多。如果你正在学强化学习或者已经跑通了DQN但总觉得环境太玩具、看不出算法之间的差异我强烈建议你用二十一点试试手。它的状态空间小到能做表格型算法又大到无法一眼看穿最优策略它有现成的基本策略可以当标准答案却又保留了随机的不可控性。这篇文章不讲教科书概念就讲我怎么建环境、怎么选算法、怎么调参、怎么被各种细节坑了一遍又一遍以及最终几套算法各自交出了什么样的成绩单。1. 为什么偏偏是二十一点被低估的RL实验沙盘很多人觉得二十一点太简单动作就“要牌/停牌”两个状态也无非是手牌点数对庄家明牌一眼就看到底了。这个判断片面了。它简单但只是规则简单策略空间一点都不简单。恰恰是这种“规则简单、策略微妙”的组合让它成为测试强化学习算法的理想标尺。1.1 二十一点比CartPole更适合算法对比的三个理由第一它有明确的外部参照系。二十一点的基本策略是数学上已经算得很清楚的东西。也就是说我训练出来的智能体是不是真的学会了合理决策直接拿它的行为和基本策略一比就知道不需要靠人肉观察环境来判断。CartPole你只能看杆子倒没倒算法到底是学明白了还是单纯在碰运气很难判断。第二天然的非平稳和不确定性。每局发牌是随机的牌与牌之间还有隐藏的关联——不洗牌的情况下前面出去的牌会影响后面的牌面分布。这让它比固定转移概率的格子世界更接近真实世界的决策问题又比自动驾驶这类高维场景更容易建模。第三稀疏奖励。二十一点只有在整局结束时才给出1、-1或0的回报中间所有决策都没有即时反馈。这跟很多真实业务场景很像你做一个推荐不会立刻知道用户三个月后是否真的喜欢。二十一点用最轻量的方式复现了“延迟奖励”这个经典难点而这正是强化学习最需要处理的核心问题之一。1.2 这个项目到底要解决什么问题项目标题里写了变体这就意味着不是只在最基础的庄家17点停牌、玩家只能要牌或停牌的规则上做文章。我实现的变体包括双倍下注和分牌。双倍下注允许玩家在拿到前两张牌后选择加倍押注但只能再补一张牌分牌则允许玩家把两张相同点数的牌拆成两副手牌独立对战。这两个变体直接改变了动作空间和状态空间。基础版只需要两个动作加了双倍之后变成三个加了分牌之后状态里还要同时维护两副手牌的点数分布。可观测的信息多了最优策略也跟着变了。更关键的是这种扩展恰恰能拉开不同算法之间的差距有的算法面对稍微复杂一点的环境就崩了有的算法仍然稳定。这个项目本质上就是想回答一个问题在规则复杂度逐渐上升的情况下Q-Learning、Sarsa、DQN这几类典型算法各自还能不能撑住。2. 游戏环境建模状态、动作、奖励的一次完整定稿强化学习项目里最耗时也最影响结果的部分往往不是算法本身而是环境建得对不对。二十一点看起来简单但如果你不把规则细节一条条抠清楚训练出来的模型一定是错的。我自己就在软17还是硬17、A算1还是11、庄家是否要牌这些规则细节上栽过跟头。2.1 状态空间设计既要够用又不能爆炸基础版二十一点的状态空间可以设计得很精简。我最终采用的是四元组加上一个布尔分牌标识的组合形式玩家当前手牌点数4到21之间庄家的明牌点数A记为11J/Q/K记为10范围1到10玩家手牌是否为“软牌”也就是手里有没有一张可被计为11的A软牌意味着爆牌风险更低策略完全不同当前是否处于可双倍下注的时机即手牌刚好两张这里最容易被忽略的是“软牌”标识。硬16和软16看起来点数一样实际上策略天差地别。软16意味着你手里有A可以安全地再要一张也不会直接爆牌硬16则是进退两难。如果不把软硬状态分开智能体根本学不会正确的决策边界最终胜率会明显偏低。后面加了分牌变体之后不能用单个点数表示手牌了。我换了一种方式不再记录总点数而是记录“当前这一副手牌的构成”和“是否处于分牌后的第二副手牌”。这样状态空间会膨胀但还能被表格型算法接受也正是从这一步开始DQN的优势才逐渐展现出来。2.2 动作空间与奖励设计稀疏反馈是重点动作空间定义为离散集合动作含义可用条件0要牌Hit任意时刻1停牌Stick任意时刻2双倍下注Double仅限前两张牌且点数非爆牌3分牌Split仅限两张相同点数手牌奖励设计我尽量精简。赢一局得1输一局得-1平局得0中途不做任何过程的逐步奖励。这个设计的坏处很明显训练早期智能体完全不知道哪个动作是好的因为所有动作的即时反馈都是0只有终局才有非零回报。好处也同样明显它逼迫算法真正学会通过值函数去估计长期回报而不是靠即时反馈的短视信号骗分。注意有人会在智能体点数超过17时给一个小的正奖励来“引导”行为我实测过这种做法非但没有加速收敛反而让模型学会了追求看起来安全的点数损失了额外的赢钱机会。除非你必须死磕极低样本量否则别加中间奖励让算法自己去发现策略。2.3 发牌机制的实现细节发牌器我采用无限牌靴模型也就是每一局开始前把所有牌归位重新洗牌。这样做有争议因为真实赌场里牌是连着发的不是每局重新洗。但从算法对比的角度无限牌靴更公平——每一局的概率分布完全一致算法学到的是一个纯策略最优解而不是试图去数牌。如果你想做得更贴近真实可以改成有限牌靴并记录已发出的低牌和高牌比例这会让状态空间再膨胀一个维度。我实现了这个扩展但很快就发现对于表格型算法这种状态设计已经超出了内存和样本量的承受范围。这恰恰验证了一个道理同样的环境模型复杂度一旦上去对数据和算力的需求是指数级上升的。3. 三种算法的设计思路与本质差异选算法前我先明确了一件事这个项目不是为了刷SOTA而是为了搞清楚经典算法在面对相同问题时各自的性格差异。所以我选了三个最具代表性的Q-Learning、Sarsa和DQN。它们分别代表了表格型离线策略、表格型在线策略、函数近似离线策略三条路线。3.1 Q-Learning贪心而勇敢的基线Q-Learning属于离线策略off-policy它更新的时候用的目标值是在下一步选择“最大Q值”对应的未来回报不管当前行为策略是不是真的会走那条路。说白了它学的永远是如果我以后都按最优走现在这一步值多少所以它胆子大、行动激进几乎不考虑探索带来的风险。表格型Q-Learning的实现非常直接。更新公式是经典的那条Q(s,a) ← Q(s,a) α·[r γ·max(Q(s,a)) - Q(s,a)]在二十一点里我用的参数是学习率α0.01折扣因子γ0.99探索率ε从1.0线性衰减到0.01。为什么γ不设成1因为虽然一局游戏很短但把γ设为1会让期望收益的方差变得很大训练过程更不稳定。0.99既不改变最优策略本质又能让收敛过程平滑一些。3.2 Sarsa保守而稳健的现实主义者Sarsa和Q-Learning的差别一句话就能说清楚Q-Learning用下一步的最大Q值做目标Sarsa用下一步实际执行动作的Q值做目标。它的更新公式是Q(s,a) ← Q(s,a) α·[r γ·Q(s,a) - Q(s,a)]注意这里Q(s,a)里的a是行为策略实际选出来的动作不是理论最优动作。这意味着Sarsa学的策略是在带着探索的情况下做出来的最优决策它天然保守因为学习过程中持续把探索随机性带来的代价算进值函数里。你在最终训练结果里会看到Sarsa训练出来的智能体在12点对庄家6这类边缘局面上更倾向于停牌而Q-Learning则更愿意要牌。后者的期望收益更高但方差也更大。这就是在线策略和离线策略性格差异最直观的体现。3.3 DQN函数近似带来的扩展性表格型方法在状态数过万之后查表和更新的效率开始下降。DQN用神经网络逼近Q函数从根本上解决了状态空间膨胀的问题。实现上我用了三层全连接网络隐层维度128激活函数ReLU输出层维度等于动作数。训练上开了两个关键组件经验回放缓冲区容量10万条每次训练随机采样128条做小批量更新。这打破了样本之间的时序相关性让网络训练稳定得多。目标网络每500步同步一次主网络参数。如果没有目标网络Q值的更新目标一直在变训练曲线会像心电图一样剧烈跳动根本收敛不下来。DQN的代价是调参空间变得巨大。学习率、目标网络同步频率、回放缓冲区大小、批量尺寸每一个都能让结果天翻地覆。我在跑了不下三十组实验之后才找到一组在二十一点上能让它发挥出和表格型方法相当性能的参数组合。4. 十万局对局的实测结果谁收敛、谁赚钱、谁空转参数说再多都不如直接看结果。我选用了统一的评价协议每种算法训练10万局训练结束后用固定策略ε0再跑10万局评估统计平均每局收益和胜率。所有实验固定随机种子保证可比性。4.1 平均每局收益的横向对比算法平均每局收益胜率收敛所需局数备注随机策略-0.08142.1%不收敛对照组基本策略0.00644.3%不适用理论参照Q-Learning0.00243.9%约6万局接近基本策略Sarsa-0.01242.7%约4万局偏保守方差小DQN-0.00443.2%约8万局收敛慢但稳定需要强调一下这里用的是无限牌靴加上玩家后手规则所以整体收益曲线跟真实赌场有差别。真实赌场的切牌机制会让长期期望进一步下压。我在项目里得到的核心结论是Q-Learning最终能逼近基本策略水准Sarsa学出来的策略更保守DQN在表格型方法未爆炸的规模下并没有明显优势但一旦把变体全开表格型方法直接失效DQN是唯一还能跑的。4.2 从行为一致性看学习质量我额外做了一个检验把训练好的策略和标准基本策略做逐状态比对计算“决策一致率”。Q-Learning在大多数关键状态上和基本策略保持一致但在部分边界状态比如玩家12点对庄家3点会选择更激进的要牌而基本策略是停牌。这种细小的偏离在统计上不显著但很有意思说明Q-Learning没有完全学透人类总结的经验可是在期望收益上差距又极其微小。DQN的行为一致性明显低于Q-Learning大概在87%左右。原因不难理解神经网络在小规模状态空间上做函数近似时反而把邻近状态的Q值拉平了导致一些本应截然不同的决策被模糊化。这也是函数近似的固有代价。4.3 变体全开后谁还能打把双倍下注和分牌全开后状态空间涨到了11万多个算上分牌后的复合状态表格型方法的Q表就已经胀到了大约十几万行的规模。Q-Learning虽然内存上还撑得住但训练了20万局依然没有收敛到稳定水平平均每局收益始终在-0.03附近波动无法继续提升。DQN在这个规模下反而开始发挥威力。在用上分牌变体后它最终收敛到平均每局收益约-0.008虽然仍然不如基础版Q-Learning在无变体规则下的表现但在规则复杂度大幅提升的前提下它已经是四个方案里唯一能有效逼近基本策略的智能体了。5. 复现项目时踩过的五个坑和最终的调参建议这部分的经验是我认为比算法理论本身更值钱的地方。我前前后后大概花了一半的时间在和环境细节、训练稳定性作斗争这些坑单看文档根本发现不了。5.1 软硬牌状态漏一个收敛结果直接失真第一个版本的环境里我把手牌16点不管软硬都编码成同一个状态。训练结果看起来也正常胜率在42%左右浮动误以为已经接近理论极限。直到我把软硬分开编码之后才发现之前的学习过程其实一直在用同一个策略应对两种截然不同的局面预期收益直接提升了将近一个百分点。这类隐蔽的知识编码问题在强化学习环境里特别坑人因为你很难从最终结果反推出问题出在环境还是在算法。5.2 不要把探索率衰减得太快第一次训练时我把ε从1.0线性衰减到0用了3万局结果模型只学到了几个浅显的规则收益曲线涨到某一点就不再动了。原因很直接它还没把状态空间全部探索完就被迫进入纯利用阶段。后来我把衰减周期延长到8万局同一套超参下收益上限明显抬升。对于这个规模的环境8万局几乎探索到了所有可达状态这时候再切换为纯利用才合理。5.3 经验回放缓冲区量级不能拍脑袋DQN里我把回放缓冲区容量设为100万结果内存倒是没爆但训练特别慢而且效果反而变差。原因在于缓冲区太大里面的老样本大多数来自探索还非常充分、策略还非常差的阶段采样时总是抽到这些过时数据网络的训练目标被严重干扰。把容量降到10万之后效果立竿见影。对于这种状态空间只有几万的环境缓冲区没必要开到百万级。5.4 用A值切换导致的手牌点数计算Bug二十一点里A既可以算1点也可以算11点切换逻辑是最容易写错的环节。我第一版实现里手牌A5会被计算为16点A计11再要一张10点时被算成21点——但牌堆里如果还有第二张A正确的计算应该是A5A17点而不是27点爆牌。这个bug直接导致智能体学到了一套完全错误的爆牌认知胜率暴跌至35%。修复之后恢复正常。这个坑提醒我在做环境之前先把游戏规则的数据结构想清楚尤其是软硬牌切换的边界条件。5.5 训练评估阶段的ε必须设为0听起来像是常识但实际操作中经常有人忽略。如果你评估时还开着探索率测出来的收益会同时包含随机动作带来的损失曲线一直在震荡。我一开始偷懒用了同一个ε值评估结果每次数字都不一样还以为是算法不稳定。固定随机种子、评估时设ε0之后所有对比才变得可信。最终调参建议给出一份可以直接参考的基线配置参数Q-Learning / SarsaDQN学习率 α0.010.001折扣因子 γ0.990.99探索率 ε1.0→0.018万局1.0→0.018万局经验回放容量无100000批量尺寸无128目标网络同步频率无500步训练局数10万10万我自己的体会是二十一点这个项目非常适合用来建立对算法性格的直觉。Q-Learning激进又高效适合状态空间干净、可枚举的场景Sarsa稳健保守适合真实环境中随机干扰大、探索代价高的场景DQN在小场景里看不出优势但它是你往复杂规则前进时唯一能继续跑下去的选择。你要是想动手复现我建议从基础版Q-Learning开始用行为一致率而不是胜率来检验学习效果然后再逐步打开变体开关一路看到不同算法在复杂度压力下的真实表现。最后提醒一句这套东西做学术验证和环境研究都很有价值但别拿它去真实赌场找自信无限牌靴和实际规则的差距足以让所有测试结果都失去参考意义。本文还有配套的精品资源点击获取

最新新闻

日新闻

周新闻

月新闻