击败庄家21点策略表,21点庄家可以看自己的底牌吗

首页 > 经验 > 作者:YD1662024-03-28 01:50:37

图解简单神经网络

在进入训练过程前,让我们先来快速讨论一下使用神经网络的利弊。神经网络是一种高度灵活的算法——就像软粘土一样,神经网络可以自我调整或进行少量转换就能适用于不同的数据集。通过神经网络可以轻松处理像线性回归这样比较刻板的问题。此外,网络层和神经元还能学习深藏于数据中的非线性关系。

但是,神经网络的这种多功能性需要一定的代价,因为它是一个黑匣子。与回归不同,在回归中我们可以通过查看回归系数来了解模型如何做出决策,而神经网络则缺乏这种透明度。同时,神经网络也存在过拟合的风险,就是对数据过度拟合以至于无法对样本数据进行很好的泛化。这些缺点虽不足以使我们放弃使用神经网络,但却值得我们牢记并设计防范措施。

生成训练数据

在训练神经网络前,我们首先需要弄清楚如何构造训练数据,这样训练出的模型才有意义。

我们想要预测什么?在我看来,我们的目标变量有两个候选参数:

  1. 输掉赌局的概率。在这种情况下,我们可能希望模型告诉我们失败的可能性是多少。再说一次,这只有在我们可以增加或减少赌注的情况下才有用,而这在21点中不适用。
  2. 实际上,我们更希望我们的神经网络能够给出正确的行为,拿牌还是停牌。因此,我们的目标变量应为“究竟是拿牌还是停牌”。

我花了一段时间才找出分析目标变量的最佳方法。下文阐述了我找到的方法。

我们需要一种让神经网络知道给定行为是否正确的方法。这种方法不需要确保万无一失,只需要大体正确即可。因此,我判断给定行为是否正确的方法是模拟一场21点游戏:将牌分发给玩家和庄家,检查是否有人拿到了21点,决定一个拿牌的行为(拿牌或停牌),如此模拟游戏直到结束并记录结果。由于模拟玩家每次只做出一个决定,因此我们可以通过他的输赢来评估该决定的质量:

我们基于此规则训练模型,其输出是对于拿牌还是停牌的预测。这次的代码与上次相似,因此在这里我不做详细介绍。

GitHub链接:

https://github.com/yiuhyuk/blackjack

代码的主要功能:

  1. 庄家的明牌(另一张暗牌,牌面朝下)
  2. 玩家手里牌点数总和
  3. 玩家手里有没有A
  4. 玩家的决定(拿牌还是停牌)

目标变量为由上述逻辑定义的正确决策。

训练神经网络

我们的神经网络将使用Keras(开源神经网络库)。先看模块导入:

from keras.models import Sequential from keras.layers import Dense, LSTM, Flatten, Dropout

再为训练神经网络构建输入变量。变量feature_list是包含上面提到的特征(X变量)名的一组列表。数据集model_df储存了所有21点模拟器产生的数据。

# Set up variables for neural net feature_list = [i for i in model_df.columns if i not in ['dealer_card','Y','lose','correct_action'] ] train_X = np.array(model_df[feature_list]) train_Y = np.array(model_df['correct_action']).reshape(-1,1)

用于实例化和训练神经网络的代码其实非常简单。第一行创建了一个序贯型神经网络,即多个网络层的线性堆叠。后面的代码对我们的模型逐层添加网络层(这里的Dense定义了最简单的网络层,即一大堆神经元),这里的数值16,128是指神经元的个数。

对于最后一层,我们需要选择一个激活函数。这个函数把神经网络的原始输出转变成某些能被我们理解的东西。最后一层有两点值得注意:第一,它只包含一个神经元,因为我们是在两个可能的结果间进行预测(二分类问题);第二,使用sigmoid激活函数,因为我们希望我们的神经网络像逻辑回归一样,在拿牌(Y=1)还是停牌(Y=0)之间进行预测 —— 或者说,我们希望知道正确行为是拿牌的概率。

最后两行代码告诉我们的神经网络用什么样的损失函数(二元交叉熵是一种用于概率输出分类模型的损失函数),并调整模型来拟合我们的数据。我没有花太多时间来调整网络层数或神经元个数,但如果你想要尝试我的代码,我觉得这可以作为模型改进的方向。

# Set up a neural net with 5 layers model = Sequential() # line 1 model.add(Dense(16)) model.add(Dense(128)) model.add(Dense(32)) model.add(Dense(8)) model.add(Dense(1, activation='sigmoid')) # final layermodel.compile(loss='binary_crossentropy', optimizer='sgd') model.fit(train_X, train_Y, epochs=20, batch_size=256, verbose=1)

