我不了解NEAT算法如何根据连接基因输入并输出数字,我熟悉在固定拓扑神经网络中使用矩阵来前馈输入,但是NEAT中的每个节点都有自己的数量连接,不一定连接到其他所有节点,我不了解,经过大量搜索,我找不到NEAT如何根据输入产生输出的答案。
有人可以解释它的工作原理吗?
答案 0 :(得分:1)
这也是我在实现自己的算法版本时遇到的问题。
您可以在NEAT用户页面https://www.cs.ucf.edu/~kstanley/neat.html中找到答案,作者说:
如何激活具有任意拓扑的网络?
激活函数bool Network :: activate()提供了详细信息。的 当然,实现方式与简单的分层方式有很大不同 前馈网络。每个节点将所有传入节点的激活加起来 从上一个时间步开始(该功能还可以处理特殊的“时间延迟” 连接,但当前版本的NEAT均未使用 我们已经发表的实验。)了解它的另一种方法是实现 激活不会从输入层一直到输出 一个单一的时间步。在单个时间步中,激活仅从 一个神经元到下一个。因此,激活需要花费几个时间步骤 输入到输出。如果您考虑一下,这就是它在 真正的大脑,信号击中您的眼睛需要时间才能到达 皮层,因为它经过多个神经连接。
因此,如果演进的网络之一不是前馈,则网络的输出将在不同的时间步中变化,这对于连续的控制问题特别有用,在该问题中环境不是静态的,但在分类问题中也是有问题的。作者还回答:
如何在获取网络输出之前确保网络稳定 分类问题?
便宜而肮脏的方法是连续激活n次,其中 n> 1,希望隐藏节点没有太多的循环或漫长的路径。
正确的方法(并且非常不错)是检查每个隐藏的节点并输出 从一个时间步长到下一个时间步长,查看是否没有任何变化,或者至少 在某些三角洲内没有变化。一旦满足此标准,则输出必须为 稳定。
请注意,在某些情况下输出可能并不总是稳定的。另外,连续 控制问题,因为网络永远不会“稳定”,所以不要检查稳定性 而是不断地对不断变化的环境做出反应。通常, 稳定用于分类问题或棋盘游戏。
答案 1 :(得分:0)
当我处理这个问题时,我研究了使用矩阵方法等的环路检测。 https://en.wikipedia.org/wiki/Adjacency_matrix#Matrix_powers
但是我发现馈送输入和获取输出的最佳方法是使用每个节点上的超时传播延迟进行环路检测:
前馈实现很简单,我从这里开始:
等待,直到到节点的所有传入连接都发出信号,然后和压激活并发送到该节点的所有输出连接。从已经具有来自输入矢量信号的输入节点开始。一旦不再有要处理的节点来获取输出矢量,就可以通过求和压榨操作手动“分流”输出节点。
对于圆度(传统的NEAT实施),我与前馈功能相同,但又有一个功能:
计算网络的“ 最大可能环路大小”。一种简单的计算方法是〜2 *(节点总数)。没有输入,从输入到网络中任何节点的步行都不会大于循环,因此,节点必须以这么多的时间步长传播,除非它是循环的一部分。 然后,我等待所有输入连接信号到达节点或发生超时(信号未在最大循环大小步长之内到达连接)。如果发生超时,则将没有信号的输入连接标记为循环。 将连接标记为递归后,请重新启动所有节点上的所有计时器(以防止在检测到的周期中的某个节点由于传播延迟而被标记为递归)
现在正向传播与前馈网络相同,除了:不要等待循环连接,所有非循环连接到达后立即求和(对于没有信号的循环连接为0然而)。这样可以确保将循环中到达的第一个节点设置为循环,从而使其对于任何给定的拓扑都是确定的,并且循环连接将数据传递到下一个传播时间步长。
这有一些第一次的开销,但是很简洁,每次运行给定的拓扑都会产生相同的结果。请注意,这仅在所有节点都有输出路径的情况下有效,因此您不必禁用分离连接(由节点添加操作建立的连接)并在进化过程中不考虑任何因素而随机修剪。
(PS这也创建了一个传统的残差递归网络,理论上可以简单地实现为矩阵运算。如果我有大型网络,我将首先通过运行一次正向传播来“表达”以获得循环连接然后使用循环连接,权重和信号连接属性以及循环连接属性作为稀疏二进制掩码为矩阵乘法操作创建“每层张量”表示形式。 tf.sparse_matrix操作,并且不使用任何树对象,但是我必须使用密集操作,消耗的n ^ 2空间对于我所需的空间来说太大了,但是由于矩阵形式,因此可以使用上述邻接矩阵幂技巧! Github上至少还有其他人做了NEAT,但我不确定它们的实现。我也发现这个有趣的https://neat-python.readthedocs.io/en/latest/neat_overview.html)
快乐黑客!