对于井字游戏、跳棋或国际象棋游戏,我应该如何表示神经网络的输入?

人工智能 神经网络 人工智能设计 井字游戏 棋盘游戏 国家代表
2021-11-10 23:11:09

我最近一直在阅读很多关于 TD-Gammon 的文章,因为我正在探索我正在制作的视频游戏中的 AI 选项。视频游戏是一种基于回合的位置类游戏,即“单位”或游戏块的位置将极大地影响其在该棋盘状态下的实用性。

为了朝着这个方向努力,我认为首先为几个不同的游戏实施神经网络是谨慎的做法。

我喜欢的想法是使用单个输出神经元对神经网络的棋盘状态进行编码,这使得该棋盘状态与其他棋盘状态相比具有相对强度。据我了解,这就是 TD-Gammon 的工作方式。

但是,当我查看其他人的代码和示例/教程时,它们代表棋盘状态的方式似乎存在很大差异。即使是像井字游戏这样简单的事情。

那么,具体来说,对于井字游戏,哪个更好,或者什么是棋盘状态的正确表示?

我见过:

  1. 9 个输入神经元,每个方格一个。A0表示自由空间、-1对手和1你自己。

  2. 9 个输入神经元,但使用不同的值,例如为0对手、0.5免费和1为自己?

  3. 你可以使用更大的值吗?012

  4. 27 个输入神经元。前 3 个是正方形 1,接下来的 3 个是正方形 2,依此类推。每个神经元都是10三组中的第一个表示该方格是否空闲;第二个表示该方格是否被您的对手占据。最后,每 3 个神经元中只有一个有1,另外两个有0

  5. 18 个输入神经元。第一个1用于 X 播放器,第二个1用于 O 播放器,两者都0用于空白

那么,当涉及到特定棋子的能力发挥作用的游戏时,比如在国际象棋中,你会如何表现这一点?

它会像使用更高的输入值来获得更有价值的作品一样简单吗?即为-20对手皇后和+20你自己的皇后?或者您是否需要更复杂的东西,为每个方格定义 10 多个值,为每个单位类型和玩家组合定义一个值?

3个回答

当您使用神经网络时,只要数据存在,神经网络通常能够学习如何将其处理成有用的结果。

但是,您通常还希望将权重的数量保持在最低限度。当您使用额外的权重时,训练网络需要更长的时间,因为您需要调整更多的值以获得最佳网络。

因此,对于井字游戏,任何涉及 9 个输入的解决方案都应该可以正常工作。

此外,如果您使用 log sigmoid 将输入保持在 0 和 1 之间,如果您使用双曲正切作为激活函数,则将输入保持在 -1 和 1 之间会有所帮助。您可能很容易找出其他激活功能的用途。您可以通过称为范围标准化的过程将数据转换为具有特定范围内值的另一个数据集。

对于国际象棋,您可以简单地以几种不同的方式对每个棋子进行编码,并且可能不会有太大的不同。

一般的经验法则是您希望最小化权重的数量,同时仍将最可能的变量提供给神经网络

强化学习方法的基础是给每个(游戏)状态(或动作)一个值,该值以某种方式表示该状态(或动作)有多好。为了存储这些值,我们可以使用像表格/哈希图这样简单的东西,但是像国际象棋或围棋这样的复杂游戏有很多状态,它们无法放入内存中。作为一种补救措施,我们将哈希图视为一个函数,并尝试使用神经网络 (NN) 对其进行逼近。幸运的是,NN 是通用逼近器,这意味着它们可以学习任何函数,包括从棋盘到数字的任意映射。

现在的问题是如何表示一个游戏板并将其提供给神经网络。在井字游戏的情况下,您列出的所有 5 种方法都可以认为是正确的。

从理论上讲,分配给什么(w, b, v)数字(白色、黑色或空白瓷砖)并不重要,如果我们教 NNf(w, w, v, ...) = 1足够多的时间,它会学习这种关联,无论它是(w, b, v) = (0, -1, 1)还是(w, b, v) = (0, 0.5, 1)

现在您的前三个示例使用此方法,但是,这里的一个小缺陷是它为名义事物分配了数字,即数字可以排序,但我们不能真正这么说black > white > vacant您的最后两个示例尝试通过使用one-hot-vectors来解决此问题。

因此,对于像国际象棋这样的游戏,如果我们仅使用数字来表示数字,NN 可能会错误地混淆两种数字类型(例如:棋子是19,后是20,它认为后是试图攻击你的国王,而只是一个棋子)并做出错误的决定。然而,它会知道这个决定是错误的,并会为状态和长期的决定分配正确的值。

最后一点:为问题选择正确的状态表示是强化学习的关键部分(类似于为分类问题选择正确的特征),有时可能会害怕选择非常高维的状态空间。但是请记住,国际象棋不是一个简单的游戏,所以大的状态空间可能不是不合理的。同样作为参考,Atari 游戏的输入维度为84*84*4.

状态表示对于为神经网络准备数据非常重要。您可以尝试不同的方式并选择最适合您的情况。

  • 您可以使用 18 个神经元作为输入,其中每个状态由 2 位表示。但是,如果您使用 sigmoid 激活函数,请避免使用 0 和 1,这可能会导致输出饱和,这意味着如果 output(y) 在任何层变为 1,则在反向传播误差上,我们有y (1-y) dE/ dy在权重更新部分,随着饱和度变为零,这意味着它将永远保持相同的状态。

这个问题可以通过以下方法解决:

解决方案 1.您可以使用 0 和 1 的一些边距来初始化输入。例如,输入可以是 [0.1, 0.9] 而不是 [0, 1]。

解决方案 2。另一个您可以在 [-0.01, 0.01] 的范围内初始化非常小的权重。

解决方案 3.您可以使用正则化技术,其目的是通过添加错误的惩罚项来抑制权重。

  • 要处理方差问题,您可以扩充一些数据,以进行适当的训练。因为,在井字游戏中,您有一个小数据集。为了增加数据,您可以在具有相同输出的输入中添加一些范围为 -0.1 到 +0.1 的边距。

我希望这可能会有所帮助。