
打德州扑克久了,你会发现这些学到的东西超有价值
2026年1月22日
德州扑克单挑有啥打法技巧?这里都给你讲明白了
2026年1月22日
资料图
选自willtipton
机器之心编译
参与:Jane W、蒋思源
近日,强化学习,即 RL,所收获的成功,像那款名为 AlphaGo 的,引发了大众极高程度的关注,然而其内在的基本构思实属相当单一寡陋,下面呢!我们针对这样一种情境展开强化学习实验,此任务是在一对一、毫无限制投注门槛的德州扑克这个纸牌类游戏之上。为了能够以一种极大可能性达到清晰明了的展示程度,我们会着手去开创一个全新的解决方案,而且是从最基础的原点开始,完全不需要借助那些预先设定好的机器进行训练学习的框架,比如说像 Tensorflow 这种已有的成熟框架。现在,就让我们借助 Python3 语言环境下的 Jupyter notebook 软件来正式开启此项工作吧!
问题设置
规则提醒:该游戏是一个 2 人无限注的德扑游戏,其中:
游戏开启,有两名选手,这两名选手各自都拥有S筹码,还分别被随机发放了2张底牌。
两个玩家参与下注,其中BB玩家即大盲注玩家,下了一个盲注的量,为1.0,另外SB玩家也就是小盲注玩家,下了半个盲注的量,是0.5 。
小盲注的玩家,能够选择全押,也就是 all-in,或者选择弃牌,也就是 fold。
若小盲注玩家有进行全押这一行为,那大盲注玩家能够选择跟注或者选择弃牌。
我们能够把规则以如下这样的方式,可视化作像下图所展示出来的那种决策树 。游戏起始于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这个问题仅仅是要找出怎样去选择行动的方案,以此来获取尽可能多的奖励。事实表明这是极具普遍性的一个框架。我们能够借由这样的方式去思考诸多问题,而解决这些问题同样存在许多不一样的方法。大抵而言,解决办法关联随机游走,于各异状态挑选诸多行为,记取哪些组合可取得何种奖励,而后试着借助这些信息于将来做出更优选择。
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^估计,这便是确定玩家策略所需的全部内容。
需注意这儿有种情况——得确保挨个状,态采取全部动作,每一个状态与动作的结合起码尝试一回,如此方可较好地估摸出最终每个都有可能的值。故而,会让玩家于短暂时间ε里任意来采取行动,用上他们此时估计出的最佳策略。首先,应积极去探索那些选择的可能性,不断频繁在加以随机选择。伴随时间的推移展,会更多地去运用所获取到的认知内涵识也就是说是。这个e将于时间流淌的过程逐步少就变小 到值。达成这点具备多种方式手段具体的诸如:有很多例子就比如说但不限于: 能够达成诸如像这般的局面,比如说有这类的方法手段可资利用来做达成这点。

