Я новичок в обучении машинам и экспериментирую с основными персептронами, прежде чем переходить к многослойным сетям.Неисправный персептрон
Проблема у меня есть с кодом ниже. У меня есть генератор данных обучения, который использует набор весов для генерации таблицы истинности.
Проблема заключается в том, что персептрон способен решать/определять набор весов, когда данные обучения были сгенерированы с помощью набора «А», но не с установкой «В». Когда дается подготовка данных, который был сгенерирован с набором «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;
}
}
Образец продукции:
Можете ли вы отлаживать и проверять, что именно происходит с весами в B. Какое значение имеет (оно близко к правильному значению) и почему условие остановки никогда не срабатывает? – slabofguinness
Спасибо за ваш ответ, я обновил сообщение с образцом вывода. Глядя на результат, проблема представляет собой общую ошибку, которая вызывает бесконечный цикл. – noobie