如何为国际象棋编写神经网络程序?

30
我希望编写一个能够学习制定好走法并打败对手的国际象棋引擎。我已经编写了一份国际象棋棋盘表示和一个输出所有可能移动的函数。因此,我只需一个评估函数来确定给定情况下棋局的优劣程度。因此,我想使用人工神经网络来评估给定的位置。输出应该是一个数值。数值越高,这个位置对白方就越有利。
我的方法是构建一个由385个神经元组成的网络:国际象棋有六种不同的棋子和64个格子。所以对于每个格子,我们取6个神经元(每个棋子一个)。如果有一个白色棋子,则输入值为1。如果有一个黑色棋子,则值为-1。如果那个格子上没有这样的棋子,则值为0。除此之外,还应该有一个神经元表示轮到哪个玩家行动。如果轮到白方行动,则输入值为1;如果轮到黑方行动,则值为-1。
我认为神经网络的这种配置相当不错。但是主要部分尚未完成:如何将这个神经网络实现在编程语言中(例如Delphi)?我认为每个神经元的权重开始时应该相同。根据比赛的结果,权重应该进行调整。但是如何调整呢?我认为我应该让两个使用我的引擎的计算机玩家互相对抗。如果白方获胜,则黑方得到反馈表明它的权重不好。
因此,如果您能帮助我将神经网络实现在编程语言中(最好是Delphi,否则是伪代码),那将是非常棒的。谢谢!

感谢您迄今为止的回答。我意识到通过神经网络下棋是困难甚至不可能的。 但是,我问题的第二部分是:如何编写神经网络(例如我的配置)?我一点都不知道,所以期待得到一些建议。 - caw
由于自 2009 年以来 SOTA 已经发生了显着变化,因此需要对此进行更新!使用深度 NL 和强化学习混合可以学习下棋是完全可能的! - Keir Simmons
@KeirSimmons 您可以发布一个或添加赏金。 - Bernhard Barker
我想指出,用一个神经元来表示应该移动的玩家并不是一个好主意,因为棋盘的评估不会均匀。我建议如果现在是黑方回合,你可以反转棋盘上所有的价值,这样就不会考虑黑白双方,而是考虑玩家和对手。 - Super Toto
给你点赞,比其他人早想到这个主意5年了 :-) - undefined
9个回答

14

;) 他们先从国际象棋开始,然后转而使用大部分相同的神经网络架构来进行围棋。 - user613326

12

我不明白为什么如果你还用经典的极小化极大搜索和alpha-beta剪枝,就不能使用一个神经网络作为静态评估器。很多国际象棋引擎使用极小化极大算法,并且配以一个愚蠢的静态评估器,只是简单地计算棋子的总数或其他什么;如果你有足够多层的极小化极大搜索,这并不那么重要。我不知道神经网络会带来多大的改进,但几乎没有什么损失。然而,训练它会很棘手。我建议使用一个向前看多步(并占用大量CPU等资源)的引擎来训练一个向前看较少步骤的评估器。这样,你最终会得到一个不需要太多CPU的引擎(希望如此)。

编辑:我在2010年写了上面的内容,现在到了2020年Stockfish NNUE已经做到了。"该网络是通过对数百万个位置进行适度搜索深度的[经典Stockfish]评估进行优化和训练的",然后作为静态评估器使用,在他们的初步测试中,当使用这个静态评估器而不是之前的评估器时,他们获得了80个Elo的提升(或者等效地说,相同的Elo但少一些CPU时间)。所以它确实有效,而且你甚至不需要像我最初建议的那样在高搜索深度下训练网络:适度的搜索深度就足够了,但关键是要使用数百万个位置。


这种方法的问题在于,如果您使用极小化和Alpha-Beta修剪启发式算法,则已经接受您的NN不如评估器的事实。现在我同意这样做很酷,只是为了拥有一个下棋的NN,但实际效益(除了您将获得的经验)并不大。 - Atilla Filiz
3
不。一个由程序员编写的手动评估器 + 深度搜索被用来训练神经网络,希望神经网络 + 浅层搜索胜过手动评估器 + 浅层搜索。如果成功,那么神经网络比手动评估器更好。 - maaartinus

6

这是可能的,但并不容易。

https://erikbern.com/2014/11/29/deep-learning-for-chess/

他使用了大量计算能力来训练他的评估功能。

总的来说,您可以按照以下方式进行。您的评估功能是一个前馈神经网络。让矩阵计算导致一个标量输出,其价值移动有多好。网络的输入向量是由棋盘上所有棋子表示的棋盘状态,例如白色兵为1,白马为2... 空格为0。示例棋盘状态输入向量只是一系列0-12。可以使用国际象棋大师的比赛(例如在fics数据库中可用)来训练此评估,通过将当前参数所述的最高估价和国际象棋大师的推荐移动之间的损失最小化来实现(这些推荐应具有最高的估价)。当然,这假设国际象棋大师的移动是正确且最佳的。


6
曾经做过类似的事情。由于您的问题没有连续性(一个位置的值与只有一个输入值变化的另一个位置的值没有密切关联),因此神经网络的成功几率非常小。在我的实验中从未成功过。我建议使用模拟退火系统和特定的启发式算法(这方面已经有很多)来评估位置的价值...
但是,如果您想使用神经网络,那么它相对容易表示。通用的神经网络只是一个图形,每个节点都是一个神经元。每个神经元都有当前激活值和转换公式,用于基于输入值计算下一个激活值,即具有链接到它的所有节点的激活值。
更经典的神经网络,即具有输入层、输出层、相同的神经元和无时序依赖性的神经网络,因此可以通过输入节点数组、输出节点数组和连接它们的节点的链接图来表示。每个节点都具有当前的激活值和一个它前进到的节点列表。计算输出值只需要将输入神经元的激活设置为输入值,并依次遍历每个后续层,在使用转换公式从上一层计算激活值时计算出来。当您达到最后(输出)层时,就得到了结果。

