德州扑克吸金强引多家平台觊觎,老k德州扑克手机版咋下载?
2026年1月8日
央视调查德州扑克APP:近万人参与赌博 大型俱乐部月入百万
2026年1月8日选自willtipton
机器之心编译
参与:Jane W、蒋思源
近来,强化学习也就是 RL 的成功,就像 AlphaGo 那样,获得了大众的高度留意,然而其基本的思路是颇为简单的。下面呢,我们要在一对一无限注德州扑克游戏之上开展强化学习。为了能够尽可能清晰地呈现,我们会从零着手去开发一个解决方案,并不需要预设的机器学习框架,像是 Tensorflow 这种。那就让我们借助 Python3 Jupyter notebook 开始吧!
问题设置
强化学习
特征:
的输入(下文使用 Q^表示 Q hat)
关于 Q^ 的线性模型
模拟扑克游戏
学习:更新 Q^
整合
结果
解释模型
可视化策略
结语
问题设置
规则提醒:该游戏是一个 2 人无限注的德扑游戏,其中:
游戏开启,有两名选手,这两名选手都拥有 S 筹码,并且有随机发放的 2 张底牌。
玩家BB也就是大盲注,其所下的注是1.0个盲注,玩家SB也就是小盲注,其所下的注是0.5个盲注 。
对于小盲注的玩家而言,存在着两种选择,其一可以选择全押,其二能够选择弃牌 。
若是小盲注玩家进行全部押注的行为,那么大盲注玩家可有跟注或者弃牌这两种选择。,。
咱们能够把规则呈现成如下面图片所展示的那种决策树,游戏起始于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)。这里,我们将使用强化学习估算解决方案。
这里有
去计算那种不存在重复情况的,两张手牌所构成的组合数量。正因如此,我们能够针对所有的牌来进行排序操作,而且这个排序是从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相关问题存在着三个关键构成板块:乃是状态领域范畴,还有动作方面形态,以及奖励范畴内容。它们共同聚合于这般情形之下:
1. 我们处于某「状态」(即我们观察到的世界的状态)。
2. 我们使用这个信息来采取某「动作」。
3. 我们会得到某种「奖励」。
4. 重复以上过程。
一遍又一遍地重复上述过程:留意状态,采取举措,获取奖励,留意新状态,采取其余行动,获取另外奖项等等。增强学习问题仅是找到怎样挑选行动之方案以获取尽可能多的奖励。事实显示这是一个极为普遍的框架。我们能够借由这么个方式思索诸多状况。解决这些状况又存在好多具有差异的方式。通常来讲,解决办法关乎随机游走,也就是在各异状态挑选各式行为,将哪些组合能获取何种奖励记住,随后试着借助这些信息于未来做出更优选择,。
问题是,RL究竟怎样用于德扑游戏呢,在任何一个决策的时候,玩家清楚他自己持有的2张底牌还有他实际在的位置,诸如此类的就是所处的状态了,接着他能够去采取行动,要么选择弃牌,要么选择做出GII这个动作,这里的GII呢,对于SB来说意思就是进行全押也就是shove,对于BB而言意思就是选择跟注,随后就会得到相应的奖励,这奖励是玩家最终赢到的钱数,在最后的手牌当中我们会采用玩家总的筹码大小,打个比方说,要是一开始筹码大小设定为S等于10,SB选择全押而BB选择弃牌,那么玩家所得到的奖励分别是11还有9 。
通过模拟手牌组合,我们找寻游戏策略,此需要同时兼理两玩家的随机手牌,促使其做出关于玩法动作的决策,之后观察每次结束时最终所获钱财之数,运用这些信息,学习(预估)即 Q 函数 Q(S,A),Q 的参数有状态 S 与动作 A,输出值则是在该状态采取该动作时所获最终奖励值,一旦拥有 Q(或其某种估计),策略选择便简单了:评估各策略,看哪个更佳 。
所以,我们这儿的事儿是估算 Q,我们会用 Q^(念作「Q 帽子」)去指代这个估算。刚开始的时候,我们会随意猜一些 Q^。接着,我们会去模拟一些手牌情况,两名玩家依据 Q^去做出决策。每一次手牌过后,我们会对估算值 Q^加以调整,以此来体现玩家在特定状态下采取特定行动后得到的真实数值。最终,我们理应能得到一个很不错的 Q^估算,而这就是确定玩家策略所需要的全部东西了。
这里得注意一个要点,那便是我们得保证在全部状态下施行全部动作,每一种状态与每个动作的组合都起码尝试一回,如此方可较为妥善地估算出最终各个可能的值,所以,我们会令玩家于时长为ε的一小段时间里随机地采取行动,运用其所获取的 现在是他们所估计的 具备优秀素质功能的合适策略。首先,我们应当踊跃地探索进行选择性行为的可能性,经常性地随心肆意挑选,随着时间的持续进展,我们会更多地借助我们已掌握的具体的知识内容,也就是说,ε会跟着时间的推进而逐渐缩小,达成这一情况的办法存在许多,比如:

