【问题标题】:How to give an AI controls in a video game?如何在电子游戏中赋予 AI 控制权?
【发布时间】:2020-04-18 20:50:04
【问题描述】:

所以我使用 PyGame 制作了 Pong,我想使用遗传算法让 AI 学会玩游戏。我希望它只知道它的桨、球和控件的位置。我只是不知道如何让 AI 自己移动桨。我不想这样做:“如果球在你上方,就上去。”我希望它只是尝试随机的东西,直到它学会做什么。

所以我的问题是,我如何让 AI 尝试控制并查看什么有效?

【问题讨论】:

    标签: python machine-learning pygame artificial-intelligence genetic-algorithm


    【解决方案1】:

    一个可能有帮助的设计考虑是您是否可以通过另一个界面提供一些最小的显示细节集;并且相反地允许对玩家桨的命令。例如,您可以通过 socket 向另一个进程发送一个描述球位置的简单结构,并且每帧更新的球拍和球都输出。按照相同的模式,您可以创建一个结构,作为对该消息的回复发送,该消息描述了如何移动玩家桨。例如:

    # Pong Game program
    import socket
    import struct
    
    # Set up server or client socket
    
    # ... Into game loop
    state = (p1_paddle_y, p2_paddle_y, ball_x, ball_y, victory_state)
    # assuming pixel locations, and victory_state is -1:Loss, 0:InProgress, 1:Win
    
    myGameStateMsg = struct.pack('>LLLLh', state[0], state[1], state[2], state[3])
    sock.send(myGameStateMsg) # Sending game state to player
    
    playerMsg = sock.recv(4) # Get player command
    playerCmd = struct.unpack('i', playerMsg) 
    # playerCmd is an integer describing direction & speed of paddle motion
    
    # ... Process game state update, repeat loop
    

    您可以使用 线程 和事务结构来实现相同的效果,但您需要考虑正确保护这些结构(读写问题等)

    出于稳定性原因,我个人更喜欢第一种方法(套接字和多处理)。假设有某种错误导致崩溃;如果您已经进行了进程分离,则更容易识别崩溃的根源。在线程级别,它仍然是可能的,但更具挑战性。多处理方法的其他好处之一是您可以轻松设置多个玩家并让游戏扩展(1vInGameAI、1v1、3v3、4v4)。尤其是当你扩展时,你可以测试不同的算法,比如 Q-Learning、自适应动态规划等,让它们互相玩!

    附录:套接字 101

    Sockets 是一种让多个进程(即正在运行的程序)相互发送消息的机制。这些进程可以在同一台机器上或跨网络运行。从某种意义上说,使用它们就像读取和写入一个不断修改的文件(这是套接字提供的抽象),而且还提供了阻塞调用,以便让进程等待信息可用.

    关于可以轻松填满多个页面的套接字(如文件套接字与网络套接字(FD 与 IP);UDP 与 TCP 等),可以讨论更多细节。相反,请参阅以下有关基本设置的教程:https://docs.python.org/3/howto/sockets.html。有了这些,您将基本了解他们可以提供什么以及与他们一起去哪里获得更先进的技术。

    您可能还想参考 struct 教程以及介绍性消息打包:https://docs.python.org/3/library/struct.html。有更好的方法可以做到这一点,但是如果不了解结构,您将不会了解它们的工作原理和分解方式。

    【讨论】:

    • 您可以在不运行多个进程或线程的情况下进行面向消息的分离。
    • 正确,如果设计满足函数式编程约束和/或在帧更新之间注入训练和控制。但是,保持处理分离允许使用满足 OP 强加的接口的其他系统([原文如此] Pong 的其他实现)对学习者进行培训和锻炼。这种接口和处理的分离可以允许学习架构独立性(可能是分布式的)。这种设计模式广泛用于 AI 竞赛、研究和行业。
    • 原谅我,你说的我什么都听不懂(有点高级)。我想知道您是否可以为我简化它。
    • 我已经参考初学者教程编辑了我的答案,并简要说明了如何制定游戏状态和玩家动作。请注意,@LieRyan 所说的也是正确的,但我发现它在面对实验时用处不大。
    【解决方案2】:

    因此,您希望 AI 输入桨的位置和球的位置。 AI 输出是两个布尔输出,AI 在下一个模拟步骤中是否应该按下向上或向下按钮。

    我还建议添加另一个输入值,即球的速度。否则,您可能需要添加另一个输入,即上一个模拟步骤中球的位置,以及一个更复杂的中间层,以便 AI 学习速度的概念。

    【讨论】:

    • 我将如何创建二进制输出?我正在想一些公式,但找不到相关性。
    • @JacobSage 对不起,我的意思是布尔输出,而不是二进制。基本上,人工神经网络的输出将是一个浮点值,例如在 0 和 1 之间,您希望将该值映射到具有激活阈值的布尔值(例如,输出大于 0.8 表示按下了相应的按钮)。
    【解决方案3】:

    学习 Atari-Pong 已经成为强化学习的标准任务。例如,OpenAI baselines github repo 实现了可以插入各种任务的 RL 算法。

    您绝对不需要那些高级算法来按照您描述的方式学习 Pong,但是您可以从他们用来区分任务(强化学习术语中的“环境”)和 AI 部分( “控制器”或“代理”)。为此,我建议阅读OpenAI Gymn Documentation,了解如何添加新环境。

    简而言之,您可以使用一些浮点数(球的位置和速度,或者两个位置而不是速度,以及桨的位置)。或者你可以使用离散输入(整数,或者只是像素,更难学习)。这些输入可以连接到一个小型神经网络。

    对于命令输出,最简单的方法是预测向上或向下移动的概率。这是一个好主意,因为当您评估您的控制器时,它会有一些非零得分的机会,因此您的遗传算法可以将不同的控制器(具有不同的权重)相互比较。只需在神经网络输出上使用 sigmoid 函数,并将其解释为概率。

    如果您将所有神经网络权重初始化为一个良好的随机范围,那么您可能只需通过足够长的时间尝试随机权重(即使没有 GA),就可以获得一个不会完全糟糕的乒乓球运动员。

    PS:如果您不打算使用神经网络:如果您只需要实现前向传递,那么从头开始实现它们真的很简单。例如。如果您不实施反向传播训练,而是使用 GA 来学习权重(或 evolution strategy,或只是随机权重)。最难的部分是为初始随机权重找到一个好的范围。

    【讨论】:

    • 我目前的问题是找到一个使用权重的函数。我以前从未做过遗传算法,所以我基本上是从零开始。
    • 这是 numpy 中 simple neural network 的示例。只需在末尾添加一个 sigmoid。
    猜你喜欢
    • 2015-10-06
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多