5
但是TD-Gammon也学会了只用神经网络玩背靠背棋,所以它必须在某种程度上有效,对吧? - caw
1
Blackgammon和Chess是非常不同的游戏...它用随机性代替规则复杂性和广泛的可能性分支。但是NN在处理统计预测方面非常擅长,而在修剪可能解决方案的树方面就不那么擅长了。 - Varkhan
如果有足够的内部节点(对于反向传播神经网络)和训练数据,连续性不会成为问题。问题在于所需的节点数量和训练量使其变得不可行。我同意神经网络是解决问题的不良选择。 - geofftnz
3
因为回答只关注前馈网络,所以被踩了。现在有许多不同的模型,例如卷积神经网络可以用于棋盘上的模式识别,这可以给出某些配置的解决方案。 毕竟,循环神经网络是图灵完备的,因此理论上可以下棋。 - Benedikt S. Vogler
1
基于神经网络的Alpha Zero和Leela Zero超越了所有传统的国际象棋引擎,证明了这个答案是错误的。 - user1066278
显示剩余3条评论

4
你需要训练人工神经网络所需的是像反向传播学习或某种形式的遗传算法。但是,象棋是如此复杂的游戏,以至于简单的ANN将难以学会玩它 - 尤其是如果学习过程是无监督的。

此外,您的问题没有提及层数。您想使用385个输入神经元来编码当前情况。但是您想如何决定该做什么?每个领域一个神经元?最高激活获胜?但是常常有不止一种可能的走法。

此外,您将需要多个隐藏层 - 可以用输入和输出层表示的函数在没有隐藏层的情况下真的很有限。

因此,我不想阻止您尝试,但是在一年左右的时间内实现和培训的成功机会几乎为零。

当我大约16岁时,我曾尝试构建和训练ANN玩井字棋...但失败了。我建议先尝试这样一个简单的游戏。


神经网络应该只评估一个位置。其他函数计算所有可能的移动。然后,对于每个移动,得到的位置被送到神经网络中,该网络会给出一个数值作为评估。例如,白方宁愿采取导致4.5而不是-6.2的移动。 - caw
正如Varkhan所指出的那样,该评分函数将非常波动,并且很难用人工神经网络来表示。 - Daniel Brückner
我也无法编写井字棋程序,因为我缺乏相关的知识技能。因此我在这里询问如何实现这样一个神经网络。在我看来,神经网络是一个非常抽象的东西。虽然我可以想象它是如何工作的,但我不知道如何编写代码来实现它。所以我希望有人能在这里帮助我。 - caw

4
我看到的主要问题在于培训。您说您希望您的人工神经网络(ANN)接收当前的棋盘位置并评估它对玩家有多好。 (我假设您将为每个可能的玩家移动将其应用于当前的棋盘状态,通过ANN进行评估,然后选择具有最高输出的那个 - 即:爬山法)。
我认为您的选项如下: 1. 开发一些启发式函数来评估棋盘状态并从中训练网络。但这引出了一个问题,即为什么使用ANN,而不是只使用您的启发式算法。 2. 使用某些统计度量,例如“白色或黑色从此棋盘配置赢得了多少场比赛?”,这将为您提供白色或黑色之间的适应值。但问题在于您需要大量的训练数据来解决问题空间的大小。
使用第二种选项,您可以始终向其提供来自国际象棋大师比赛的棋盘序列,并希望ANN覆盖足够,以便开发出解决方案。
由于问题的复杂性,我建议您尝试使用最大的网络(即:内部节点很多),但不会使培训速度变慢。

谢谢。我已经测试过了。它是可行的,但你需要无法想象的大量训练数据 - 正如你之前所写的那样。在国际象棋中,有大约2.28x10^46种可能的位置,因此你永远不会有足够的训练数据来处理每个位置。 - caw
2
是的,尽管神经网络的想法是它应该能够在有限的训练集下进行泛化。很多取决于您试图拟合的函数的复杂性,在国际象棋的情况下将会非常复杂。 - geofftnz
好的,你说服了我。但是你怎么编码呢?我很想测试一下,尽管我现在知道我的引擎永远不会成为职业选手。 - caw

1

你的输入算法很好 - 所有位置、所有棋子和两个玩家都被考虑在内。你可能需要为游戏板的每个过去状态添加一个输入层,以便过去事件再次用作输入。

输出层应该(以某种形式)给出要移动的棋子和要移动到的位置。

编写一个使用包含所有神经元权重和突触强度的连接组的遗传算法,并开始多个分离的基因池,每个基因池中有大量的连接组。

让它们相互对弈,保留最好的几个,交叉和变异最好的连接组以重新填充池。


1

0

来这里说一下Silas所说的。使用极小化算法,您可以期望能够向前看N步。使用Alpha-beta剪枝,您可以将其扩展到理论上的2*N步,但更现实的是3*N/4步。神经网络在这里非常适用。

也许遗传算法可以使用。


2
被踩了 - 这与问题有何关联?问题明确询问的是神经网络。 - Arafangion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接