Artificial intelligence 用神经网络连接4:草稿的评估+;进一步步骤

Artificial intelligence 用神经网络连接4:草稿的评估+;进一步步骤,artificial-intelligence,neural-network,game-ai,Artificial Intelligence,Neural Network,Game Ai,我想建立一个连接4引擎,使用人工神经网络-只是因为我对人工神经网络着迷 我将创建以下ANN结构草案。这样行吗?这些连接正确吗(即使是交叉连接) 你能帮我起草一个这个ANN的UML类图吗 我想将板表示作为ANN的输入。输出应该是选择的移动 以后应使用进行学习,并应用。引擎将与人类玩家比赛。然后根据比赛结果调整重量 我在找什么… 。。。主要是编码问题。从抽象思维到编码的过程越多越好。实现神经网络有很多不同的方法,从简单/易于理解到高度优化。您链接到的具有指向、、等中的实现的链接,如果您有兴趣了解其

我想建立一个连接4引擎,使用人工神经网络-只是因为我对人工神经网络着迷

我将创建以下ANN结构草案。这样行吗?这些连接正确吗(即使是交叉连接)

你能帮我起草一个这个ANN的UML类图吗

我想将板表示作为ANN的输入。输出应该是选择的移动

以后应使用进行学习,并应用。引擎将与人类玩家比赛。然后根据比赛结果调整重量

我在找什么…


。。。主要是编码问题。从抽象思维到编码的过程越多越好。

实现神经网络有很多不同的方法,从简单/易于理解到高度优化。您链接到的具有指向、、等中的实现的链接,如果您有兴趣了解其他人是如何实现的,可以作为很好的参考

一个简单的体系结构将节点和连接建模为单独的实体;节点可能具有到其他节点的传入和传出连接以及激活级别和错误值,而连接具有权重值

或者,还有更有效的方法来表示这些节点和连接——例如,作为按层组织的浮点值数组。这使得编写代码有点困难,但避免了创建太多对象和指向对象的指针


一个注意事项:除了正常的输入节点外,人们通常还包括为每个隐藏和输出节点提供常量值的节点。

我以前已经实现了神经网络,并且看到了您提出的架构中的一些问题:

  • 典型的多层网络具有从每个输入节点到每个隐藏节点的连接,以及从每个隐藏节点到每个输出节点的连接。这允许来自所有输入的信息被组合,并对每个输出作出贡献。如果为每个输入指定4个隐藏节点,则将失去网络识别输入和输出之间关系的部分能力

  • 您将如何提出培训网络的价值观?你的人际网络在董事会位置和最佳下一步行动之间建立了映射,因此你需要一组提供这一点的培训示例。游戏结束时的移动很容易识别,但是你如何判断游戏中间的移动是“最佳的”?(强化学习在这里有帮助)


  • 最后一个建议是使用双极输入(-1表示错误,+1表示正确),因为这可以加快学习速度。Nate Kohl提出了一个很好的观点:每个隐藏和输出节点都将受益于偏置连接(将其视为另一个固定值为“1”的输入节点)。

    您的设计将高度依赖于您计划使用的特定类型的强化学习

    最简单的解决方案是使用反向传播。这是通过将误差反馈回网络(以反向方式)并使用(sigmoid)函数的逆函数来确定每个权重的调整来实现的。经过多次迭代后,权重将自动调整以适应输入

    遗传算法是反向传播的一种替代方法,它可以产生更好的结果(尽管有点慢)。这是通过将权重视为可以轻松插入和删除的模式来实现的。该模式被一个变异版本(使用自然选择原理)替换了好几次,直到找到合适的模式为止


    正如您所看到的,每种方法的实现都会有很大的不同。您可以尝试使网络具有足够的通用性,以适应每种类型的实现,但这可能会使其过于复杂。一旦投入生产,通常只有一种形式的培训(或者理想情况下,您的网络已经得到培训)。

    下面是我在处理神经网络时如何组织设计和代码的。这里的代码(显然)是伪代码,大致遵循面向对象的约定

    从下到上,你将拥有你的神经元。每个神经元都需要能够保持它对传入连接施加的权重,一个用来保存传入连接数据的缓冲区,以及它的传出边列表。每个神经元需要能够做三件事:

    • 从传入边缘接受数据的一种方法
    • 一种处理输入数据和权重的方法,以确定该神经元将发送的值
    • 一种将神经元的值发送到输出边缘的方法
    就代码而言,这可以转化为:

    // Each neuron needs to keep track of this data
    float in_data[]; // Values sent to this neuron
    float weights[]; // The weights on each edge
    float value; // The value this neuron will be sending out
    Neuron out_edges[]; // Each Neuron that this neuron should send data to
    
    // Each neuron should expose this functionality
    void accept_data( float data ) {
        in_data.append(data); // Add the data to the incoming data buffer
    }
    void process() {
        value = /* result of combining weights and incoming data here */;
    }
    void send_value() {
        foreach ( neuron in out_edges ) {
            neuron.accept_data( value );
        }
    }
    
    //Each layer needs to keep track of this data.
    Neuron[] neurons;
    
    //Each layer should expose this functionality.
    void fire() {
        foreach ( neuron in neurons ) {
            float value = neuron.process();
            neuron.send_value( value );
        }
    }
    Neuron[] get_neurons() {
        return neurons;
    }
    
    接下来,我发现制作一个包含神经元列表的Layer类是最简单的。(很有可能跳过这个类,让你的神经网络保存一个神经元列表。我发现有一个层类在组织上和调试上都更容易。)每个层都应该公开以下功能:

    • 使每个神经元“燃烧”
    • 返回该层环绕的原始神经元阵列。(当您需要在神经网络的第一层手动填充输入数据时,这非常有用。)
    就代码而言,这可以转化为:

    // Each neuron needs to keep track of this data
    float in_data[]; // Values sent to this neuron
    float weights[]; // The weights on each edge
    float value; // The value this neuron will be sending out
    Neuron out_edges[]; // Each Neuron that this neuron should send data to
    
    // Each neuron should expose this functionality
    void accept_data( float data ) {
        in_data.append(data); // Add the data to the incoming data buffer
    }
    void process() {
        value = /* result of combining weights and incoming data here */;
    }
    void send_value() {
        foreach ( neuron in out_edges ) {
            neuron.accept_data( value );
        }
    }
    
    //Each layer needs to keep track of this data.
    Neuron[] neurons;
    
    //Each layer should expose this functionality.
    void fire() {
        foreach ( neuron in neurons ) {
            float value = neuron.process();
            neuron.send_value( value );
        }
    }
    Neuron[] get_neurons() {
        return neurons;
    }
    
    最后,您有一个NeuralNetwork类,它包含一个层列表、一种使用初始数据设置第一层的方法、一种学习算法以及一种运行整个神经网络的方法。在我的实现中,我通过添加第四层来收集最终的输出数据,该层由一个伪神经元组成,该神经元简单地缓冲所有传入数据并返回该数据

    // Each neural network needs to keep track of this data.
    Layer[] layers;
    
    // Each neural network should expose this functionality
    void initialize( float[] input_data ) {
        foreach ( neuron in layers[0].get_neurons() ) {
            // do setup work here
        }
    }
    void learn() {
        foreach ( layer in layers ) {
            foreach ( neuron in layer ) {
                /* compare the neuron's computer value to the value it
                 * should have generated and adjust the weights accordingly
                 */
            }
        }
    }
    void run() {
        foreach (layer in layers) {
            layer.fire();
        }
    }
    
    我建议从反向传播开始作为您的学习算法,因为它被认为是最容易实现的。当我