【问题标题】:How to Identify Recurrent Connections in an Arbitrary Neural Network如何识别任意神经网络中的循环连接
【发布时间】:2017-07-23 20:15:46
【问题描述】:

我正在尝试在 C# 中实现增强拓扑的神经进化。我遇到了经常性连接的问题。我知道,对于循环连接,输出基本上是暂时的。

http://i.imgur.com/FQYjCLZ.png

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

n3[t] = (i1[t]*a + n6[t-1]*e)*d + i2[t]*b*c) * f

但是,我很难弄清楚如何识别链接 e 是循环连接这一事实。我读到的关于 NEAT 的论文展示了 XOR 问题和双极无速度问题的最小解如何都有循环连接。

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

您将如何准确识别这些联系?

【问题讨论】:

    标签: artificial-intelligence evolutionary-algorithm


    【解决方案1】:

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

    我的网络开始时仅作为输入和输出层。为了创建连接和神经元,我实现了某种 DNA(在我的情况下,这是一组指令,例如“将神经元 nr.2 与神经元 nr.5 连接并将权重设置为 0.4”)。我网络中的每个神经元都有一个“layerNumber”,它告诉我神经元在我的网络中的位置。这个 layerNumber 是为每个输入和输出神经元设置的。对于输入神经元,我使用 Double.minvalue,对于输出神经元,我使用 Double.maxvalue。

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

    • 无论何时你想创建一个连接,确保'from'神经元有一个 layerNumber

    • 每当您想创建连接时,请确保“to”神经元的 layerNumber 大于“from”神经元。

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

    如果您遵守所有规则,您应该始终只有转发连接。没有复发的。如果您想要循环连接,您可以通过在创建新连接时交换 'from' 和 'to' 来创建它们。

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

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

    希望不要太复杂...

    【讨论】:

      【解决方案2】:

      好吧,与其告诉你不要有经常性连接,我实际上会告诉你如何识别它们。

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

      假设我们有这个神经网络: Neural Network

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

      Input Layer  [1, 2]
      Hidden Layer [5, 6, 7]
      Output Layer [3, 4]
      

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

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

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

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

      现在我们从查看输出层开始。我们可以计算神经元 3 吗?不?因为 6 不见了。我们能算出6吗?不?因为 5 不见了。等等。它看起来有点像这样:

      3, 6, 5, 7
      

      问题是我们现在陷入了一个循环。所以我们引入了一个临时数组来存储我们已经访问过的所有神经元 ID:

      [3, 6, 5, 7]
      

      现在我们问:我们能算出 7 吗?不,因为缺少 6。但是我们已经访问了 6...

      [3, 6, 5, 7,] <- 6
      

      第三条规则是:当你访问一个之前已经访问过的神经元时,将你所遵循的与这个神经元的连接设置为循环连接。 现在你的数组看起来像这样:

      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*weight(x->y)的计算

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-19
        • 2018-09-23
        • 1970-01-01
        • 2017-01-30
        • 1970-01-01
        • 2023-03-14
        • 2018-10-05
        • 2012-03-04
        相关资源
        最近更新 更多