繁体   English   中英

有人可以告诉我此反向传播实现的问题是什么

[英]Can someone tell me what is wrong with this back propagation implementation

所以我正在尝试在C#中实现反向传播神经网络。 而且我遇到了打ic。 训练网络时,所有输出均为0.49 ??? ...或0.51 ??? ......

这是我的网络课

namespace BackPropNetwork
{
public class Network 
{
    public double[][] Values { get; set; }
    public double[][] Deltas { get; set; }
    public double[][][] Weights { get; set; }
    public Network(params int[] size)
    {
        Values = new double[size.Length][];
        Weights = new double[size.Length][][];
        Deltas = new double[size.Length][];
        Random r = new Random();
        for(int i = 0; i < size.Length; i++)
        {
            Values[i] = new double[size[i]];
            Weights[i] = new double[size[i]][];
            Deltas[i] = new double[size[i]];
            if (i != size.Length - 1) {
                for (int j = 0; j < size[i]; j++)
                {
                    Weights[i][j] = new double[size[i + 1]];
                    for(int k= 0; k < size[i + 1]; k++)
                    {
                        Weights[i][j][k] = r.NextDouble() ;
                    }
                }
            }
        }
    }
    public double[] FeedThrough (double[] input)
    {
        if(input.Length!= Values[0].Length)
        {
            throw new InvalidOperationException();
        }
        Values[0] = input;
        for(int i = 0; i < Values.Length-1; i++)
        {
            for(int j = 0; j < Values[i + 1].Length; j++)
            {
                Values[i + 1][j] = Sigmoid(GetPassValue(i, j),false);
            }
        }
        return Values[Values.Length - 1];
    }
    double GetPassValue(int layer,int neuron)
    {
        double sum = 0;
        for(int i = 0; i < Values[layer].Length; i++)
        {
            sum += Values[layer][i] * Weights[layer][i][neuron];
        }
        return sum;
    }
    public double Sigmoid(double d, bool dir)
    {
        if (dir)
        {
            return d * (1 - d);
        }else
        {
            return 1 / (1 + Math.Exp(d));
        }
    }
    public void CorrectError(double[] error)
    {
        for(int i = Values.Length - 1; i >= 0; i--)
        {

            if (i !=Values.Length - 1)
            {
                error = new double[Values[i].Length];
                for(int j = 0; j < Values[i].Length; j++)
                {
                    error[j] = 0;
                    for(int k = 0; k < Values[i + 1].Length; k++)
                    {
                        error[j] += Weights[i][j][k] * Deltas[i + 1][k];
                    }
                }    
            }

            for(int j = 0; j < Values[i].Length; j++)
            {
                Deltas[i][j] = error[j] * Sigmoid(Values[i][j],true);
            }

        }

    }
    public void ApplyCorrection(double rate)
    {
        for(int i = 0; i < Values.Length-1; i++)
        {
            for(int j = 0; j < Values[i].Length; j++)
            {
                for(int k = 0; k < Values[i + 1].Length; k++)
                {
                    Weights[i][j][k] = rate * Deltas[i + 1][k] * Values[i][j];
                }
            }
        }
    }
}

}

这是我的测试人员课程:

namespace BackPropagationTest
{
class Program
{
    static void Main(string[] args)
    {
        Network n = new Network(3, 5, 5, 1);
        double[][] input = new double[][] { new double[] { 1, 0, 1 }, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 }, new double[] {0, 1, 0 } };
        double[][] output = new double[][] { new double[] { 0 },new double[] { 1 }, new double[] { 0 }, new double[] { 0 } };
        for (int i = 0; i < 10; i++)
        {
            for(int j = 0; j < input.Length; j++)
            {
                var x = n.FeedThrough(input[j]);
                double[] error = new double[output[0].Length];
                for(int k= 0; k < x.Length; k++)
                {
                    error[k] = output[j][k] - x[k];
                }
                n.CorrectError(error);
                n.ApplyCorrection(0.01);
                for(int k = 0; k < x.Length; k++)
                {
                     Console.Write($"Expected: {output[j][k]} Got: {x[k]} ");
                }
                Console.WriteLine();


            }
            Console.WriteLine();

        }
    }
}

}

这是我的输出:

Expected: 0 Got: 0.270673949003643
Expected: 1 Got: 0.500116517554687
Expected: 0 Got: 0.499609458404919
Expected: 0 Got: 0.50039031963377

Expected: 0 Got: 0.500390929619276
Expected: 1 Got: 0.500390929999612
Expected: 0 Got: 0.499609680732027
Expected: 0 Got: 0.500390319841144

Expected: 0 Got: 0.50039092961941
Expected: 1 Got: 0.500390929999612
Expected: 0 Got: 0.499609680732027
Expected: 0 Got: 0.500390319841144

Expected: 0 Got: 0.50039092961941
Expected: 1 Got: 0.500390929999612
Expected: 0 Got: 0.499609680732027
Expected: 0 Got: 0.500390319841144

它永远这样下去。

编辑1:

我在替换的ApplyCorrection()函数中进行了更改

 Weights[i][j][k] = rate * Deltas[i + 1][k] * Values[i][j];

与`

 Weights[i][j][k] += rate * Deltas[i + 1][k] * Values[i][j];

现在权重似乎在更新。 但是我仍然对这种实现的正确性表示怀疑。 阿卡仍然需要帮助:)

编辑2:

我不是对输出层的总误差求和,而是对每个样本误差分别进行反向传播。 现在是,但是输出非常令人困惑:

而且我还尝试将输出对从(0,1)更改为(-1,1),以使计算出的误差值更大。 这是在1000000个历元之后以0.1的学习速率进行的:

Expected: -1 Got: 0.999998429209274 Expected: 1 Got: 0.999997843901661 Expected: -1 Got: 0.687098308461306 Expected: -1 Got: 0.788960893508226 Expected: -1 Got: 0.999998429209274 Expected: -1 Got: 0.863022549216158 Expected: -1 Got: 0.788960893508226 Expected: -1 Got: 0.999998474717769

尝试使用类似下面的方法,并检查错误是否正在减少或仍然相同。

public double Sigmoid(double d, bool dir)
{
    if (dir)
    {
        return d * (1 - d);
    }else
    {
        if (d < -45.0) return 0.0;
        else if (d > 45.0) return 1.0;
        else return 1.0 / (1.0 + Math.Exp(-d));
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM