C# 用c语言逼近线性函数的前馈-反向传播网络

C# 用c语言逼近线性函数的前馈-反向传播网络,c#,function,neural-network,backpropagation,C#,Function,Neural Network,Backpropagation,我正在研究前馈-反向传播网络并使用Accord.c中的神经库我使用了ResilientBackpropagationLearning类来管理动量本身 此时,我的问题是理解如何近似函数,尤其是那些输入变量的线性组合,因此是最简单的函数。 学习是有监督的,一个例子是:3个变量->y-x1,x2,x3=2*x1+x2+5*x3 我开始研究单个变量的函数,然后是2个变量,然后是3个变量,我得到了令人满意的结果。 我设法扩大了网络规模,并取得了良好的效果 --案例3输入: 3输入 1个隐藏层,其中有15节

我正在研究前馈-反向传播网络并使用Accord.c中的神经库我使用了ResilientBackpropagationLearning类来管理动量本身

此时,我的问题是理解如何近似函数,尤其是那些输入变量的线性组合,因此是最简单的函数。 学习是有监督的,一个例子是:3个变量->y-x1,x2,x3=2*x1+x2+5*x3

我开始研究单个变量的函数,然后是2个变量,然后是3个变量,我得到了令人满意的结果。 我设法扩大了网络规模,并取得了良好的效果

--案例3输入:

3输入 1个隐藏层,其中有15节 1输出 在输入变量范围内随机生成的100个示例的训练集。 训练1000个时代,但也不多。 我可以得到小于0.001的网络误差和1-2%的验证集平均百分比误差

--现在用4个输入试试

4输入 1个隐藏层,其中有25节 1输出 在输入变量范围内随机生成的500个示例的训练集 5000个时代的培训 我可以得到小于2.5的网络错误和25-30%的验证集平均百分比错误

我尝试了这么多的配置,结果都很差。即使将示例数增加到5000个,将纪元数增加到100000个,将隐藏节点数增加到50个,验证集的平均错误百分比也会提高,但仅提高到20-25%

为什么我变得这么穷

这是我的程序的基本代码:

这是我的简单程序:

using Accord.Neuro;
using Accord.Neuro.Learning;
using System;

namespace ConsoleApp4_1
{
    class Program
    {
        struct struttura
        {
            public double INPUT1, INPUT2, INPUT3, INPUT4, OUTPUT1;
        }