通常被称作‘动作价值函数(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。我们恰好是知晓connectedness属于德扑相当重要的属性,正如它自身的名称所表明那般。除了这个情况之外,要是所有的特征量纲都是保持一致的状态、情形,这个模型他所具备的学习效果将会好上加好起来,于此境地、这里,所有的那些相关、有关系的特征粗略大概是处在0、没有和1、数 的范围、区间之内,我们经由、通过把rank给分割用来除以numRanks计算而得将其得以实现、给出得到这个效果 ,它是不一样一个。句号。
最终,要是 not 是 GII(也就是说要是动作属于弃牌这一情况),实际上这时候我们定会把这些数字设定成 0。我们清楚,当玩家执行了放弃出牌这个动作时,特定的持有手牌对于结果而言不会产生任何作用(将小概率出现的卡牌移除效果排除在外),所以在这种状况下我们会把无关的信息给去除掉。
当前思考最后两个元素,第一个直接对玩家位置进行编码,然而第二个同时依赖于isSB以及isGII,为何会呈现这种状况,稍后我们会展示这个“交叉项”的必要性。
关于 Q^ 的线性模型
我们会去学习一个用于估计的线性函数的Q^函数,这表明我们要切实学习一个参数向量,一般称作θ,其长度(7)和特征向量相同,之后,我们会针对特定的φ去估计Q^ 。
这里,下标i用来指明向量的特定元素,把参数列表写成(φ;θ),这表明Q^的值由φ和θ决定,不过我们能够把它当作是φ的函数,此时θ是固定的值。代码十分简单,。

这个函数虽为普遍运用,可此算法无特别之处能让它成该问题最佳选择。这仅是一种方法,是把某些学习参数与某些特征相结合来获输出,且完全由我们定义一个θ向量,让它产生我们要的输出。然而,正确选θ会为我们很好地估计在有特定手牌时采取特定行动的价值 。
模拟扑克游戏
我们接下来要着手于‘玩’手牌这件事了,我们会在后续的几个部分中来开展此项事宜,不过当下我们要先去构建三个关键的概念,这些概念和RL问题的三个关键点相关联,分别是状态、动作以及奖励,首先是状态,每一次进行手牌操作时,我们会通过随机发牌的形式去初始化每个玩家的状态 。

第二点,着手采取动作,每位玩家会运用现今的模型、此模型由theta给出,也会凭借已知的手牌以及身份是SB这情况前来挑选动作。在如下函数当中,我们去估算GII以及弃牌/FOLD、也就是qGII和qFOLD的值。接着抉择当下的最优项、此最优项是1 – ε,不然就随机地挑选动作。返回所实施的动作,还有相应的价值估计以及特征向量,这两项我们后续会用到。

第三点,一旦我们晓得了每个玩家当下所拥有的手牌以及其做出的动作,那我们便去模拟剩余的手牌以此来获取玩家的奖励。要是存在任何一个玩家弃牌,那么我们能够马上返回正确的奖励值。不然的话,我们依据玩家的状态以及奖励期望(权益),在恰当的时间段随机挑选出一个赢家。

当玩家处于全押情形时,我们借助小技巧躲开了模拟。不同于运用5张公共牌实地模拟游戏,进而评估玩家手牌以判断谁获胜,我们当前依据预先算出的概率随机挑选出一个赢家。这在数学层面是等同的(琐碎的证明略去),这仅是种更便利且计算效率更高的方式。
尤为关键的是,我们展开学习的进程未曾借助这些公平性或者有关游戏规则的信息。就如我们很快即将目睹那般,哪怕是全然进行模拟,学习的进程也并无差异,甚至智能体还会跟外部黑盒的扑克游戏系统展开交互进而有可能遵守不一样的规则!那么,学习的进程到底怎样推进呢?
学习:更新 Q^
一次手牌结束后,我们要更新theta,对于每个玩家,我们已然知晓其状态,知晓其采取的动作,我们还有动作对应的估计价值,还有从游戏里获得的实际奖励,从某种意义来讲,实际获取的奖励是“正确解”,要是动作的估计价值跟此不一样,那么我们的模型是有误的,我们需要更新theta,从而使Q^(φ;θ)更靠近正确的答案。
设定,φ‘是一位处在特定状态的玩家,R是她所获得的实际奖励 ,通过(R-Q^(φ;θ))^2而得出了一个L ,这个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
所以,仅相当于加总theta的第1个和第6个元素的,是我们的线性模型的Q^ :
此刻,我们已然明晰,依据游戏的规则,SB 选择弃牌所具备的价值为 9.5。故而,极其酷炫的一点是,模型跟真实情形极为贴近!这乃是一次很棒的逻辑判断,并且借助例子阐释了怎样估算我们模型有可能出现的误差值大小。
还有一种情形是,BB选择弃牌,仅有phi的首个元素为非零状态,而我们察觉到一个估计数值,。
这话表述有些混乱且存在不文明词汇,我先纠正后再改写。纠正后:虽然不清楚正确答案应该是什么,只是知道它肯定在9(若SB始终GII)和10.5(要是SB一直弃牌)之间。实际上,这个数字更靠近9并非(和)10.5,这跟SB更倾向于GII有关。改写后:尽管不明白正确答案究竟是啥,仅晓得它必定处于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之间的差。以一个额外的6BB加上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)数值。同时,第六个元素乃是针对于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的增量数值。
留意,此模型依旧没办法捕捉诸多细微的详情。举例来说,鉴于模型全然内置的函数形式,我们所见到的,在两个特定手牌组合之下,像是A2以及K2,对于SB和BB而言GII的估计值的差异全然是相同的情况。无论θ的值怎样,我们的模型都不具备预测的可能性。
偏差值(bias)很高的模型是这样的,它不灵活,且还拥有一个强大的内置“观点”用以决定结果会呈现出何种样子。特征工程如此重要的原因就在于此。倘若没尝试为算法提供精心设计的特征,那么它或许就不存在表征优秀解决方案的能力 。
能够给模型增添更多的特征,像是其他交叉项在内,借此获取更为低偏差的模型,然而这兴许会致使劣势产生。这就有可能迅速丧失可解释性,同时也或许会碰到更多的技术问题,例如出现过拟合的情形。(当然了,在诸多使用场景当中这并非是首要考虑的事项,准确性相较于可解释性而言更为关键,并且存在应对过拟合的手段)。
可视化策略
首先,我们要评估这个模型,以此来找到完整的策略。然后,我们要了解在每个玩家的1326种手牌组合当中,GII或者弃牌究竟哪个更加好:

乍看上去,针对于SB而言,大概有55%的手牌会做出全押这种选择,然而对于BB来讲,大约在占到49%那个时段会进行跟注 。

最终呢,我们能够去生成一批SVG,用以在Jupyter环境里绘制GII范围,是这样的 。


怎么在这儿诸多我们所想希望拥有的、具备大的手牌良好优秀、存在对子也不错佳妙、同花比不同花更具优势、相较于BB打法较为轻松自在等诸多定性的特征之中进行选择呢你问?可是哟,边界线手牌的打法时不时地会和真正处于平衡状态的策略存在不一样的情况唷。
结语
RL技术一文,是篇介绍性应用文章,它为我们提供了一些合理策略,用于进行德扑游戏。该学习过程,不依赖任何结构,也不依赖游戏规则。它是纯粹地,让智能体自己进行游戏,观察结果,再根据此做出更好决定。另一方面,重要特征工程,需要一些领域专业知识,才可学习一个好的模型。


