Alpha Zero 的移动编码是如何工作的?

人工智能 强化学习 零字母 多代理系统 行动空间
2021-11-11 17:25:38

我是AI的初学者。我正在尝试训练多智能体 RL 算法来下棋。我遇到的一个问题是用数字表示动作空间(合法移动/老实说只是一般移动)。我查看了 Alpha Zero 如何表示它,他们使用 8x8x73 数组来编码所有可能的动作。我想知道它实际上是如何工作的,因为我对他们的解释有点困惑:

国际象棋中的走法可以分为两部分:选择要移动的棋子,然后在该棋子的合法走法中进行选择。我们代表政策π(as)由一个8×8×73平面堆栈编码超过 4,672 个可能移动的概率分布。每一个8×8位置标识从哪个方格“拾取”一块。前 56 个平面为任何棋子编码可能的“皇后移动”:一些正方形[1..7]沿着八个相对罗盘方向之一{N,NE,E,SE,S,SW,W,NW}移动棋子。接下来的 8 个平面编码了该棋子可能的骑士动作。最后的 9 个平面在两个可能的对角线中分别编码了棋子移动或捕获的可能欠促销,分别为骑士、主教或车。第七级的其他棋子移动或捕获被提升为皇后。

例如,一个数字如何表示移动 1. e4 或 1. NF3(以及 1. NF3 的整数与 1. f3 有何不同)?你怎么知道哪个整数对应哪个动作?这就是我本质上要问的。

1个回答

让我们做代码,所以所有的细节都下来了。

编码字典:

codes, i = {}, 0
for nSquares in range(1,8):
    for direction in ["N", "NE", "E", "SE", "S", "SW", "W", "NW"]:
        codes[(nSquares,direction)] = i
        i += 1

您会看到字典中每codes都有 56 个条目。(nSquares,direction)

骑士移动我们将编码为长的“二”单元边缘首先移动,短的“一”单元边缘第二:

for two in ["N","S"]:
    for one in ["E","W"]:
        codes[("knight", two, one)] , i = i , i + 1
for two in ["E","W"]:
    for one in ["N","S"]:
        codes[("knight", two, one)] , i = i , i + 1

现在我们应该有 64 个代码。据我了解,最后的 9 步是当棋子达到最终排名并选择被低估时。它可以通过移动N或捕获NE来达到最终排名NW对三件可能促销不足。编写代码:

for move in ["N","NW","NE"]:
    for promote_to in ["Rook","Knight","Bishop"]:
        codes[("underpromotion", move, promote_to)] , i = i , i + 1

如前所述,我们得到 73 个代码。

政策

动作的分布是一个(8,8,73)张量(它不是正式的“策略”,因为策略也应该依赖于状态,但让我们在这个讨论中切入这个角落):

policy = np.zeros((8,8,73))

为方便起见,我们还为列编写代码:

columns = { k:v for v,k in enumerate("abcdefgh")}

一个数字如何表示移动 1. e4

前两个维度选择您要移动的图形。所以,那将是e2典当。我们将向北“N”移动 2 个单元格。

因此,我们在适当的索引处将 1 放入张量中。请注意,您必须从行索引中减去 1,以使其从零开始。

e4policy = np.zeros((8,8,73))
e4policy[ columns['e'] , 2 - 1 , codes[(2 , "N")]] = 1

一个人如何用数字表示这一举动 1. NF3

前两个维度选择您要移动的图形。所以,那就是g1骑士。我们进行西北NW骑士跳跃。

NF3policy = np.zeros((8,8,73))
NF3policy[ columns['g'] , 1 - 1 , codes[("knight", 'N' , 'W')]] = 1

通常,策略是所有可能移动的概率分布,因此策略张量中会有几个非零概率值。例如,有1.e41.Nf3具有 50/50 概率的开放政策将是:

openingPolicy = (e4policy + NF3policy) / 2 

希望这可以解决问题。