我是一个机器学习的新手,在转向多层网络之前,我一直在尝试使用基本的感知器进行实验。
我的问题出在下面的代码中。我有一个训练数据生成器,它使用一组权重来生成真值表。
我的问题是,当训练数据使用’A’组权重生成时,感知器能够解决/确定这组权重,但使用’B’组权重生成时却不能。当给定使用’B’组权重生成的训练数据时,它会持续陷入无限循环,试图确定权重(这是局部最小值问题吗?)
我不完全明白为什么会发生这种情况。任何帮助或建议都将不胜感激。
提前感谢。
// 调用函数 public static void TestPerceptron () { // 问题: // 当使用'A'组权重生成训练数据时,感知器能够根据给定的训练数据确定正确的权重。 // 当使用'B'组权重生成训练数据时,感知器永远无法完成训练,并陷入无限循环 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]; // 获取目标 var target = inputs [inputs.Length - 1]; // 计算输出 var computed = ComputeOutput (weights, inputs, bias); // 通过激活函数传递计算结果 var output = PerceptronHelper.Activation (computed); // 确定误差 var error = (target - output); // 调整权重 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{ // 根据给定的权重生成训练数据 - 输入的数量 = 权重的数量 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; // 生成训练数据 for (var index = 0; index < numInputCombinations; index++) { var sum = 0.0; // 数组的最后一个项目是预期输出 var trainDataLine = new double[weights.Length+1]; var binary = Convert.ToString (inputValue, 2); binary = binary.PadLeft (weights.Length, '0'); // 创建训练数据行 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); // 将预期结果存储在数组的最后一个项目中 trainDataLine [weights.Length] = output; // 将行添加到数据中 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; }}
输出示例:
回答:
将学习率改为0.075解决了这个问题。