我计划对一个具有多个隐藏层的神经网络使用Nguyen-Widrow算法。在研究过程中,我发现了许多模糊之处,希望能澄清这些问题。
以下是Nguyen-Widrow算法的伪代码
用随机值初始化所有隐藏层的权重 对于每个隐藏层{ beta = 0.7 * Math.pow(hiddenNeurons, 1.0 / 输入数量); 对于每个突触{ 对于每个权重{ 通过将权重除以该神经元的权重范数并乘以beta值来调整权重 } } }
我想澄清的是,hiddenNeurons的值是特定隐藏层的大小,还是网络中所有隐藏层的大小?我因为查阅了各种来源而感到困惑。
换句话说,如果我有一个网络(3-2-2-2-3)(索引0是输入层,索引4是输出层),hiddenNeurons的值应该是:
NumberOfNeuronsInLayer(1) + NumberOfNeuronsInLayer(2) + NumberOfNeuronsInLaer(3)
还是只是
NumberOfNeuronsInLayer(i) ,其中i是我当前所在的层
编辑:
那么,hiddenNeurons的值应该是当前隐藏层的大小,而输入值应该是前一个隐藏层的大小?
回答:
听起来你想要更精确的代码。以下是我参与的一个项目中的一些实际代码行。希望你能阅读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后,我的项目初始学习速度大大提高了。
附言:我不确定我的实现是否符合Nguyen和Widrow的意图。我甚至不关心,只要它能提高初始学习速度就行。
祝你好运,
-Øystein