okej, antar att jag inte kommer kunna få så jättemycket hjälp här, men någon kanske kan något. Metoden ska träna ett neuronnät i luffarschack genom backpropagation. Ett TrainingSet, som är en publik inre klass i NeuralNetwork tas emot och innehåller de exempel med målresultat som ska tränas.
Nätet består av 9 neuroner i varje lager, och alla lager ligger i hiddenLayer, det första och sista är input- respektive outputlayer, och det finns om jag minns rätt m st dolda lager, som bestäms av användaren i GUI.
Problemet är att inlärningen helt enkelt inte fungerar. Ska debugga lite för att komma på mer specifikt.
Jag är också osäker på hur errorn ska beräknas, och hur denna ska utnyttjas för att fixa vikterna.
Har framförallt utgått från http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.htmlför att förstå backpropagation, så algoritmen är väl egengjord på ett sätt kan man säga.
public void trainNeuralNetwork(TrainingSet trainingSet, double learningFactor, double maxError, double maxIterations, String playerColor, Form form, TextBox textOut)
{
double error = 0;
int iteration = 0, n;
double currentActivationValue;
double[] nextLayersActivationWeights;
do
{
trainingSet.reset();
currentActivationValue = 0.0;
n = 0;
error = 0;
while (trainingSet.hasMoreSets())
{
string[][] example = trainingSet.getNextSet();
n = 0;
// forward propogate /* activate neurons in inputLayer from input */
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
//activate alla neuroner i inputLayer
if (example[/**/i][j].Equals(playerColor))// om playerColor är X är act(X)=-1, act(O)=1, act( )=0
currentActivationValue = 1;
else if (example[/**/i][j].Equals(comColor))
currentActivationValue = 2;
else currentActivationValue = 0;
inputLayer.ElementAt(n).activate(currentActivationValue);
n++;
}
}
/* go through all layers, updating each neuron's inputSum from the previous layer's neurons */
// för varje lager i nätet frånomed det andra
for (int i = 1; i < layers.Count(); i++)
{ // för varje neuron j inom lagret innan...
for (int j = 0; j < this.neurons; j++)
{ // om den är aktiv...
if (layers.ElementAt(i - 1).ElementAt(j).isActive())
{ // hämta aktiveringsvikterna...
currentActivationValue = layers.ElementAt(i - 1).ElementAt(j).getSum();
nextLayersActivationWeights = layers.ElementAt(i - 1).ElementAt(j).getWeights(false); //false gör att inputSum inte nollställs
for (int k = 0; k < this.neurons; k++)
{ // och aktivera dessa med föregående lagers vikter
layers.ElementAt(i).ElementAt(k).activate(nextLayersActivationWeights.ElementAt(k) * currentActivationValue);
}
}
}
}
//backward propogate
/* compare outputLayer with target output */
// kolla output layer efter aktiverade neuroner, jämför med target i error
double[] targetResults = trainingSet.getCurrentTargetResults();
//n = 0;
for (int i = 0; i < this.neurons; i++)
{
/*for (int j = 0; j < this.n; j++)
{/**/
outputLayer.ElementAt(i).errorSignal(
targetResults.ElementAt(i) - outputLayer.ElementAt(i).getSum());
//}
}
/* from right to left, add up all error sums */
for (int i = layers.Count() - 2; i >= 0; i--) // -2 för att vi börjar på näst sista lagret
{ // i varje lager fram till inputlayer
for (int j = 0; j < this.neurons; j++)
{ // för varje neuron i lagret till höger om detta (lager i+1, neuron j)
for (int k = 0; k < this.neurons; k++)
{ // i varje neuron i detta lager (lager i, neuron k)
layers.ElementAt(i).ElementAt(k).errorSignal(
layers.ElementAt(i+1).ElementAt(j).getErrorSum(layers.ElementAt(i).ElementAt(k).getWeight(j)), //errorsumman i lagret till högers j:te neuron
layers.ElementAt(i).ElementAt(k).getWeight(j)); //denna neurons (lager i neuron k) vikt till neuron j för lagret till höger
}
}
}
/* correct the weights of each neuron */
for (int i = 0; i < layers.Count()-1; i++) // skippa att rätta vikterna för outputLayer
{ // för varje lager fr vänster till höger
for (int j = 0; j < this.neurons; j++)
{ // för varje neuron j inom lager i,
for(int k = 0; k < this.neurons; k++) { // fixa vikterna för neuron k i lager i+1
layers.ElementAt(i).ElementAt(j).correctWeight(k, layers.ElementAt(i + 1).ElementAt(k).getErrorSum(layers.ElementAt(i).ElementAt(j).getWeight(k)), learningFactor);
}
}
}
// beräkna total error
/*for (int i = 0; i < hiddenLayer.Count() - 1; i++)
{*/
for (int j = 0; j < this.neurons; j++)
{//summera errorn i outputLayer
error += outputLayer.ElementAt(j).getErrorSum(1.0);
}
//}
error /= this.neurons; // dela på antalet neuroner i outputLayer för att få ett medelvärde.
error /= trainingSet.Count();
deactivateAll();
}
if (textOut != null)
textOut.Text = "Iteration " + iteration.ToString() + ", error " + error.ToString() + ", where MaxError is " + maxError.ToString();
form.Update();
form.Refresh();
} while (Math.Abs(error) > maxError && iteration++ < maxIterations);
}
tack för any hjälp at all
Okej, problemet är definitivt i den här metoden, efter två iterationer av trainingSet blir vikterna oändligt små. Vad kan det vara för fel? är framförallt dessa rader som borde påverka:
variabel:
layers.ElementAt(i).ElementAt(k).activate(nextLayersActivationWeights.ElementAt(k) * currentActivationValue);
variabel:
outputLayer.ElementAt(i).errorSignal(
targetResults.ElementAt(i) - outputLayer.ElementAt(i).getSum());
variabel:
layers.ElementAt(i).ElementAt(k).errorSignal(
layers.ElementAt(i+1).ElementAt(j).getErrorSum(layers.ElementAt(i).ElementAt(k).getWeight(j)), //errorsumman i lagret till högers j:te neuron
variabel:
layers.ElementAt(i).ElementAt(j).correctWeight(k, layers.ElementAt(i + 1).ElementAt(k).getErrorSum(layers.ElementAt(i).ElementAt(j).getWeight(k)), learningFactor);
Tråden låst på grund av inaktivitet