因给出从任何状态采取任何特定动作的值,所以 Q 被称作「动作价值函数(action – value function)」,它在多数 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 。我们恰巧晓得connectedness是德扑的关键属性,像它的名字一样 。此外呢,要是所有的特征在量纲方面保持一致,那么该模型的学习所得的效果就会更加出众显著。在这个地方,所有相关的特征大体上是处于 0 和 1 这个范围内之中,这是我们通过拿 rank 去除以 numRanks 而从而得到的结果 。
最后,如果不是isGII(也就是如果动作是弃牌),我们实际上会把这些数字设定为0。我们清楚,当玩家进行弃牌操作时,特定的持有手牌对于结果来说没有任何作用和影响(忽略小概率的卡牌移除效果),所以在这种情形下我们会去除无关的信息。
目前来思索最后那两个元素,头一个直接对玩家所处方位予以编码,然而第二个却同时由isSB以及isGII来决定,为何会呈现这种状况呢,随后我们会展示出这个“交叉项”的必要性 。
关于 Q^ 的线性模型
我们会去学习一个用于估计的Q^函数,此函数为线性函数。这进一步表明,我们实则要去学习一个参数向量,这个参数向量平常被称作θ,它的长度,具体是7,与特征向量的长度保持一致。而后,我们会针对特定的φ来对Q^作出估计:
在此处,下标 i 用来指代向量的那些特定元素,并且把参数列表写成 $(φ ; θ)$,这意味着 Q^ 这个值是依存于 φ 和 θ的,不过我们能够认定它是 φ 的函数,这里 θ 是固定的值 。代码的简单程度为:

即便该函数被广泛运用,可此算法并无突出之处,无法使其成为解决此问题的最优之选。此仅为一种途径:把某些学习参数与某些特征相互结合来获取输出,且完全由我们去定义一个θ向量,让其生成我们期望的输出。然而,恰当选取θ会助我们精准估计在持有特定手牌时采取特定行动的价值。
模拟扑克游戏
我们接下来要进行「玩」手牌这个行为了,我们会在后续的几个部分里开展此项活动,不过当下我们要先构建三个起到关键作用的概念,这些概念跟 RL问题的三个有着重要意义的组成部分存在关联,分别是状态、动作以及奖励,首先来说状态,每一次进行手牌操作时,我们会通过随机发牌这样的形式去对每个玩家的状态作出初始化操作!

第二点,要采取动作,每个玩家会运用当前的模型,也就是由 theta 所给出的,还有已知的手牌以及自身身份,它是为 SB 的前提下,去选择动作。在以下的函数当中,我们会去估测 GII 和弃牌,亦或是 FOLD,也就是 qGII 和 qFOLD 它们的值。之后选取当下的最优项,其概率是 1减去 ε,不然则随机地去选择动作。最后返回所采取的动作,以及与之相应的价值估计和特征向量,这两项我们在之后是会用得上的。

第三点,当明确每个玩家此刻手中的牌以及其动作后,我们通过模拟剩余尚未出现的牌来获取玩家所能得到的奖励。若有哪怕一个玩家选择弃牌,那么我们能够马上 返回正确无误的奖励数值。不然的话,我们依据玩家当前所处的状态以及预估的奖励期望权益,在恰当的时间段随机挑选出一个获胜者来 。

