Artificial intelligence 用神经网络连接4:草稿的评估+;进一步步骤
我想建立一个连接4引擎,使用人工神经网络-只是因为我对人工神经网络着迷 我将创建以下ANN结构草案。这样行吗?这些连接正确吗(即使是交叉连接) 你能帮我起草一个这个ANN的UML类图吗 我想将板表示作为ANN的输入。输出应该是选择的移动 以后应使用进行学习,并应用。引擎将与人类玩家比赛。然后根据比赛结果调整重量 我在找什么…Artificial intelligence 用神经网络连接4:草稿的评估+;进一步步骤,artificial-intelligence,neural-network,game-ai,Artificial Intelligence,Neural Network,Game Ai,我想建立一个连接4引擎,使用人工神经网络-只是因为我对人工神经网络着迷 我将创建以下ANN结构草案。这样行吗?这些连接正确吗(即使是交叉连接) 你能帮我起草一个这个ANN的UML类图吗 我想将板表示作为ANN的输入。输出应该是选择的移动 以后应使用进行学习,并应用。引擎将与人类玩家比赛。然后根据比赛结果调整重量 我在找什么… 。。。主要是编码问题。从抽象思维到编码的过程越多越好。实现神经网络有很多不同的方法,从简单/易于理解到高度优化。您链接到的具有指向、、等中的实现的链接,如果您有兴趣了解其
。。。主要是编码问题。从抽象思维到编码的过程越多越好。实现神经网络有很多不同的方法,从简单/易于理解到高度优化。您链接到的具有指向、、等中的实现的链接,如果您有兴趣了解其他人是如何实现的,可以作为很好的参考 一个简单的体系结构将节点和连接建模为单独的实体;节点可能具有到其他节点的传入和传出连接以及激活级别和错误值,而连接具有权重值 或者,还有更有效的方法来表示这些节点和连接——例如,作为按层组织的浮点值数组。这使得编写代码有点困难,但避免了创建太多对象和指向对象的指针
一个注意事项:除了正常的输入节点外,人们通常还包括为每个隐藏和输出节点提供常量值的节点。我以前已经实现了神经网络,并且看到了您提出的架构中的一些问题:
最后一个建议是使用双极输入(-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();
}
}
我建议从反向传播开始作为您的学习算法,因为它被认为是最容易实现的。当我