我是机器学习的新手,并且在进入多层网络之前一直在尝试基本的感知器。
我遇到的问题是下面的代码。我有一个训练数据生成器,它使用一组权重来生成真值表。
我遇到的问题是感知器能够在用训练集A' A'生成训练数据时解决/确定权重集。但没有套装' B'。什么时候 给定用set' 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;
}
}
输出样本: