/// <summary> /// Uczy sieć za pomocą propagacji wstecznej /// </summary> public void learnNetwork(int iterations, double learningConstant) { if (examples.Count == 0) { throw new ExampleListException("Liczba przykładów musi być większa od zera"); } Random r = new Random(); double eta = learningConstant; //double mi = 0.1; foreach (UniqueLayer l in layers) { foreach (Perceptron p in l.Perceptrons) { p.Weights.round(); } } // Oblicza wartości u dla każdego perceptronu // Przykład wartości ui: /// <code> /// classificationExamples[0].Example /// </code> Vector output; double lastError = globalError(); //const double c = 1.05; int interval = iterations / 10000; for (int z = 0; z < iterations / 10000; z++) { for (int i = 0; i < 10000; i++) { // Inicjalizacja testowego wektora delt delty = new List<Vector>(layers.Count); // Obecnie rozważany przykład LearningExample ex = examples[r.Next(examples.Count)]; classify(ex); // Trzeba utworzyc wektory pamiętające wartości delta Vector delta = new Vector(classificationExamples.Last().Example.Dimension); Vector newDelta; // Zmienne pomocnicze Vector lastExapmle = classificationExamples.Last().Example; Vector expected = classificationExamples[0].ExpectedValue; // Utworzenie wartości delta dla warstwy ostatniej for (int j = 1; j < lastExapmle.Dimension; j++) { //if (i > 10000) //{ // mes("Błąd wynosi " + (lastExapmle[j] - expected[j]) // + "\nPochodna wynosi " + lastExapmle[j] * (1 - lastExapmle[j])); //} delta[j] = (lastExapmle[j] - expected[j]) * // Błąd lastExapmle[j] * (1 - lastExapmle[j]); // Pochodna //Console.WriteLine("(" + expected[j].ToString() + " - " + lastExapmle[j] + ")" // + " * " + (lastExapmle[j] * (1 - lastExapmle[j])) + " = " + delta[j]); } //delta.round(); // Obliczenie wartości delta dla warstw niższych // oraz odpowiednich wag delty.Add(delta); for (int j = layers.Count - 2; j >= 0; j--) { output = classificationExamples[j].Example; //output.round(); newDelta = new Vector(output.Dimension); newDelta.zeros(); for (int k = 1; k < classificationExamples[j + 1].Example.Dimension; k++) { // Perceptron zwracający ui Perceptron p = layers[j + 1].Perceptrons[k - 1]; for (int l = 1; l <= layers[j].Perceptrons.Count; l++) { newDelta[l] += delta[k] * p.Weights[l] * output[l] * (1 - output[l]); // Pochodna } } //newDelta.round(); // Przyjmujemy nowy wektor delta delta = newDelta; delty.Insert(0, delta); } #if DEBUG string str = ""; #endif for (int j = -1; j < layers.Count - 1; j++) { if (j >= 0) { output = classificationExamples[j].Example; } else { output = ex.Example; } for (int k = 0; k < layers[j + 1].OutputDimension - 1; k++) { Perceptron p = layers[j + 1].Perceptrons[k]; #if DEBUG Vector tmp = new Vector(p.Dimension); #endif for (int l = 0; l < output.Dimension; l++) { //if (i > 10000) //{ // mes("u: " + output[l].ToString() + ", u': " + (output[l] * (1 - output[l])).ToString() // + ", d: " + delty[j + 1][k + 1].ToString()); //} p.Weights[l] -= eta * delty[j + 1][k + 1] * output[l]; //* (1 - mi) //+ mi * (p.Weights[l] - p.LastWeights[l]); //p.LastWeights[l] = p.Weights[l]; // Dla testowania #if DEBUG if (i == 10000) { tmp[l] = eta * delty[j + 1][k + 1] * output[l]; } #endif } //p.Weights.round(); #if DEBUG //str += tmp.ToString() + "\n"; #endif } } #if DEBUG if (i == 10000) mes(str); #endif } if (OnLearningIterationEnded != null) OnLearningIterationEnded(this, new NetworkLearningIterationEventArgs(this, z * 10000)); } if (OnNetworkLearned != null) OnNetworkLearned(this, new NetworkEventArgs(this)); }
/// <summary> /// Funkcja przeznaczona do badania globalnego błędu. /// </summary> public double globalError() { double err = 0; if (examples.Count == 0) throw new Exception("Zerowa lista przkładów"); Vector sum = new Vector(examples[0].ExpectedValue.Dimension); // Wyzerowuje wektor błędu sum.zeros(); foreach (LearningExample ex in examples) { // Różnica kwadratowa //mes(classify(ex).ToString() + ", " + ex.ExpectedValue); sum += (ex.ExpectedValue - classify(ex)).power(2); } // Zaczynamy od 1, żeby pominąć bias for (int i = 1; i < examples[0].ExpectedValue.Dimension; i++) { err += sum[i]; } err /= 2.0F; //System.Windows.MessageBox.Show(((long)err).ToString()); return err; }