        static void Main(string[] args)
        {
            bool needToStop = false;
            Random rr = new Random((int)DateTime.Now.Millisecond);

            int NE = 40, epoche = 50000, p;
            double ERRORE = 0.00001d;

            struttura[] EE = new struttura[NE];
            double error = 1; 
            double[][] input = new double[NE][];
            double[][] output = new double[NE][];
            for (int u = 0; u < NE; u++) input[u] = new double[4];
            for (int u = 0; u < NE; u++) output[u] = new double[1];


            for (p = 0; p < NE; p++)
            {
                EE[p].INPUT1 = rr.Next(1, 200);
                EE[p].INPUT2 = rr.Next(1, 100);
                EE[p].INPUT3 = rr.Next(1, 50);
                EE[p].INPUT4 = rr.Next(1, 150);

                EE[p].OUTPUT1 = 0.1d * EE[p].INPUT2 + (2.0d / 3) * EE[p].INPUT1 + (7.0d / 10) * EE[p].INPUT3 + (2.0d / 3) * EE[p].INPUT4;    //  278.3333333   
            }
            for (p = 0; p < NE; p++)
            {
                for (int u = 0; u < NE; u++) input[u][0] = EE[u].INPUT1 / 200;
                for (int u = 0; u < NE; u++) input[u][1] = EE[u].INPUT2 / 100;
                for (int u = 0; u < NE; u++) input[u][2] = EE[u].INPUT3 / 50;
                for (int u = 0; u < NE; u++) input[u][3] = EE[u].INPUT3 / 150;

                for (int u = 0; u < NE; u++) output[u][0] = EE[u].OUTPUT1 / 278.3333333;
            }

            // create neural network
            ActivationNetwork network = new ActivationNetwork(new SigmoidFunction(), 4, 8, 1);

            // create teacher
            var teacher = new ResilientBackpropagationLearning(network);   

            int i = 0;
            // loop
            while (!needToStop)
            {
                i++;
                // run epoch of learning procedure
                error = teacher.RunEpoch(input, output);
                // check error value to see if we need to stop
                if ((error < ERRORE) | (i == epoche)) needToStop = true;
                Console.WriteLine(i + "  " + error);
            }

            Console.WriteLine("Esempi per epoca: "+NE+"     epoca: " + i + "     error: " + error + "\n\n"); // bastano 408 epoche con NE = 40

            double[] test1 = new double[] { 30.0d / 200, 80.0d / 100, 23.0d / 50, 100.0d/150};
            double[] ris1 = network.Compute(test1);
            double[] ris1Atteso1 = new double[] { 110.7666667d };
            Console.WriteLine("a: " + (ris1[0] * 278.3333333d).ToString("") + "   " + ris1Atteso1[0]);

            double[] test2 = new double[] { 150.0d / 200, 40.0d / 100, 3.0d / 50, 40.0d/150};
            double[] ris2 = network.Compute(test2);
            double[] ris1Atteso2 = new double[] { 132.7666667d };
            Console.WriteLine("\na: " + (ris2[0] * 278.3333333d).ToString("") + "   " + ris1Atteso2[0]);

            double[] test3 = new double[] { 15.0d / 200, 30.0d / 100, 45.0d / 50, 146.0d/150};
            double[] ris3 = network.Compute(test3);
            double[] ris1Atteso3 = new double[] { 141,8333333d };
            Console.WriteLine("\na: " + (ris3[0] * 278.3333333d).ToString("") + "   " + ris1Atteso3[0]);

            double[] test4 = new double[] { 3.0d / 200, 60.0d / 100, 12.0d / 50, 70.0d/150};
            double[] ris4 = network.Compute(test4);
            double[] ris1Atteso4 = new double[] {63.0666667d};
            Console.WriteLine("\na: " + (ris4[0] * 278.3333333d).ToString("") + "   " + ris1Atteso4[0]);

            double[] test5 = new double[] { 50.0d / 200, 2.0d / 100, 44.0d / 50, 15.0d/150};
            double[] ris5 = network.Compute(test5);
            double[] ris1Atteso5 = new double[] { 74,333333d };
            Console.WriteLine("\na: " + (ris5[0] * 278.3333333d).ToString("") + "   " + ris1Atteso5[0]);

            double[] test6 = new double[] { 180.0d / 200, 95.0d / 100, 25.0d / 50, 70.0d/150 };
            double[] ris6 = network.Compute(test6);
            double[] ris1Atteso6 = new double[] { 193.6666667 };
            Console.WriteLine("\na: " + (ris6[0] * 278.3333333d).ToString("") + "   " + ris1Atteso6[0]);

            double[] test7 = new double[] { 22.0d / 200, 12.0d / 100, 2.0d / 50, 10.0d/150 };
            double[] ris7 = network.Compute(test7);
            double[] ris1Atteso7 = new double[] { 23.9333333d };
            Console.WriteLine("\na: " + (ris7[0] * 278.3333333d).ToString("") + "   " + ris1Atteso7[0]);

            double[] test8 = new double[] { 35.0d / 200, 5.0d / 100, 40.0d / 50, 120.0d/150 };
            double[] ris8 = network.Compute(test8);
            double[] ris1Atteso8 = new double[] { 131.8333333d };
            Console.WriteLine("\na: " + (ris8[0] * 278.3333333d).ToString("") + "   " + ris1Atteso8[0]);

            double[] test9 = new double[] { 115.0d / 200, 70.0d / 100, 50.0d / 50, 88.0d/150};
            double[] ris9 = network.Compute(test9);
            double[] ris1Atteso9 = new double[] { 177.3333333d };
            Console.WriteLine("\na: " + (ris9[0] * 278.3333333d).ToString("") + "   " + ris1Atteso9[0]);

            double[] test10 = new double[] { 18.0d / 200, 88.0d / 100, 1.0d / 50, 72.0d/150 };
            double[] ris10 = network.Compute(test10);
            double[] ris1Atteso10 = new double[] { 69.5d };
            Console.WriteLine("\na: " + (ris10[0] * 278.3333333d).ToString("") + "   " + ris1Atteso10[0]);

            double sum = Math.Abs(ris1[0] * 278.3333333d - ris1Atteso1[0])+ Math.Abs(ris2[0] * 278.3333333d - ris1Atteso2[0]) + Math.Abs(ris3[0] * 278.3333333d - ris1Atteso3[0]) + Math.Abs(ris4[0] * 278.3333333d - ris1Atteso4[0]) + Math.Abs(ris5[0] * 278.3333333d - ris1Atteso5[0]) 
                + Math.Abs(ris6[0] * 278.3333333d - ris1Atteso6[0]) + Math.Abs(ris7[0] * 278.3333333d - ris1Atteso7[0]) + Math.Abs(ris8[0] * 278.3333333d - ris1Atteso8[0]) + Math.Abs(ris9[0] * 278.3333333d - ris1Atteso9[0]) + Math.Abs(ris10[0] * 278.3333333d - ris1Atteso10[0]);

            double erroreMedio = sum / 10;

            double sumMedie = Math.Abs((ris1[0] * 278.3333d - ris1Atteso1[0]) / (ris1Atteso1[0]))
            + Math.Abs((ris2[0] * 278.3333d - ris1Atteso2[0]) / (ris1Atteso2[0]))
            + Math.Abs((ris3[0] * 278.3333d - ris1Atteso3[0]) / (ris1Atteso3[0]))
            + Math.Abs((ris4[0] * 278.3333d - ris1Atteso4[0]) / (ris1Atteso4[0]))
            + Math.Abs((ris5[0] * 278.3333d - ris1Atteso5[0]) / (ris1Atteso5[0]))
            + Math.Abs((ris6[0] * 278.3333d - ris1Atteso6[0]) / (ris1Atteso6[0]))
            + Math.Abs((ris7[0] * 278.3333d - ris1Atteso7[0]) / (ris1Atteso7[0]))
            + Math.Abs((ris8[0] * 278.3333d - ris1Atteso8[0]) / (ris1Atteso8[0]))
            + Math.Abs((ris9[0] * 278.3333d - ris1Atteso9[0]) / (ris1Atteso9[0]))
            + Math.Abs((ris10[0] * 278.3333d - ris1Atteso10[0]) / (ris1Atteso10[0]));

        Console.WriteLine("\nErrore medio su 10 : "+ erroreMedio);

        Console.WriteLine("\nErrore % medio : " + (sumMedie/10)*100);
            Console.ReadLine();
        }


    }





}

