用于简单神经网络的反向传播会产生异常结果

时间:2016-07-29 08:23:04

标签: machine-learning neural-network backpropagation

几天前,我尝试将我今年在人工智能讲座中学到的关于神经网络的知识付诸实践。我试图做一个简单的,只有2个神经元,它会复制它的输入信号。通过我的计算,这里有一个关于网络的小图:http://imgur.com/a/RixAH(对不起法语评论,他们并不重要)

奇怪的是它确实会收敛,但是对于一个简单的二进制输入信号,当信号为0时,网络有效地发送〜0,但是当它为1时,它发送〜0.5,我不会#39;了解原因。另外,我必须将学习率设置得相当高(~100)以使其正常工作,我再也不知道为什么。

这是我用来测试网络的java代码:

public class Main
{
    final static double R = 100;

public static void main(String[] args)
{
    double w1 = Math.random(), w2 = Math.random();

    for (int iter = 1; iter <= 100; iter++)
    {
        int x;

        if (Math.random() >= 0.5)
        {
            x = 1;
        }
        else
        {
            x = 0;
        }

        double p1 = x * w1;
        double y = 1 / (1 + Math.exp(-p1));

        double p2 = y * w2;
        double z = 1 / (1 + Math.exp(-p2));

        double P = -0.5 * Math.pow(x - z, 2);

        double dP1 = (x - z) * z * (1 - z) * w2 * y * (1 - y) * x;
        double dP2 = (x - z) * z * (1 - z) * y;

        w1 += R * dP1;
        w2 += R * dP2;

        System.out.println("x = " + x + ", z = " + z + ", P = " + P);
    }
}

}

你知道问题可能来自哪里吗?

感谢。

LeChocdesGitans

编辑:

我终于设法让它工作了(我按照你的网络配置建议)。我想还有一个实现错误,因为它在我改变网络布局后没有直接工作,但是我重新开始了它,现在我可以做很有趣的东西,比如字符识别,它可以工作很好,与我的应用程序的基本程度相比。

再次感谢您的建议!

1 个答案:

答案 0 :(得分:1)

正如 rpd 所说,你的主要问题是你正在训练两个连续的层。在数学上,这意味着应用于节点1的所有校正都必须通过节点2进行过滤。是的,您可以应用链规则,贝叶斯定理或其他等效过滤,但这总是存在实现错误的风险。 / p>

根据您描述的效果,您几乎肯定会在实施中出错。最大的线索是,您必须将学习率提高到任何合理的值以上,以获得甚至可接受的结果。请记住,这是识别小步骤的缩放因子。值100表示​​您正在对正确调整进行最佳当前估计,然后达到100倍。如果算法的其余部分是正确的,那么学习率超过1.0就是故意在没有收敛的情况下疯狂振荡。

如果您已跟踪中间值,请发布更新顺序;如果没有,那么你应该使用那个调试步骤。

但是,你应该首先将隐藏的神经元并联,而不是串联。首先,功能的卷积只是浪费了一些步骤。另一方面,权重应该通过相同的过程(并行)更新。结果应该收敛于易于归一化为1.0的不同权重(例如,通过SoftMax操作)。单层反向传播是一种低阶计算:在您尝试使用您设置的立方(和更差)误差函数进行更快收敛之前,使用简单的线性过程(Euler方法)调试过程。

我稍微处理了你的笔记和算法,并得到了一些观察结果。

  • 您在笔记的第一行中删除了一个负号:如果P(x,z)= -1/2(x-z)^ 2,则导数为 - (x-z)或z-x。在算法中进行此更改有助于收敛。

  • 串联神经元的卷积通常是有缺陷的;这可以简单地减少到具有单个隐藏神经元的模型。