Artificial intelligence 如何识别任意神经网络中的递归连接

Artificial intelligence 如何识别任意神经网络中的递归连接,artificial-intelligence,evolutionary-algorithm,Artificial Intelligence,Evolutionary Algorithm,我试图在C#中实现增广拓扑的神经进化。我遇到了反复连接的问题。我知道,对于循环连接,输出基本上是暂时位移的 在链接的图像中,我展示了一个非常简单的神经网络,有2个输入、3个隐藏节点和一个输出。如果没有激活函数或传递函数,我认为它的计算公式为: n3[t] = (i1[t]*a + n6[t-1]*e)*d + i2[t]*b*c) * f 然而,我很难弄清楚如何识别链接e是一个循环连接的事实。我读到的那篇关于NEAT的论文展示了XOR问题和双极无速度问题的最小解是如何具有循环联系的 如果您有

我试图在C#中实现增广拓扑的神经进化。我遇到了反复连接的问题。我知道,对于循环连接,输出基本上是暂时位移的

在链接的图像中,我展示了一个非常简单的神经网络,有2个输入、3个隐藏节点和一个输出。如果没有激活函数或传递函数,我认为它的计算公式为:

n3[t] = (i1[t]*a + n6[t-1]*e)*d + i2[t]*b*c) * f
然而,我很难弄清楚如何识别链接e是一个循环连接的事实。我读到的那篇关于NEAT的论文展示了XOR问题和双极无速度问题的最小解是如何具有循环联系的

如果您有一个固定的拓扑结构,这看起来相当简单,因为您可以自己分析拓扑结构,并确定需要延迟哪些连接


您将如何准确识别这些连接

我开始写这篇论文时也遇到了类似的问题。我不知道你的人际网络现在是什么样子,所以我会向你解释我做了什么

我的网络一开始只是作为输入和输出层。为了创建连接和神经元,我实施了某种DNA(在我的例子中,这是一系列指令,如“连接神经元编号2和神经元编号5,并将权重设置为0.4”)。我网络中的每个神经元都有一个“layerNumber”,它告诉我神经元在我网络中的位置。为每个输入和输出神经元设置此layerNumber。对于inputneurons,我使用Double.minvalue;对于outputneurons,我使用Double.maxvalue

这是基本设置。从现在起,修改网络时只需遵循以下规则:

  • 无论何时要创建连接,请确保“from”神经元具有layerNumber
  • 无论何时你想要创建一个连接,确保“到”神经元的层号比“从”神经元的层号大

  • 每当一个连接被拆分为两个连接以及它们之间的一个神经元时,将神经元layerNumber设置为NeuronFrom.layerNumber*0.5+NeuronTo.layerNumber*0.5 这一点很重要,不能将它们相加并简单地除以2,因为这可能会导致Double.maxValue+something,这将返回一些奇怪的数字(我猜会发生溢出,所以会得到一个负数?)

如果您遵守所有规则,则应始终仅具有转发连接。没有复发的。如果您想要重复连接,您可以在创建新连接时通过将“from”和“to”交换来创建它们

专业技巧: 只使用一个神经元阵列列表。 让DNA使用神经元的ID来找到它们,但创建一个“连接”类,该类将神经元对象作为属性。 过滤连接/神经元时,请使用ArrayList.stream().filter()

当稍后通过网络传播时,您可以只按layerNumber对神经元进行排序,设置InputValue并使用for()循环遍历所有神经元。只需计算神经元的outputvalue,并将其传递给每个有连接的神经元,其中“from”是==当前神经元


希望不要太复杂…

好吧,我不是告诉你不要有重复性连接,而是告诉你如何识别它们

你需要知道的第一件事是,重复连接是在所有其他连接和神经元之后计算出来的。因此,哪个连接是循环的,哪个不是,取决于NN的计算顺序。 另外,当你第一次把数据放入系统时,我们只会假设每个连接都是零,否则部分或全部神经元就无法计算

假设我们有一个神经网络:

我们将该网络分为3层(尽管在概念上它有4层):

第一条规则:输出层的所有输出都是循环连接

第二条规则:可以首先计算输入层的所有输出

我们创建两个数组。一个包含所有神经元和连接的计算顺序,另一个包含所有(潜在)循环连接。 现在这些阵列看起来有点像这样:

Order of 
calculation: [1->5, 2->7 ]

Recurrent:   [ ]
3, 6, 5, 7
Order of 
calculation: [1->5, 2->7 ]

Recurrent:   [6->7 ]
[1->5, 2->7, 7, 7->4, 7->5, 5, 5->6, 6, 6->3, 3, 4, 6->7]
现在我们从输出层开始。我们能计算神经元3吗?不因为6不见了。我们能计算6吗?不因为5不见了。等等看起来有点像这样:

Order of 
calculation: [1->5, 2->7 ]

Recurrent:   [ ]
3, 6, 5, 7
Order of 
calculation: [1->5, 2->7 ]

Recurrent:   [6->7 ]
[1->5, 2->7, 7, 7->4, 7->5, 5, 5->6, 6, 6->3, 3, 4, 6->7]
问题是我们现在陷入了一个循环。因此,我们引入一个临时数组,存储我们已经访问过的所有神经元id:

[3, 6, 5, 7]
现在我们问:我们能计算7吗?没有,因为少了6个。但是我们已经访问了6个

[3, 6, 5, 7,] <- 6
现在您完成了这个过程,最后将计算数组的顺序与循环数组连接起来,这样循环数组就紧跟在另一个数组之后。 它看起来像这样:

Order of 
calculation: [1->5, 2->7 ]

Recurrent:   [ ]
3, 6, 5, 7
Order of 
calculation: [1->5, 2->7 ]

Recurrent:   [6->7 ]
[1->5, 2->7, 7, 7->4, 7->5, 5, 5->6, 6, 6->3, 3, 4, 6->7]
假设我们有[x->y,y]

其中x->y是x*重量的计算(x->y)

其中,y是(y的输入)总和的计算。所以在这种情况下求和(x->y)或者只求x->y

这里还有一些问题需要解决。例如:如果一个神经元的唯一输入是一个循环连接怎么办?但是我想你可以自己解决这个问题