在玩家将所有筹码都押上的情形下,我们凭借小技巧躲开了模拟。跟借助5张公共牌切实模拟游戏,还评估玩家手中的牌以判断谁获胜不一样,我们现下依据预先算好的概率随机挑出一个赢家。这在数学层面是等同的(琐碎的证明予以忽略),这仅仅是一种更便利且计算效率更高的方式 。
最为关键的一点是,对于我们而言的学习进程,并未借助于这些公平性或者涉及游戏规则的诸多信息。就如同我们很快就会目睹的这般,哪怕是充分地去进行模拟,学习的这一过程仍旧没有产生什么差异,甚至智能体还会和外部黑盒的扑克游戏体系相互进行作用,进而有可能去遵循彼此有别的规则!那么,学习进程实际上到底是怎样开展的呢?
学习:更新 Q^
当一次手牌结束后,我们要更新theta。对于每一个玩家,我们清楚其状态以及所采取的动作。我们得到了动作对应的估计价值以及从游戏里获取的实际奖励。从某种层面来讲,实际获取的奖励是所谓的「正确解」,如果动作的估计价值和此不一样,那么我们的模型就存在错误。我们务必要更新theta,从而让Q^(φ;θ)更加靠近正确的答案。
设 φ’ 是玩家所处的特定状态,R 是她所获的实际奖励。设 L 等于 (R 减去 Q 的 φ 次方对于 θ;的计算结果的平方)。L 有着损失函数这一称谓。L 越小的时候,R 就越靠近 Q 的 φ 次方对于 (和这个 θ;的计算。要是 L 等于 0),那么 Q 的次方就恰好等同于 R。也就是说,我们要微小调整 θ 以此谋求使 L 相对更小。[ noteworthy:有大批可能的损失函数,随着 Q 的次方益发靠近 R,L 就越发变小。这里的损失函数只是被普遍采用的一个选例 ]。
所以,「更新Q」意味着凭借改变θ致使L变得更小,存在不止一种达成这一目的的方式,其中一种简便的方式是随机梯度下降(也就是stochastic gradient descent),简单来讲,它更新θ所依据的规则是:
我们要去挑选「超参数」α(此为称做学习率的东西),它具有把控每次更新幅度的能力。要是α过小,那么学习速度会迟缓,然而要是它极大,则学习进程有可能没法达成收敛。把L代入到这个更新规则里面,展开几行微积分运算,我们得出。

那最后一行有的是提供更新参数的准则,我们会依据这个来编写代码,留意这儿的θ跟φ都是长度为七的向量,这儿更新参数的准则分别对每个元素适用 。
整合
最后,该整合所有内容了。重复以下步骤:
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 个元素,以及 theta 的第 6 个元素,。
当下,我们已然清楚,依据游戏的规则,有个叫SB的选择弃牌时其价值是9.5 。故而,极其酷炫,模型跟真实情形十分相近!这是一项很棒的逻辑判断,还借助例子阐明了怎样去估计我们模型有可能出现的误差值大小 。
另一种情形是,BB选择弃牌,仅有phi的第1个元素并非零值,我们发觉获得一个估计数值,。
尽管并不明晰正确答案究竟是什么,只是晓得它必定处在9(假设总是如此GII)与10.5(当总是弃牌的时候如此SB)两者间。实际上,这个数相比于10.5更趋近于9,这契合并非契合SB相比于弃牌更倾向于GII这方面之事。
有一个用来思考每个 θ 输入的更具普遍性的方法,每个元素 θ_i 会令 Q^ 产生增加,这是由于与之对应的特征 φ_i 会出现增加 1 的情况,举例来说,当存在适当的手牌并同时施行 GII 策略时,θ 的第 5 个元素会出现增加 1 的情形,所以,具备适合手牌的估计奖励值为 0.22571655,这是一个微小的正向奖励,看起来是符合情理的。
θ的第二个元素,此元素对应玩家,其排名较高的手牌,这个第二个元素是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的玩德扑游戏的老规则。这条规则在锦标赛现场是比较容易被记住的。该规则的原则是为你的手牌构建“能力指数”,“能力指数”是依照顺子、同花以及对子来进行规则构建的,构建好后用它来判定是否GII。它们在特征方面的组合较量于我们的特征组合而言究竟怎样呢?它们最终得出的结果又是如何呢?
最终,为何选取isSB以及isGII去判定最后一项特征德信竞技,而非仅仅只是isGII呢?对此进行思考。(BB,FOLD)的估算值仅仅是θ的首个元素,因而这个首个元素应当能够肆意变动,从而获取正确的(BB,FOLD)数值。那么,第6个元素乃是于SB里的额外奉献,它需要能够肆意变动以取得正确的(SB,FOLD)。
一旦我们从弃牌变为进行GII,元素2至5转到处于非零形态,且依据玩家情况调整成特定的数值,然这些判定同样适用于SB和BB此二者。该模型要给SB全押给出某些相比BB全押迥异的判定 。
假如我们最终的特征是这样的,若为isGII那么数字是1,要是不为isGII不然呈现为0 ,此情况和玩家无关,于是在所估计的值里,SB与BB之间唯一的差异会体现在isSB这一项上 ,这个数值得将执行弃牌之时SB和BB之间存在的差异考虑进去,并且还要把执行GII之际两者的差异也给考虑进去 ,模型得在这两个差异当中选出一个数字,最终或许会引发一些不太好的折中结果 ,与之相反,我们所需要的是,若isGII并且isSB那数字就是1,不然就是0 。该模型能够区分SB GII的增量值,该模型,还能够区分BB GII在这种情况下的增量值,如此这般。
留心,此模型依旧没能领会诸多渺小微末的详情。举例来说,鉴于模型内含完整一体的函数据式,我们所见到的在两个特定手牌组合状况下、像 A2与K2这般、针对 SB 和 BB而言的GII的估计数值的偏差是全然一样的。无论θ的值怎样,咱们这个模型都绝无可能用以预测 。
有这样一种模型,其偏差值(bias)很高,它不灵活,还有一个强大的内置“观点”,用以确定结果会呈现何种样子,正是基于此,特征工程显得极为重要,倘若我们未曾尝试为算法提供依据精心设计的特点,那么它很可能就欠缺表征一个优良解决方案的能力。
有能力为模型增添更多的特征,像是其它的交叉项,借此来获取偏差相对较低的模型,然而这很有可能带来不足之处,这种增加特征的情况会迅速地丧失掉可解释性,同时也或许会遭遇更多的技术方面的问题,就像过拟合这种情况,当然就在多数的使用情形当中这并非是处于首要位置的问题,因为准确性相较于可解释性而言是更为重要的,并且存在用以处理过拟合这种情况的办法。
可视化策略
我们针对要找出完整的策略这一事项,会去评估那个模型,是要弄清楚在每一个玩家的1326种手牌组合当中,究竟GII或者弃牌哪一个会更好呢,是这样的:

