【问题标题】:XOR neural network error keeps converging to 0.5XOR 神经网络误差不断收敛到 0.5
【发布时间】:2021-01-19 18:50:50
【问题描述】:

我刚开始尝试通过复制一个我发现的用 python 编写的简单神经网络,在 c# 中创建自己的神经网络,输出始终以 0.5 结束。我查看了在 Google 上发布的关于同一问题的所有其他问题,但没有一个解决方案适用。我不知道为什么会这样。这是我的代码现在的样子:

public class NeuralNetwork
        {
            private double[,] w;

            public NeuralNetwork()
            {
                w = random(2, 1);
            }

            public double[,] getWeights()
            {
                return w;
            }

            public void train(double[,] x, double[,] y, int iterations)
            {
                for (int i = 0; i < iterations; i++)
                {
                    double[,] output = think(x);
                    double[,] error = Mat.subtract(Mat.transpose(y), output);
                    double[,] adjust = dot(Mat.transpose(x), Mat.multiply(error, doSigDeriv(output)));

                    w = Mat.add(w, adjust);
                }
            }

            public double[,] think(double[,] inputs)
            {
                return doSig(dot(inputs, w));
            }

            private double[,] dot(double[,] a, double[,] b)
            {
                double[,] dot = new double[a.GetLength(0), b.GetLength(1)];

                for (int i = 0; i < a.GetLength(0); i++)
                {
                    for (int j = 0; j < b.GetLength(1); j++)
                    {
                        for (int k = 0; k < b.GetLength(0); k++)
                            dot[i, j] += a[i, k] * b[k, j];
                    }
                }
                return dot;
            }

            private double[,] random(int w, int h)
            {
                double[,] a = new double[w, h];
                for (int i = 0; i < w; i++)
                {
                    for (int j = 0; j < h; j++)
                    {
                        a[i, j] = 2 * (double)rand.NextDouble() - 1;
                    }
                }
                return a;
            }

            private double[,] doSig(double[,] a)
            {
                double[,] b = new double[a.GetLength(0), a.GetLength(1)];
                for (int i = 0; i < a.GetLength(0); i++)
                {
                    for (int j = 0; j < a.GetLength(1); j++)
                    {
                        b[i, j] = sig(a[i, j]);
                    }
                }
                return b;
            }

            private double[,] doSigDeriv(double[,] a)
            {
                double[,] b = new double[a.GetLength(0), a.GetLength(1)];
                for (int i = 0; i < a.GetLength(0); i++)
                {
                    for (int j = 0; j < a.GetLength(1); j++)
                    {
                        b[i, j] = a[i, j] * (1 - a[i, j]);
                    }
                }
                return b;
                //return Mat.multiply(a, Mat.subtract(one(a), a));
            }

            private double sig(double x)
            {
               return 1 / (double)(1 + Math.Exp(-x));
            }
        }

x 是我用于输入的数组和 y 用于输出的数组,而 Mat 只是我用来处理矩阵运算的一个类。当我测试它时,我将迭代次数更改为 10000 和 50000 并得到相同的结果。非常感谢任何见解,谢谢。

编辑:我刚刚意识到,当它应该是 0 时,它是 -0.5 而 1 是 0.5。

【问题讨论】:

  • 我认为大多数进入 NN 的人不再从头开始编写代码,我曾经这样做过,但我不再这样做了,你最好花时间在 pytorch / tensorflow 上。在那里你使用管道。输入层隐藏层,输出层学习 RELU 等。(如果你想深入研究,我认为那是更好的时间)
  • 啊,好吧,我明白了,所以您认为即使是初学者也更值得与之合作和学习?
  • 特别是作为初学者,让神经网络做一些实际有趣的事情会更有意义它是免费的。

标签: c# machine-learning neural-network


【解决方案1】:

当然 user219279 的评论是正确的:NN 现在更好地在 GPU/Tensor 中运行,当您要扩展网络时,这要快得多。但是,对于 XOR 反向传播和研究,您不需要性能。

0.5 的输出值很常见,称为“局部最小值”。当您的网络训练由于某种原因无法收敛时,就会发生这种情况。权重达到巨大的 +/- 值,而不是具有小值和 0/1 输出的平衡。

我在上面看到的错误:没有足够的权重。您将权重分配为 2x1 数组,连接输入输出。你不能训练一个只有 2 个权重的 XOR 结果网络。您至少需要 5 个砝码。有关合适的 XOR 架构的更多信息,请参阅http://mnemstudio.org/neural-networks-multilayer-perceptrons.htm

【讨论】:

  • 我一定会这样做的!只需阅读链接,它非常有用。我可以将新的权重添加到已经存在的矩阵中,还是需要第二个矩阵来添加额外的权重?谢谢!
  • 没关系,这次我重写了中间部分并使用了 6 个权重,过了一会儿它现在可以正常工作了。再次感谢!
  • 你放入的神经元越多,你的训练就会越灵活,因为权重的值很低。网络还是可以学习的。在每个神经元的入口处都有一个在 0 附近陡峭的 S 函数:权重在该范围内学习,不超过 ca -3 或 3。如果您有太多这样的权重,网络就会饱和。试试这个:以某种配置设置网络,训练它..然后更改训练。查看交换网络需要多少个周期。重新训练永远不应该得到 0.5 个结果,或者花费太长时间......然后你使用的神经元不够,或者训练不一致。
猜你喜欢
  • 2018-11-04
  • 1970-01-01
  • 2016-05-13
  • 2020-03-28
  • 2018-01-31
  • 1970-01-01
  • 2016-07-10
  • 2017-07-13
相关资源
最近更新 更多