风雷游戏厅正式版v2017.3.24.1047 正式版
2025年12月25日德州扑克转牌圈怎么玩?掌握决策及底池管理全攻略
2025年12月25日选自willtipton
机器之心编译
参与:Jane W、蒋思源
近期,强化学习也就是 RL 的成功,就像 AlphaGo 那样,获得了大众的极高关注,然而其基本思路颇为简单。接下来,我们在一对一无限注德州扑克游戏当中进行强化学习。为了能够尽可能清晰地展现,我们会从零着手开发一个解决方案,并不需要预设的机器学习框架,像是 Tensorflow。那就让我们借助 Python3 Jupyter notebook 开始吧!
问题设置
强化学习
特征:
的输入(下文使用 Q^表示 Q hat)
关于 Q^ 的线性模型
模拟扑克游戏
学习:更新 Q^
整合
结果
解释模型
可视化策略
结语
问题设置
规则提醒:该游戏是一个 2 人无限注的德扑游戏,其中:
一场游戏正式开局,有两名参与的选手,他们都持有 S 筹码,并且手头有着经由随即方式发放而来的 2 张底牌。
第2个,BB也就是大盲注的玩家,下了1.0个盲注数额,而SB就是小盲注的玩家,下的是0.5个盲注数额。
小盲注的玩家,能够选择全押,也就是进行all━in操作,或者选择弃牌,也就是执行fold动作 。 .
4. 要是小盲注玩家把手里筹码全部押上,那么大盲注玩家能够选择跟注或者弃牌 。
对于规则,我们能够将其以可视的方式呈现为如同下图所展示的那种决策树。游戏起始于 E 这个点,在这个时候,SB 存在两种选择,要么进行全押,要么选择弃牌。要是他选择弃牌,那么我们就会转移至状态 A,此时游戏宣告结束。要是他选择全押,那么我们会转移至状态 D,在这个状态下,BB 必须要在跟注以及弃牌这两者之间做出相应的决定。倘若有一个玩家选择弃牌,那么另一个玩家便会获得盲注,要是两个玩家都选择全押,那么就会发放 5 张公共牌,并且金额会依照扑克的正常规则来进行分配。
这个游戏有的解决方案很著名,其网址是(http://www.dandbpoker.com/preflop-charts),它还有的办法是其他的,比如虚拟对局,其网址为(https://www.youtube.com/watch?v=MVMfDswjJE0),以及直接优化,其网址是(http://willtipton.com/coding/poker/2016/03/06/shove-fold-with-tensorflow.html)。这里,我们将使用强化学习估算解决方案。
这里有
计算种出来的不重复的2张手牌的组合数量。所以呢,我们能够给全部的牌进行排序,并且从0开始编到1325号。只要前后的编号是一样的,那么具体的顺序其实是没有关系的。下面这个函数暗中定义了这样的一种排序,还创建了从牌的编号到相关决策的映射关系:就是牌的排序情况(牌面顺序或者说rank)以及同花性(牌面花色也就是suitedness) 。
要留意,输出而成的元组里面的首个元素,也就是代码之中的r2,始终会排序在前面,要是存在的话。举例来说,手牌的编号是57,精确来说刚好就是62,我们能够获得:
当玩家进行全押操作时,他们平均所获取的底池,也就是所谓的「期望利益」,是依据游戏规则来予以决定的。文件pf_eqs.dat,其网址为http://willtipton.com/static/pf_eqs.dat,它包含一个numpy矩阵pfeqs,该矩阵的网址是http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.savetxt.html,这里的pfeqs指的是,当对手持有手牌j时,持有手牌i的期望利益 。
当然,有时两人起始手牌存在一张相同的牌,处于这种情形下,它们的期望无法同时进行计算,此时获取他们的期望利益也并不适宜。文件pf_confl.dat(http://willtipton.com/static/pf_confl.dat)含有另一个1326×1326矩阵德信竞技,其中每个元素为0或者1。A 0表明两位玩家的起始手牌不相同,a 1表明起始手牌一样。
举例来说,鉴于手牌当中,56 处于的状态是 62,57 此种情况属于 62,58 在相关范畴内亦是 62,所以我们便得出了如下结果:
为什么结果不正好是 0.5 呢?
强化学习
接下来步入 RL 教程。RL 问题存在三个关键构成部分,分别是状态(state),动作(action),奖励(reward)。它们组合在一起呈现出如下情况:
1. 我们处于某「状态」(即我们观察到的世界的状态)。
2. 我们使用这个信息来采取某「动作」。
3. 我们会得到某种「奖励」。
4. 重复以上过程。
不断地重复上述流程,重复的次数为一遍又一遍,即:先对状态予以观察,再据此来采取行动,行动之后可 获取奖励,之后就是观察新的状态,接着采取另外一个行动,采取该行动后同样会再获取又一个奖励等。RL问题仅仅是要找出怎样才能够选择行动的方案,从而获取尽可能多的奖励。实则已然证明这属于一个格外普遍的框架。基于该框架作为一种方式,我们能够对诸多问题予以考虑思索,而针对这些被考虑思索的种种不同问题实施解决,实际也存在着许多不一样的方法。大概来讲,解决办法关联随机游走,于不同状态挑选各类行为,记住哪些组合可获取何种奖励,接着试着借助这些信息在往后作出更佳的抉择句号。
在德扑游戏里 RL是怎样被运用的呢?对于玩家而言,在任意决策点上,其知晓自身的2张底牌以及所处位置,这构成了状态。随后他能够施行相应行动:或者选择弃牌,或者进行GII。这里面GII对于SB而言意味着全押(shove),而对于BB来说意味着跟注。接着会获取奖励,此奖励乃是玩家所赢得的货币数量,并且在最终的手牌环节我们会运用玩家总体的筹码规模值。举例来讲,要是初始筹码规模为S=10,SB全押而BB弃牌,那么玩家所获奖励分别是11和9 。
我们会借助模拟手牌组合去查找游戏的策略,我们会同步处理两个玩家的随机手牌,使之做出有关如何玩的决策,接着留意他们每次结束之际最终获得多少钱,我们将运用该信息去学习(估计)Q函数Q(S,A),Q的参数是状态S以及动作A,其输出值是在那个状态下采取那个动作时获取的最终奖励值,一旦我们具备Q(或者它的某种估计),策略选择就容易了,我们能够评估每个策略,瞧瞧哪一个更优。
因而,我们此地的工作是对Q进行估计,我们会用Q^(念作「Q hat」)来指代这个估计,初始化之时,我们会随机去猜测一些Q^ ,接着,我们会模拟一些手牌,两名玩家依据Q^来做出决定,每一次手牌之后,我们会调整那个估计值Q^,以此来反映玩家于特定状态下采取特定动作后所获取的实际值,最终,我们理应得到一个不错的Q^估计,这便是确定玩家策略所需的全部内容 。
这里存在一点需要留意,我们得保证在全部状态下施行所有动作,每一个状态与动作的组合都起码尝试一回,如此方可很好地估算出最终每个有可能的值。故而,我们会使玩家在一小段时长ε内随机地去采取行动,运用他们(当下估计的)最优策略。起初,我们应当积极地探究选择的可能性,频繁地随机进行选择。伴随时间的推进,我们会更多地运用所获取的知识。也就意味着,ε会随着时间的流逝而缩小。有诸多方式能够达成这点,比如:
从任何状态选取采取任何特定动作所具有值的那个,被称作「动作价值函数(action – value function)」用Q表示,它在大多数RL方法里有着重要作用它使得特定动作从任何状态取值表示从任何状态对于一个动作品评价在衡量这种情况时所具有的价值,这个动作本身所获得从任何价值给定某状态于之得到的价值,那么Q^该怎么去表示,到底要如何进行评估,是不是在每一次手牌之后就更新呢 ?
特征:Q^ 的输入
首先,Q^的输入是状态和动作,把这个信息传递给Q函数,此信息作为位置,像SB为1,BB为0,还作为手牌编码,其范围是0到1325,也作为动作,比如GII为1,弃牌为0。不过,我们将会看到,要是我们做更多的工作,就会得到更好的结果。在这里,我们用7个数字的向量描述状态和动作:
函数phi 返回的向量φ会成为Q 函数的输入,此向量被称作特征向量,其各元素皆是特征,这里φ发音为「fee」。我们将会见到,我们所挑选的特征能够在结果质量方面引发极大差异。进行特征选择(此即所谓「特征工程」)时,我们运用了与问题相关领域的知识。它如同科学那般具有艺术性。在此情形下,我们会采用以下几种方式对判断哪些属于相关信息的知识进行编码。一起来看看 。
基于便利的缘由,第一个元素一直都是 1。思索紧跟其后的四个元素。这些元素是用来代表玩家手中的牌的。我们已然从手牌编码转变成了 rank1、rank2 以及 isSuited;这三个变量在技术层面上所给出的信息与手牌编码是一样且相同的且一致的(将特定的组合排除在外并忽视遗漏),然而这个模型会更出色地运用这种格式的信息。除了原本的排序之外,我们还纳入了 (|rank1 – rank2|)^0.25这样的值。我们恰好了解到连通性是德州扑克的关键且重要的属性,就如同它的名字所暗示的那样。另外,要是所有的特征在量纲方面保持一致这种状况下,该模型的学习所取得的效果将会更优。在这儿,所有的那些具有特点的事物大体上处于 0 与 1 之间这样的范围,这是我们借助把 rank 用 numRanks 去除以此方式而获得的。
最后,要是出现 not isGII 的情况(也就是动作是弃牌的时候),我们事实上会把这些数字设定为 0。我们清楚,当玩家进行弃牌动作时,特定的持有手牌对于结果而言不存在任何影响(须忽略小概率的卡牌移除效果),所以在这种情形下我们会去除无关的信息。
当前思考最后那两个元素,第一个直接对玩家的位置进行编码,然而第二个同时依赖于isSB以及isGII,为何会出现这种状况呢,稍后我们会展示这个“交叉项”的必要性。
关于 Q^ 的线性模型
我们会去学习一个用于估计的 Q^ 函数,该函数是线性函数,这就意味着,我们要切实去学习一个参数向量,此参数向量一般被称作θ,它的长度为7 ,且与特征向量的长度一样,之后,我们会针对特定的φ来对 Q^ 加以估计 。
这里,下标 i 用来指代向量的特定元素,并且把参数列表写成 (φ;θ),这表明 Q^ 的值是由 φ 和 θ 所决定的,不过我们能够把它看成是 φ 的函数,而 θ 是固定不变的值。代码十分简单:
这个函数被普遍使用,不过,这个算法没什么特别的地方,无法成为解决这个问题的最佳选择。这只是其中一种办法:把某些学习参数跟某些特征结合起来得到输出,而且,完全由我们去定义一个θ向量,让它产生我们期望的输出。然而,正确挑选θ能帮我们很好地估计在有特定手牌时采取特定行动的价值。
模拟扑克游戏
我们接下来要进行「玩」手牌这个行为了,手牌的「玩」会在接下来的几个部分里展开进行,然而当下我们要先构建三个重要的概念,这三个重要概念与RL问题的三个重要组成部分存有紧密关联关系。和哪些相关呢?分别是状态、动作以及奖励。首先来说状态,对于每次手牌而言,我们会采用随机发牌这样的方式去初始化每个玩家的状态 。
第二点,要采取动作,各个玩家会借由当前所用之模型(此模型由theta予以呈现),还有已知的手牌以及身份(其身份为SB),进而去挑选动作呢。于后续的这些函数里,我们会对GII跟弃牌/FOLD(也就是qGII与qFOLD)的值作估算。接着去挑选当下的最优项(为1 – ε),要是没得挑的话呢,那就随机地去选择动作。最后返回所采取的那个动作,以及与之相对应的价值估计和特征向量,而这两项我们在之后是会用到的 。
第三个要点是,一旦我们清楚知晓每个玩家此刻所拥有的手牌以及所做出的动作,那我们便去模拟剩余的手牌以此来获取玩家的奖励。要是有任何一个玩家选择弃牌,我们能够马上返回正确的奖励数值。不然的话,我们依据玩家的状态以及奖励期望(equity),在恰当的时间段随机挑选出一个赢家 。
在玩家将自身能够投入游戏的全额赌注进行押注的情形之下,我们运用了小窍门成功避开了模拟。 然而,与借助5张公共牌切实开展模拟游戏,再对玩家手中拿着的牌进行评估,以此来判定谁会获胜有所不同的是,我们当下依据预先经过计算得出的概率随机挑选出一个获胜者。 这种方式在数学层面是具备同等效力的(忽略掉那些繁杂琐碎的论证过程);这只不过是一种更为便利且计算效率更高的途径 。
较为关键的是,我们于学习进程当中并未运用这些公平性部分或者跟游戏规则相关的信息。就如同我们很快就会见到的这般,哪怕是展开全然的模拟,学习进程也不会存在什么差异,甚至智能体于外部这个黑盒样式的扑克游戏系统从事交互进而有可能遵守不一样的规则!那么,学习进程到底是怎样开展的呢?
学习:更新 Q^
手牌结束一回后,我们要更新theta,每位玩家,其状态及所采取动作我们已知,动作对应估计价值,游戏中获实际奖励我们也有,某种意义上,实际获奖励是“正确解”,动作估计价值异于此,我们模型有误,我们需更新theta,让Q^(φ;θ)更靠近正确答案。
使 φ’ 成为一个玩家所处的特定状态,R 是她所获取的实际奖励。使L等于(R 减去 Q 的(φ 与 θ)次方)的平方。L 被称作损失函数。L 越小,R 就越接近 Q 的(φ 与 θ)次方,如若 L 为 0,那么 Q 的次方恰好等同于 R。也就是说,我们期望微调整 θ,让 L 变得更小。(留意,存在诸多可能的损失函数,致使随着 Q 的次方愈发接近 R,L 越来越小。此处的损失函数仅是一个常见的选择)。
所以,「更新 Q」的意思是,通过改变θ,进而让L变得更小。能够做到这一点的方法并非只有一种,其中一种较为简单的方法叫随机梯度下降(stochastic gradient descent)。简单来讲,它更新θ所依据的规则是:
我们要去挑选「超参数」α,它被称作学习率,此超参数能够把控每次更新的幅度。要是α过小,那么学习速度就迟缓,然倘若α很大,那学习过程或许无法达成收敛。把L代入进这个更新规则里头,接着开展几行微积分运算的工作,结果我们就收获了。
提供更新参数准则的是最后一行,我们会依据这个来编写代码,要注意此地的θ以及φ均属于长度为7的向量,在此处更新参数的准则,针对每个元素都适用。
整合
最后,该整合所有内容了。重复以下步骤:
1. 随机发给每个玩家手牌。
2. 令玩家各自选择一个动作。
3. 得到结果。
4. 使用观测到的(状态,动作,结果)元组更新模型。
以下的函数,名为 mc 的那个,达成了这般的蒙特卡罗算法情形,且返回了用于学习模型的参数 theta 。
特别注意,上节推导出的参数更新规则在代码中得到了实现。
结果
解释模型
本例中,固定 S=10。
我们获取到了数字,然而,它们具备意义吗?事实上,存在几种方式能够协助我们进行判断,并且借助它们获取一些关于模型的解释 。
首先,我们思索某些特定的情形。当SB选择弃牌(FOLD)时,其估计的值是多少呢?很轻易便能得出,由于在这种状况下φ相对简易。实际上,除开第1个(固定为1)以及第6个(对应于isSB)以外,所有的元素都是0:phi =。
1,0,0,0,0,1,0
因此,我们所拥有的线性模型的 Q^ ,仅仅是等同于进行加总操作的 theta 的第 1 个元素与第 6 个元素 , 。
现今,我们已然明晰,依据游戏的规则,SB所抉择的弃牌的价值为9.5 。故而,极其酷炫,模型跟真实情形极为贴近!这是一项很棒的逻辑判断,还借助例子阐述了怎样去估量我们模型有可能呈现出的误差值的大小。
还有一种情形是,BB选择弃牌,唯有phi的首个元素并非零值,我们察觉出一个估计数值,。
虽说并不明晰确切的答案究竟会是怎样,只是明白它必定处于9要是SB始终是GII和10.5要是SB始终弃牌之间。实际上,这个数值相较于10.5更朝9靠近,这与 SB 更倾向于 GII 而非什么相一致,这并不明确但就是这么个情况。
存在着一种更为普遍、更具一般性的方式,用以对每一个 θ 输入予以思考。每一个元素 θ_i 均会致使 Q^ 发生增加,这是由于与之对应的特征 φ_i 会出现增加 1 的情况。举例来说,当存在恰当的手牌且得以同时执行 GII 策略之际,θ 的第 5 个元素会产生增加 1 的变化。所以,拥有适合手牌的估计奖励值为 0.22571655,这是一个微小的正向奖励。看起来是合乎情理的。
首先,θ的第2个元素指的是对应玩家排名较高的手牌,这个元素的值是6.16764962 。然后,这对应着这样一种特征,就是假如是isGII的话,那么就是rank2除以numRanks ,不然的话就是0 ,说的是玩家排名较高手牌时的GII策略。这里,rank2除以numRanks ,所以,特征每增加1大约就等于2 与ace之间的差 。最后,以一个额外的6 BB加上1个ace而不是2来取得胜利,看起来好像是挺合理的。(但是,为什么你会觉得有第二张更高的手牌显然是负的?)
检查与第6个特征相对应的θ的元素,若isSB为1,其对应元素为1,若isSB不为1,其对应元素为0,若所有其它特征相等,那么在SB中的附加值明显为 -0.15230302,我们或许能将这解释为位置上的劣势,这是由于存在不得不首先采取行动而产生的小惩罚 。
然而,其他所有方面并非必然相同。特定条件下,若 SB 执行 GII 策略,那么最后一个特征同样不为零。所以 -0.15230302 构成了 SB 执行弃牌时的一项附加值。当执行 GII 时,我们对最后一个特征的贡献予以总结,得出奖励为 -0.15230302 加上 0.14547532 等于 -0.0068277。显然能看到,当 SB 采取更为激进的策略时,位置劣势便会减少!
在这里,我们看到,于本问题范畴之中,挑选有意义的特征能够助力我们有效地解释结果。有意思的是,存在一个被称作SAGE的老规则用以玩德扑游戏。该规则在锦标赛现场易于被记住。其原则是为你的手构建「能力指数」,此指数依据顺子(rank)、同花(suitedness)以及对子(pair)按规则构建,接着用它来决定是否GII。它们的特征组合跟我们的特征组合相比较会怎样呢?它们的结果如何呢?
最终,为何我们选用isSB以及isGII用以确定最后的那个特征,而非仅仅只是isGII呢?对此展开思考。(BB,FOLD)的估计数值仅仅是θ的第1个元素,因而这个第1个元素必须能够任意地变动,以此来获取正确的(BB,FOLD)值。那么,第6个元素乃是在SB里的额外贡献,它得能够任意地变动以取得正确的(SB,FOLD)。
一旦我们从弃牌转变为GII,元素2至5变成非零状态,且依据玩家调整成特定值,不过这些决策同样对于SB和BB适用。该模型需要产出给SB全押的一些有别于BB全押的决策。
假设我们最后的特征是,若为isGII那么就是1,不然就是0。这并非由玩家决定,于是SB和BB的估计值之间唯一的不同会在于isSB这一项。这个数值得把执行弃牌时SB和BB之间的差别考虑进去,还要加上执行GII时SB和BB之间的差别。模型必须在这两个差别之间选出一个数值,最终或许会引发一些不太好的折中情况。恰恰相反的是,我们所需要的是,若为isGII且是isSB就是1,否则就是0。如此一来,此模型能够分辨出SB GII跟BB GII的增量数值。
需留意,这个模型依旧没办法捕捉诸多细微的细节处。比如说,鉴于模型是完完全全内置的函数形式,我们所见到的 GII 估计值的差异,在两个特定的手牌组合情形下,像 A2 以及 K2,对于 SB 和 BB 已然是全然相同的。不论 θ 的值究竟怎样,我们的这个模型都绝对没有可能做出预测。
有着很高偏差值(bias)的这样的模型,它是不灵活的,且存在一个决定结果样子的强大内置「观点」,这便是特征工程如此重要的原因。要是我们未曾尝试为算法提供精心设计的特征,那么也许它就没有表征一个很好解决方案的能力。
模型能够被增添更多特征,像是其他交叉项,借此得到偏差较低的模型,然而这或许会引发缺点,这会迅速丧失可解释性,还可能遭遇更多技术问题,像过拟合,当然,在多数运用里这并非首要问题,准确性比可解释性更具重要性,并且存在处理过拟合的办法。
可视化策略
为了找出完整的策略,我们会对该模型进行评估,以此去知晓在每个玩家的1326种手牌组合当中,究竟是GII更好还是弃牌更好 :
看样子,针对于 SB,大概 55%的手牌抉择是全部押注,然而对于 BB,大概 49%的时段会选择跟进加注:
最终,我们能够生成些许 SVG,用以在 Jupyter 环境里绘制 GII 范围,。
对于我们而言,该如何去进行选择呢,在此地存在着诸多我们所期望的具备定性性质的特征呢,诸如,大的手牌状况良好是很不错的,拥有对子这种情况也是挺好的,属于同花的情形要优于并非同花的情形,SB的打法相较于BB而言更为宽松等等,然而,处于边界线状态的手牌其打法有的时候会和处于真正的平衡策略的打法之间存在差异,是不一样的 。
结语
一篇介绍性的、应用 RL 技术的文章,给我们提供了一些合理的策略,用以进行德扑游戏。该学习过程,不依赖于任何的结构,也不依赖于任何游戏规则。它纯粹地通过让智能体自己去进行游戏,去观察结果,然后依据此来做出更好的决定。另一方面,重要特征工程,需要一些领域专业知识,才能够学习一个好的模型。
无模型,agent 通过采取相应行动,进而观察奖励来实现学习。它无需具任何关于怎样产生这些奖励的先验知识,诸如关于范围、权益,甚至游戏规则等方面的了解,并且也未曾试图仓促地去学习这些内容。于扑克游戏里,实际上我们对某些手牌以及动作会致使何种特定奖励颇为清楚,我们能够借助这一点,然而在许多其他情形下却并非如此。
基于价值的,我们着重于去找出处于每个状态之时每个动作所具备的价值,随后确定实际的策略,这或多或少可算是事后才产生的想法。还有基于策略的方法,比如虚拟游戏,其重点在于直接去学习于每个状态之下所采取的动作。
蒙特卡罗,我们针对整个手牌组合也就是情节来抽样,依据我们在手牌后所获取的价值展开学习。“时序差分”方法,能够在手牌结束之前,对所有中间状态的预期值予以估计,还能够更高效地运用这些值来学习。鉴于每位玩家在结束之前,于德扑游戏里只能开展单一动作,虽说这对我们而言并非关键所在,但它能够在更多状态的问题上,引发出很大的影响呢。
针对策略,我们要去估计玩家策略所具有的价值。实际上,这件事情并非是简单的。因为玩家有时会采取那种随机也就是并非最优的动作,所以我们所估计出来的价值并非是最优策略所对应的值得,而这并不是我们真正所期望而得到的。即便在对非最优选择展开探索的这个时期,更为复杂的那种“离策略”方式也是能够去了解实际存在的最优策略的。
不少 RL 问题,从起始直到结束,都涵盖诸多(也许无穷多)状态 。对于这种情形而言,当中的 agent 期望让所有未来奖励的总和实现最大化,并非是要最大化即刻奖励 。处于这种状况下,假定相较于在将来某个时刻获取奖励,agent 对当下获得奖励的偏好程度较低 。德扑游戏里一局手牌的时间向来很短,所以我们无需为此担忧 。
线性函数逼近器:在此例当中,所学习的是呈现行的函数,这个函数,会把(状态 – 动作)一对这样的情形的呈现转变映射成为数值。另外的别的能够选用用来替代一番这么呈现学习的方式方法包含有简单的表,这个表是把每一个状态的每一个被展现出来的动作的预估数值分别地专门存放存储搁置的,以及林林总总好些其他种类型类型的那种的函数逼近器。特别格外专门特别地,这样的一种呈现这么的学习方法方式在神经网络里是极为非常相当成功的。在某种一定的不同程度上,造成导致引发这样成功的结果是由于缘由是基于它们并不需要好多好些大量的特征工程来才能够取得到获得不错良好的结果成果。神经网络一般情况下通常平常情况下可以学习去获取到一组不错良好的特征,并且还能够学习到懂得知晓明白该咋样去运用使用到进行使用它们!但是不过本文目前一时当下在这里暂且暂时先不不去探讨研究这个话题主题。