检查模型的表现

一种快速确定我们的模型是否有价值的方法是使用ROC曲线。

请查看链接:

https://towardsdatascience.com/roc-curves-and-the-efficient-frontier-7bfa1daf1d9c)

ROC曲线可以告诉我们,模型在权衡利益(真阳率True Positive Rate)和代价(假阳率False Positive Rate)时表现如何 —— 曲线下的面积越大,模型表现越好。

下图是我们的21点神经网络的ROC曲线 —— 这看上去似乎比随机猜测(红色虚线)要好不少。曲线下的面积,即AUC,达到0.73是明显高于随机猜测的AUC(0.5)。

击败庄家21点策略表,21点庄家可以看自己的底牌吗(5)

21点神经网络的ROC曲线

我是用训练数据来画ROC曲线的。通常,我们希望用验证或测试数据去画,但在这个例子里,我们知道只要我们的样本数量足够大,它对于整体就是有代表意义的(假设21点的游戏规则不变)。并且我们还可以期望我们的模型有很好的泛化能力(任何新数据都有和我们训练数据一样的基本统计特性)。

是时候大显身手了!

在我们的神经网络正式开始21点之前,我们需要给它一个决策规则。请记住,神经网络最后一层中的sigmoid 激活函数会将输出变成“正确的行为是拿牌”的概率。因此我们需要一个决策规则,在给定这个概率的情况下,我们决定是否拿牌。

下面的函数用来确定这个决策规则,model_decision 函数的通过输入神经网络所需要的特征集来做出预测,并将作出的预测与预先给定的阈值进行比较,来决定是否拿牌。在这里我将阈值定为0.52,因为从上次的尝试中我们可以发现爆牌是21点玩家面临的最大风险。因而将0.52作为拿牌的阈值会使我们的模型选择拿牌的可能性小一些,于是爆牌的可能性也相应减小。

def model_decision(model, player_sum, has_ace, dealer_card_num): input_array = np.array([player_sum, 0, has_ace, dealer_card_num]).reshape(1,-1) predict_correct = model.predict(input_array) if predict_correct >= 0.52: return 1 else: return 0 def model_decision(model, player_sum, has_ace, dealer_card_num): input_array = np.array([player_sum, 0, has_ace, dealer_card_num]).reshape(1,-1) predict_correct = model.predict(input_array) if predict_correct >= 0.52: return 1 else: return 0

现在我们需要将上面的函数加入代码中是否决定拿牌的部分。所以当我们需要决定是否拿牌时,神经网络会基于庄家的明牌、玩家手中牌的总点数以及玩家是否有A这三个特征来做出决策。

我们的模型表现不俗!

最后,让我们将神经网络模型的表现与朴素策略模型和随机模型进行比较。有几点值得注意:

让我们看看神经网络是否找到了更优的策略。下表展示了各种策略类型的结果分布。从中我有两个发现:首先,我们的神经网络仅输掉了不到一半的游戏(49%)。 虽然很难说我们会最终获胜,但对于一场赔率固定的游戏来说,这是相当不错的结果了;其次,神经网络实际上并不比会比朴素策略带来更多的胜局,而是能够更频繁地将对手逼成平局。

击败庄家21点策略表,21点庄家可以看自己的底牌吗(6)

各种策略类型的结果

我们还可以观察不同策略在一些重要的特征(庄家的明牌和玩家手中牌的总点数)中的表现。 首先,让我们看一下庄家的明牌对我们三种策略获胜或平局的概率影响。 在下图中,如果庄家的明牌点数较小,神经网络的表现和朴素策略相差不大。 但是,当庄家的明牌点数较大(大于等于7)时,神经网络的表现明显更好。

击败庄家21点策略表,21点庄家可以看自己的底牌吗(7)

获胜或平局的概率随庄家明牌点数的变化(柱形越长概率越大!)

我们还可以看看获胜或平局的概率如何随玩家初始手牌的总点数而变化。结果看起来非常棒,无论玩家初始手牌的总点数是多少,和另外两种策略相比,我们的神经网络都能表现一样好甚至更好。 反观朴素策略, 它在绝望之谷(玩家初始手牌的总点数介于12到16之间)的表现甚至不如随机策略。毫无疑问,神经网络具有更佳的表现。

击败庄家21点策略表,21点庄家可以看自己的底牌吗(8)

上一页123下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.