这么看,针对于称为SB的对象而言,大概有55%持有的手牌会选择全部押上这样的行为操作,然而针对称作BB的对象来讲,约莫49%的时段会抉择跟注这种举动:

最后,我们能够生成某些 SVG,用以在 Jupyter 环境里绘制 GII 范围,标点符号。


为啥我们要做选择?这儿存在不少我们所期望的诸多定性方面的特征呢:大的手牌状况良好,有对子是相当不错得,同花的情形要优于不同花的,SB的打法相较BB而言更为宽松。然而,处于边界线状态下手牌的打法有时候会同处于真正的平衡策略里的打法存在差异。
结语
有一篇此类介绍性质的文章专为我们呈上借助 RL 技术的一些于合理度层面说得通的策略能在德扑游戏里运用。其展开的学习进程并不依附借助依靠哪怕在任何结构这儿有或者游戏规则那方面有的成分。纯粹是以智能体自身去开展进行游戏,去观察所出现的结果,并且于此种情况依据这些拿来再做出更优的决定这样的方式。另外一方面,重要特征工程在学习得以有一个好的模型时需要一些领域专业知识。
无模型方式下,agent 凭借采取行动,以及观察获取奖励来展开学习。它无需任何有关如何产生这些奖励的先验知识,诸如像是范围、权益,乃至游戏规则方面,也未见其试图仓促去学习此类内容。于扑克游戏里,实际上针对某些手牌以及动作会致使何种特定奖励,我们是颇为知悉的,我们能借此。然而在诸多别的情形状况下,却并非如此这般。
于价值所依的情况而言:我们着重于去找出处于每个状态之下每一个动作所具备的价值,接着去确定切实可行的策略,这略微算是事后萌生出的想法。另外存在基于策略的办法(就像是虚拟游戏那般),它的重点在于直接去学习于每个状态之际所采取的动作。
蒙特卡罗:抽取整个手牌组合(情节)的样本,按手牌后获得的价值以此学习。“时序差分(temporal difference)”方法能在手牌结束前估计所有中间状态预期值,还可更高效用光这些价值作学习。因每个玩家于德扑游戏结束前仅能来一次单一动作,虽此对我们并不要紧,却能在更多情况里产生重大的影响 ,。
对于策略,我们要估计玩家策略所具备的价值。实际上呀,这绝非等闲容易之事。只因玩家有时会施行随机的、并非最优的动作,故而我们所估计出的价值并非最优策略所对应的那个值,而这可不是我们真切所求的。即便就在探索非最优选择的这个当口,更为繁杂的「离策略(off policy)」方法同样能够知晓实际存在的最优策略。
无折现型,多数 RL 问题自始至终涵盖不少(或许无限多)状态,对,于这般情形下,agent 欲把所有未来奖励的总和增至最大,而非将即刻奖励最大化,在此种情形里,假定相较于将来某时获取奖励, agent针对当下拿到奖励的偏好更小,德扑游戏的一局手牌时间向来很短,因而我们无需忧心。
线性函数逼近器:在这个例子里所学的是线性函数,这个函数把(状态 – 动作)对的表征映射成数值。其他的替代办法包含简单的表,这个表把每个状态的每个动作的估计数值单独存放着,还有多种多样别的类型的函数逼近器。尤其值得强调的是,这种法在神经网络当中极为成功。在一定程度上,之所以如此是源于它们不需要诸多特色工程就能取得不错的成果。神经网络一般情况下能够学到一组不错的特征,并且还能学到如何去运用它们!不过本文暂且不去探究该话题。


