神经网络的初学者噩梦

时间:2019-06-01 22:06:12

标签: neural-network deep-learning

我一直在阅读Michael Nielsen的《神经网络和深度学习》一书: http://neuralnetworksanddeeplearning.com/ 虽然我很喜欢它,但我仍停留在第2章中,讨论了最简单的问题,找不到解决该问题的方法。

为实现我的目标,在我重写并测试了示例程序以对本书中的手写数字进行分类之后,我想测试一下,如果我的理解是100%正确的,尤其是当我不怎么使用矩阵和numpy之前。 对于尚未阅读过的人,这是一个简单的三层神经网络,布局为784、15、10,其中第一层和最后一层分别是输入和输出,神经元使用Sigmoid激活1.0 /(1.0 + E ^ -z)和使用二次成本函数(|| TY || ^ 2)/ 2的导数的随机梯度下降算法来找到权重和偏差。在Mnist数据集上使用50000个训练样本和10000个测试样本来评估进度。

我决定制作自己的神经网络模拟器来执行相同的工作,并以一种即使具有“聪明才智”的人也能够理解它的方式编写它。我选择了完全面向对象的方法,因为速度并不重要。我的想法如下:

  • 有InputLayer,hiddenLayer和OutputLayer类,每个类都引用网络中的上一个和下一个

  • 有InputNeuron,HiddenNeuron和OutputNeuron类,每个类都引用了网络中的上一层和下一层。

  • 每个层实例均包含相应神经元类型,输入输入,隐藏隐藏等的实例。

  • 隐藏和输出神经元类型具有偏差,权重,z(激活和权重的加权总和),增量,weightsTrainingBuffer,biasTrainingBuffer和trainingBufferCount。 weightsTrainingBuffer和biasTrainingBuffer是权重和bias的类型对应项-双数组和双变量。执行反向传播时,将计算每个人的梯度并将其添加到相应位置-wTB数组中的第零权重梯度到第零位,到bTB的偏差梯度等。对神经元执行反向传播时,trainingBufferCount会增加。

  • 它们也具有Flush方法。调用它时,每个训练缓冲区值都除以trainingBufferCount(数量,增加了多少次),计算平均梯度,乘以学习率,然后从权重和偏差中减去。这是一种执行迷你批处理的方法,例如,您只需执行10次反向传播,然后调用flush即可在网络上进行更改。 weightsTrainingBuffer,biasTrainingBuffer和trainingBufferCount当然在刷新后会重置。

  • UpdateTrainingBuffer方法,对于隐藏和输出神经元,计算权重和偏差梯度是相同的。使用的公式是偏差的delta和delta * previousLayer [i]。第i个权重的输出。两者的上述冲洗方法也相同。

  • 隐藏神经元和输出神经元之间的唯一区别在于它们如何计算增量。

  • 输出神经元使用公式delta = Costprime(currentOutput,targetOutput) SigmoidPrime(z),其中CostPrime是currentOutput-targetOutput和SigmoidPrime Sigmoid(z)(1-Sigmoid(z))

  • 第i层中的隐藏神经元使用以下算法计算其增量:

    1. 变量preDelta = 0.0
    2. 在下一层迭代神经元,将每个神经元的权重乘以其增量,并将其添加到preDelta中。
    3. 将当前神经元增量计算为preDelta * SigmoidPrime(z)
  • 神经网络首先将所有权重和偏差都设置为零,以实现可追踪的结果,我也禁用了训练数据混排。

  • 培训具有参数trainingData,learningRate,Epochs数量,minibatchSize,testData。它遍历训练样本,前馈每个人以在网络中设置zs和输出,然后应用反向传播,如果这样做是在miniBatchSize时间内完成的,则也会调用flush。在检查完所有样本后,进行评估以进行测试。

当我阅读示例程序时,所有这些似乎对我来说都是正确的。只有一个问题,它不会求人!!! 该示例程序以相同的参数开始-零网络,无乱序和批处理大小10,第一次迭代后,学习率3达到10000中的6120,而我的程序只有3400左右,并且似乎并没有急剧上升。 有趣的是,如果仅使用两层网络-784、10,则两个程序的结果都非常相似-在10000中大约有8300。 因此,我认为隐藏层中的某个地方存在问题,但是经过数周以及非常密集的测试和调试之后,我仍然不知道在哪里。 如果我上面列出的想法是正确的,您可以验证一下吗?实现应该是正确的,我检查了大约一百万次,并用其他编程语言进行了一次完整的重写,所以现在我拥有具有相同行为的C#和C ++版本。对我来说唯一有意义的是,这个问题是我的理解,但是即使使用示例程序,我也无法分辨出哪里。

我的源代码在这里,如果有帮助的话: http://leteckaposta.co/file/807055742.1/b4314835b49e269dfae1f30ba2ba7b442a516a6f/cs 我没有提供训练数据和测试数据,它们大约有400 mb,但是如果需要,我可以添加它们。

在此先感谢您的帮助,这开始让我发疯,比平常更疯狂。

0 个答案:

没有答案