最近,强化学习(RL)的成功(如 AlphaGo)取得了大众的高度关注,但其基本思路相当简单。下面我们在一对一无限注德州扑克游戏上进行强化学习。为了尽可能清楚地展示,我们将从零开始开发一个解决方案,而不需要预设的机器学习框架(如 Tensorflow)。让我们用 Python3 Jupyter notebook 开始吧!
- 问题设置
- 强化学习
- 特征:
的输入(下文使用 Q^表示 Q hat)
- 关于 Q^ 的线性模型
- 模拟扑克游戏
- 学习:更新 Q^
- 整合
- 结论
- 解释模型
- 可视化策略
- 结论
问题设置
规则提醒:该游戏是一个 2 人无限注的德扑游戏,其中:
1. 游戏开始,两名选手均有 S 筹码和随机发放的 2 张底牌。
2. BB(大盲注)玩家下 1.0 个盲注,SB(小盲注)玩家下 0.5 个盲注。
3. 小盲注玩家可以全押(all-in)或弃牌(fold)。
4. 如果小盲注玩家全押,那么大盲注玩家可以跟注(call)或弃牌。
我们可以将规则可视化为下图所示的决策树。游戏开始于 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 恰好是 6♦2♣,我们有:
当玩家全押时,他们平均获得的底池(「期望利益」)根据游戏规则决定。文件 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 [i,j] 指当对手持有手牌 j 时持有手牌 i 的期望利益。
当然,有时候两人起始手牌有一张牌是相同的,在这种情况下,它们的期望不能同时计算,这时取得他们的期望利益也不合适。文件 pf_confl.dat(http://willtipton.com/static/pf_confl.dat)包含另一个 1326×1326 矩阵,其中每个元素为 0 或 1。A 0 表示两位玩家的起始手牌不一样,a 1 表示起始手牌一样。
例如,由于手牌 56 是 6♦2♣,57 是 6♥2♣,58 是 6♣2♠,于是我们有: