【问题标题】:Weight Initialisation权重初始化
【发布时间】:2012-11-21 07:16:49
【问题描述】:

我计划将 Nguyen-Widrow 算法用于具有多个隐藏层的 NN。在研究的过程中,我发现了很多含糊不清的地方,我想澄清一下。

以下是 Nguyen-Widrow 算法的伪代码

      Initialize all weight of hidden layers with random values
      For each hidden layer{
          beta = 0.7 * Math.pow(hiddenNeurons, 1.0 / number of inputs);
          For each synapse{
             For each weight{
              Adjust weight by dividing by norm of weight for neuron and * multiplying by beta value
            }
          } 
      }

只是想澄清hiddenNeurons的值是特定隐藏层的大小,还是网络中所有隐藏层的大小。我通过查看各种来源混淆了。

换句话说,如果我有一个网络(3-2-2-2-3)(索引 0 是输入层,索引 4 是输出层),那么 hiddenNeurons 的值会是:

NumberOfNeuronsInLayer(1) + NumberOfNeuronsInLayer(2) + NumberOfNeuronsInLaer(3)

或者只是

NumberOfNeuronsInLayer(i) ,其中 i 是我所在的当前层

编辑:

那么,hiddenNeurons 的值就是当前隐藏层的大小,而输入的值就是前一个隐藏层的大小?

【问题讨论】:

  • 我认为这个等式与每个隐藏层有关,即隐藏神经元的数量是第 i 层中的神经元数量(可以从一个隐藏层到另一个隐藏层不同),输入的数量是相同第 i 层的输入数,即前第 (i-1) 层的神经元数。
  • 我不确定说实话,这么多消息来源说不同的东西,我对算法必须是什么感到困惑。不过感谢您的回复:)
  • 其实在大多数情况下,一个隐藏层就足够了,至少数量较多的网络可以减少到一个隐藏层的类比。这就是为什么该公式通常以隐藏层中的神经元数量和(其)输入来描述的原因。当您添加二维隐藏层时,该公式也递归适用于它,其中输入是前一层的输出。
  • 那么,hiddenNeurons 的值就是当前隐藏层的大小,而输入的值就是前一个隐藏层的大小?顺便谢谢你的回复:)
  • hmm,我仍然不确定,尽管大多数示例只有一个隐藏层,但在计算隐藏层和输出层之间的权重时,使用的输入大小似乎是输入层。

标签: artificial-intelligence neural-network


【解决方案1】:

Nguyen-Widrow 初始化算法如下:

  1. 使用(范围)随机值初始化隐藏层的所有权重
  2. 对于每个隐藏层
    2.1 计算 beta 值,0.7 * Nth(#neurons of input layer) root of #当前层的神经元
    2.2 每个突触
    2.1.1 每个权重
    2.1.2 通过除以神经元和权重的范数来调整权重 乘以 beta 值

Encog Java Framework

【讨论】:

  • 是的,我看过这个伪代码。那么输入层的神经元个数是第一个NN的层,而不是前面的隐藏层?
  • 这是前一层的神经元数(第一个隐藏层的特征数)。
【解决方案2】:

听起来你想要更精确的代码。以下是我参与的项目中的一些实际代码行。希望您阅读 C。它有点抽象和简化。有一个struct nn,它保存着神经网络数据。您可能有自己的抽象数据类型。

我的项目中的代码行(有些简化):

float *w = nn->the_weight_array;
float factor = 0.7f * powf( (float) nn->n_hidden, 1.0f / nn->n_input);

for( w in all weight )
    *w++ = random_range( -factor, factor );

/* Nguyen/Widrow */
w = nn->the_weight_array;
for( i = nn->n_input; i; i-- ){
    _scale_nguyen_widrow( factor, w, nn->n_hidden );
    w += nn->n_hidden;
}

调用的函数:

static void _scale_nguyen_widrow( float factor, float *vec, unsigned int size )
{
    unsigned int i;
    float magnitude = 0.0f;
    for ( i = 0; i < size; i++ )
        magnitude += vec[i] * vec[i];

    magnitude = sqrtf( magnitude );

    for ( i = 0; i < size; i++ )
         vec[i] *= factor / magnitude;
}

static inline float random_range( float min, float max)
{
    float range = fabs(max - min);
    return ((float)rand()/(float)RAND_MAX) * range + min;
}

提示:
在您实现了 Nguyen/Widrow 权重初始化之后,您实际上可以在前向计算中添加一个小代码行,将每个激活转储到一个文件中。然后你可以检查这组神经元对激活函数的影响程度。求均值和标准差。您甚至可以使用绘图工具绘制它,即。 gnuplot。 (无论如何,您都需要一个像 gnuplot 这样的绘图工具来绘制错误率等。)我这样做是为了实现。情节很不错,在我的项目中使用 Nguyen/Widrow 使最初的学习变得更快。

PS:根据 Nguyen 和 Widrows 的意图,我不确定我的实现是否正确。我什至认为我不在乎,只要它确实提高了最初的学习。

祝你好运,
-Øystein

【讨论】:

  • 首先,感谢您的回复。算法走很长的那些线,但如果我正确地阅读了你的代码,你的神经网络只有一个隐藏层。我的问题是如何将此算法用于具有多个隐藏层的神经网络。更具体地说,在获取算法的隐藏层大小时(在这种情况下是您的 nn->n_hidden),该值是否必须是我所在的当前隐藏层的大小(第 i 层)或大小所有隐藏层的组合?我不是在寻找代码,更多的是为了澄清我正确使用了算法。
  • 另外,输入层的神经元个数是NN中第一层的大小,而不是之前的隐藏层?
  • 对,我的神经网络只有一个隐藏层。但是,我会对所有隐藏层做同样的事情。请记住,这首先只是一种经验技术,因此在下一层隐藏节点中使用哪个范围并不重要。我可能会对所有层使用相同的因子。对你来说重要的是实际测试。请按照我在提示部分中描述的操作。将每个级别的激活存储到文件中,并计算均值和标准差。我保证:这将为您的初始化算法提供一些启示!
猜你喜欢
  • 2017-09-15
  • 1970-01-01
  • 2022-11-12
  • 2019-04-14
  • 2018-06-20
  • 2020-01-14
  • 1970-01-01
  • 2017-03-12
  • 2021-05-08
相关资源
最近更新 更多