我正在尝试实现我自己的多层感知器,不幸的是我犯了一些我找不到的错误。链接到完整程序就在这里(它很简单,简单的c#控制台应用程序)。我正在学习this book,我正在尝试从批处理到顺序表单重写的代码位于this github。
链接到我的项目is here(github)。 感知器本身is here。
我的测试输入是Xor功能,功能,功能和一些随机功能,噪音很小。
我的问题是:
1)
在我使用无穷大检查覆盖所有代码(用于双溢出)之前,我的所有结果(和权重)非常快(100多次迭代)收敛到某些超高值,结果变为NaN
。添加支票后,我得到了double.MaxValue
。有趣的是,如果我运行相同的程序约5次,我将得到正确的结果(取决于迭代次数)。唯一的随机变量是使用随机数初始化的权重(范围-1/sqrt(n) < x < 1/sqrt(n)
,其中n
是隐藏层中的神经元数)。可能是什么原因造成的?
2) 我正在训练和验证相同的数据集(因为它现在无关紧要),并且因为它是顺序算法,所以我在我的课堂内改变训练输入和目标。
public void Train(int iterations, double eta)
{
_lastHiddenUpdates = new double[_hiddenWeights.RowLength(), _hiddenWeights.ColumnLength() + 1];
_lastOutputUpdates = new double[_outputWeights.Length];
for (int i = 0; i < iterations; i++)
{
ShuffleRows(); // <---- ShuffleRows is a private method without any ref parameter!
this._currentIteration = i;
var result = ForwardPhase(_trainingInput);
BackwardsPhase(result.OutputResult, result.HiddenValues, eta);
}
}
这是在MultiLayerPerceptron
课程内。问题是,在训练之后,原始数组double[]
也被洗牌了!双精度数组是结构,结构是按值传递的,而不是通过引用传递的,原始数组是program.cs
。为什么它在范围之外改变了?我错过了什么吗?现在我只是克隆目标数组。
第3)
这太丑了
var infinity = deltasHs[i, j];
if (double.IsNegativeInfinity(infinity))
{
deltasHs[i, j] = double.MinValue;
}
else if (double.IsPositiveInfinity(infinity))
{
deltasHs[i, j] = double.MaxValue;
}
我怎么能这么简单?
注意:在编写这个程序时,我没有注意性能,有时我会循环多次通过一个数组只是为了将可读性保持在合理的水平。 我也知道你不应该在相同的数据集上训练和验证,但这不是我的目标,如果我的感知器也会学习噪音,我将非常高兴。我只想让这只愚蠢的鹅工作(并理解)。