在python neat中设置可变数量的输入节点

问题描述

我有一个简单的游戏,屏幕上有一个弹跳的球,并且玩家可以左右移动屏幕并向上射箭以弹出球,每次玩家击球时,球都会爆裂并分成两个较小的球,直到达到最小尺寸并消失。 我正在尝试使用一种基于python整洁库的遗传算法以及关于本片关于https://www.youtube.com/watch?v=MMxFDaIOHsE&list=PLzMcBGfZo4-lwGZWXz5Qgta_YNX3_vLS2的本教程的遗传算法来解决该游戏,因此我有一个配置文件,其中我必须指定在该文件中必须有多少个输入节点。网络中,我曾想过要输入玩家的x坐标,玩家的x坐标与球的x坐标之间的距离以及玩家的y坐标与球的y坐标之间的距离。

我的问题是,在游戏开始时,我只有一个球,但是经过几步移动后,屏幕上可能会有更多的球,所以我应该有更多的输入节点,屏幕上的球也更多我必须提供给网络的输入坐标越多。

那么如何以可变方式设置输入节点的数量呢?

enter image description here

config-Feedforward.txt文件

"""
# network parameters
num_hidden              = 0
num_inputs              = 3 #this needs to be variable
num_outputs             = 3
"""

python文件

    for index,player in enumerate(game.players):
        balls_array_x = []
        balls_array_y = []

        for ball in game.balls:
            balls_array_x.append(ball.x)
            balls_array_x.append(ball.y)




        output = np.argmax(nets[index].activate(("there may be a number of variable arguments here")))


        #other...

最终代码

for index,player in enumerate(game.players):
    balls_array_x = []
    balls_array_y = []

    for ball in game.balls:
        balls_array_x.append(ball.x)
        balls_array_y.append(ball.y)

  
    distance_list = []
    player_x = player.x
    player_y = player.y
    
    i = 0

    while i < len(balls_array_x):
        dist = math.sqrt((balls_array_x[i] - player_x) ** 2 + (balls_array_y[i] - player_y) ** 2)
        distance_list.append(dist)
        i+=1

    i = 0

    if len(distance_list) > 0:
        nearest_ball = min(distance_list)

        output = np.argmax(nets[index].activate((player.x,player.y,nearest_ball)))

解决方法

这是一个很好的问题,据我所知,对于像NEAT这样的简单ML算法,谷歌搜索还没有解决。

由于NEAT会显式地编码每个单个神经元和连接,因此显然无法在此处应用深度NN的传统大小调整方法(填充,裁剪,RNN,中间层等)。

我也不知道有什么通用的方法/技巧可以使输入大小对传统的NEAT算法变得可变,坦率地说,我认为没有。尽管我可以想到对算法的一些更改,使之成为可能,但是我认为这对您没有帮助。


因此,我认为您有3种选择:

  • 将输入大小增加到算法应跟踪的最大球数,并将不存在的球的x-diff / y-diff值设置为其他不可能的数字(例如-1)。如果存在球,则实际上为这些x-diff / y-diff输入神经元设置值,并在它们消失时再次将其设置为-1。然后让NEAT弄清楚。同样值得考虑的是连接2个单独的NEAT NN,第一个NN具有2个输入,1个输出,第二个NN具有1个(玩家pos)+ x(最大球数)输入和2个输出(左,右)。第一个NN为每个球的位置生成一个输出(并且每个球都相同),第二个NN获取第一个NN的输出并将其转换为动作。另外:最大球数不必一定是可显示球的最大数,但也可以限制为10,并且仅考虑10个最接近的球。

  • 每个动作侧只考虑1个球(使输入1 + 2 * 2)。可以考虑每侧最低的球或每侧最近的球。这样的预处理可以使这样简单的NN任务变得很容易解决。也许您可以在测试环境中增加惯性,从而增加非线性度,使其始终总是传送/急转至最低球并不是那么容易。

  • 您将整个观测空间输入到NEAT(或统一下采样的分数)中,例如整个游戏,无论分辨率如何,最低但仍然明智。我知道这个观察空间很大,但是NEAT在处理这样的空间时效果很好。


我知道这不是您可能希望的NEAT的可变输入大小选项,但是在不显着更改底层NEAT算法的情况下,我不知道任何此类常规选项/技巧

但是,如果有人知道更好的选择,我很高兴得到纠正!