虽然我不熟悉雅阁。 您可能会遇到一个典型的问题,这个问题可能发生在维数错误的网络上。 神经网络在训练集上表现得非常好,但在实际集上却不是

我想你应该试着用更少的隐藏神经元。 由于您的网络学习了大量的训练集,因此无法处理不同的数据。因为最好是85%的分数进行训练,79%的分数进行验证。与99%的培训和65%的验证相比。请注意,这两个网络的百分比总数是相同的85+79=99+65,但第一个网络在解决未知问题时会更好;这是总的目标

你现在拥有的东西被称为过度适合。 最常见的原因是,网络开始表现得更像内存,它会记住treshold,而它应该更多地是关于未知验证集中的决策。我希望这能有所帮助

还要注意的是,由于隐藏的神经元较少,在火车上也可能达不到接近100%的效果,但最终解决不了这个问题,记住这一点


也不确定你想用它解决什么问题,但要确保你的数据集有正确的神经网络,为了简单的测试乐趣,尝试使用爱尔兰花卉数据集。我的人际网络在“训练+验证”组合中的得分可达199.16%左右。你可以试着克服这一点,如果是的话,请告诉我一个最新情况:

正如你所建议的,我尝试过使用较少的神经元,并且使用不同数量的训练集元素和年代。我找不到任何改进。我不知道你是如何制作培训集和验证集的。但我很好奇,你有没有试着交换它们。ea您的培训集是否可代表您的验证集?。或者他们之间有很大的区别?。也许可以将这两个数据集结合起来,使用随机生成器随机划分为训练集和验证集。如果这没有帮助,请确保验证没有问题。不要将测试输入与验证输出进行比较。应该是验证输入与验证输出。我犯了一个愚蠢的错误,int u=0;u