Skip to main content
 首页 » 编程设计

haskell之神经网络总是为任何输入产生相同/相似的输出

2024年10月01日17bhlsheji

我在尝试为 Tic-Tac-Toe 创建神经网络时遇到问题。然而,出于某种原因,训练神经网络会使其对任何给定输入产生几乎相同的输出。

我确实查看了 Artificial neural networks benchmark ,但我的网络实现是为每个神经元具有相同激活函数的神经元构建的,即没有恒定神经元。

为了确保问题不仅仅是由于我选择的训练集(1218 个棋盘状态和由遗传算法生成的移动),我尝试训练网络以重现 XOR。使用了逻辑激活函数。我没有使用导数,而是将误差乘以 output*(1-output),因为一些消息来源表明这等效于使用导数。可以把Haskell源码放在HPaste上,但是看着有点尴尬。网络有3层:第一层有2个输入和4个输出,第二层有4个输入和1个输出,第三层有1个输出。在第二层增加到 4 个神经元没有帮助,在第一层增加到 8 个输出也没有帮助。

然后,我根据 http://hebb.mit.edu/courses/9.641/2002/lectures/lecture04.pdf 手动计算错误、网络输出、偏差更新和权重更新,以确保代码的这些部分没有错误(没有,但我可能会再做一次只是为了确保)。因为我使用的是批量训练,所以我没有在公式(4)中乘以 x。我正在添加重量变化,但 http://www.faqs.org/faqs/ai-faq/neural-nets/part2/section-2.html 建议减去它。

即使在这个简化的网络中,问题仍然存在。例如,这些是批量训练和增量训练 500 个 epoch 后的结果。

Input    |Target|Output (Batch)      |Output(Incremental) 
[1.0,1.0]|[0.0] |[0.5003781562785173]|[0.5009731800870864] 
[1.0,0.0]|[1.0] |[0.5003740346965251]|[0.5006347214672715] 
[0.0,1.0]|[1.0] |[0.5003734471544522]|[0.500589332376345] 
[0.0,0.0]|[0.0] |[0.5003674110937019]|[0.500095157458231] 

减法而不是加法会产生同样的问题,除了一切都是 0.99 而不是 0.50 的东西。 5000 epochs 产生相同的结果,除了批量训练的网络在每种情况下准确返回 0.5。 (哎呀,即使是 10,000 个 epochs 也不适用于批量训练。)

一般有什么可以产生这种行为的吗?

此外,我查看了增量训练的中间误差,尽管隐藏/输入层的输入各不相同,但输出神经元的误差始终为 +/-0.12。对于批量训练,错误在增加,但非常缓慢,而且错误都非常小 (x10^-7)。不同的初始随机权重和偏差也没有区别。

请注意,这是一个学校项目,因此提示/指南会更有帮助。虽然重新发明轮子并建立自己的网络(用我不太了解的语言!)是一个可怕的想法,但我觉得这更适合学校项目(所以我知道发生了什么......理论上,至少。我学校似乎没有计算机科学老师)。

编辑:两层,一个 2 个输入到 8 个输出的输入层,以及一个 8 个输入到 1 个输出的输出层,产生几乎相同的结果:每个训练案例为 0.5+/-0.2(左右)。我也在玩 pyBrain,看看那里是否有任何网络结构可以工作。

编辑 2:我使用的学习率为 0.1。很抱歉忘记了这一点。

编辑 3:Pybrain 的“trainUntilConvergence”也没有给我一个完全训练有素的网络,但是 20000 epochs 可以,隐藏层中有 16 个神经元。 10000 个 epoch 和 4 个神经元,虽然不多,但很接近。所以,在 Haskell 中,输入层有 2 个输入和 2 个输出,隐藏层有 2 个输入和 8 个输出,输出层有 8 个输入和 1 个输出......我在 10000 个时期遇到了同样的问题。并且有 20000 个纪元。

编辑 4:我根据上面的 MIT PDF 再次手动运行网络,并且值匹配,所以代码应该是正确的,除非我误解了这些方程。

我的一些源代码位于 http://hpaste.org/42453/neural_network__not_working ;我正在努力清理我的代码并将其放入 Github(而不是私有(private) Bitbucket)存储库中。

所有相关的源代码现在都在 https://github.com/l33tnerd/hsann

请您参考如下方法:

我遇到过类似的问题,但能够通过改变这些来解决:

  • 将问题缩小到可管理的规模。 我第一次尝试输入太多,隐藏层单元太多。一旦我缩小了问题的规模,我就可以看到较小问题的解决方案是否有效。这也有效,因为当它按比例缩小时,计算权重的时间显着减少,因此我可以尝试许多不同的事情而无需等待。
  • 确保你有足够的隐藏单位。 这对我来说是个大问题。我有大约 900 个输入连接到隐藏层中的约 10 个单元。这太小了,无法快速收敛。但如果我添加额外的单位,也会变得非常慢。减少输入的数量有很大帮助。
  • 改变激活函数及其参数。 我一开始用的是tanh。我尝试了其他函数:sigmoid、normalized sigmoid、Gaussian 等。我还发现改变函数参数使函数更陡或更浅会影响网络收敛的速度。
  • 改变学习算法参数。 尝试不同的学习率(0.01 到 0.9)。如果您的算法支持,也可以尝试不同的动量参数(0.1 到 0.9)。

  • 希望这可以帮助那些在谷歌上找到这个线程的人!