故障感知器

Malfunctioning perceptron

我是机器学习的新手,在转向多层网络之前一直在尝试基本的感知器。

我遇到的问题是下面的代码。我有一个训练数据生成器,它使用一组权重来生成一个真值 table。

我遇到的问题是,当训练数据是使用集 'A' 而不是集 'B' 生成时,感知器能够 solve/determine 权重集。什么时候 给定用集合 'B' 生成的训练数据,它会无限继续 循环尝试确定权重(这是局部最小值问题吗?)

我不明白为什么会这样。任何帮助或建议是 赞赏。

提前致谢。

// Calling function 
public static void TestPerceptron ()
    {
        // Problem: 
        // When training data is generated using the 'A' set of weights, the perceptron is able to determine the correct weights based on the given training data.
        // When training data is generated using the 'B' set of weights, the perceptron never completes training and is stuck in an infinite loop

        double[] weights = new double[] {
            //3,2,2,3 // A
            3,2,1,3,1 // B
        };

        double bias = 0.0; 

        var trainingData = PerceptronHelper.GenerateDataSetUsingWeights (weights, bias);
        var perceptron = new Perceptron ();
        perceptron.Train (trainingData, null, null);

        //perceptron.Train (trainingData, weights, bias); 
    }


public class Perceptron
{
    private static Random r = new Random ();
    protected double _bias = r.NextDouble();
    protected double[] _weights;

    protected virtual double ComputeOutput(double[] weights, double[] inputs, double bias)
    {
        var total = 0.0;

        for (var index = 0; index < inputs.Length-1; index++) 
        {
            total += weights [index] * inputs [index];
        }

        return total + (1 * bias);
    }

    protected virtual void SetWeights(ref double[] weights, double[] inputs, double error, double learningRate, ref double bias)
    {
        for (var index = 0; index < inputs.Length-1; index++) 
        {
            weights[index] = weights [index] + (learningRate * error * inputs [index]);
        }

        bias += learningRate * error * 1;
    }

    public virtual void Train(double[][] trainingData, double[] idealWeights, double? idealBias)
    {
        var learningRate = 1.0;
        var totalError = 1.0;
        var targetError = 0.0;
        var epochs = 0.0;
        var bias = _bias;
        var weights = new double[trainingData[0].Length-1];

        if (idealBias.HasValue)
            bias = idealBias.Value;

        if (idealWeights != null)
            weights = idealWeights;

        while (totalError > targetError) 
        {
            totalError = 0.0;

            for (var index = 0; index < trainingData.Length; index++) 
            {
                var inputs = trainingData [index];

                // get target
                var target = inputs [inputs.Length - 1];

                // compute output
                var computed = ComputeOutput (weights, inputs, bias);

                // pass computed through activation
                var output = PerceptronHelper.Activation (computed);

                // determine error 
                var error = (target - output);

                // adjust weights
                SetWeights (ref weights, inputs, error, learningRate, ref bias);

                totalError += Math.Abs(error);

                var weightsMsg = "Weights: ";

                foreach(var weight in weights)
                {
                    weightsMsg += weight + "|";
                }

                Console.WriteLine (String.Format ("error: {0} weights: {1} bias: {2}", totalError, weightsMsg, bias));
            }

            epochs++;
        }

        _bias = bias;
        _weights = weights;
    }

    public void Predict(double[] inputs)
    {
        var sum = 0.0;

        for (var index = 0; index < inputs.Length; index++) 
        {
            sum += inputs [index] * _weights [index] + 1 * _bias;

            Console.WriteLine (String.Format("input: {0} weight: {1} bias: {2}", inputs[index], _weights[index], _bias));
        }

        var output = PerceptronHelper.Activation (sum);
        Console.WriteLine ("Output:{0}", output);
    }
}


public static class PerceptronHelper
{
    // generate training data based on given weights - the number of inputs = number of weights 
    public static double[][] GenerateDataSetUsingWeights(double[] idealWeights, double bias)
    {
        var weights = idealWeights;
        var inputs = new double[weights.Length];
        var numInputCombinations = Math.Pow(2,inputs.Length); 
        var trainData = new double[(int)numInputCombinations][];
        int inputValue = 0;

        // generate training data
        for (var index = 0; index < numInputCombinations; index++) 
        {
            var sum = 0.0;  

            // last item in array is expected output
            var trainDataLine = new double[weights.Length+1];

            var binary = Convert.ToString (inputValue, 2);
            binary = binary.PadLeft (weights.Length, '0');

            // create training data line
            for (var wIndex = 0; wIndex < weights.Length; wIndex++) 
            {
                inputs [wIndex] = double.Parse(binary[wIndex].ToString());
                trainDataLine [wIndex] = inputs [wIndex];
                sum += inputs [wIndex] * weights [wIndex];
            }

            sum += (1 * bias);

            var output = Activation (sum);

            // store the expected result in the last item of the array
            trainDataLine [weights.Length] = output;

            // add the line to the data
            trainData[index] = trainDataLine;

            inputValue++;
        }

        return trainData;
    }

    public static double Activation (double sum) 
    {
        Console.WriteLine (String.Format("evaluating :{0}", sum));
        return Math.Abs(sum) >= 5 ? 1 : 0;

    }
}

输出示例:

https://onedrive.live.com/redir?resid=8a0ad995f81066db!176&authkey=!AGgY8Iy4g_8lpv4&ithint=file%2crtf

将学习率更改为 0.075 解决了这个问题。