private void BackPropagationOutput(int row) { int lastLayerNeurons = _layers[_layers.Length - 1].Neurons.Length; int connectionsToNeuron = _layers[_layers.Length - 1].Neurons[0].Synapses.Length; // Operowanie na każdym neuronie w ostaniej warstwie for (int i = 0; i < lastLayerNeurons; i++) { // output - ExpectedOutput // Pochodna po funkcji kosztu double difference = (_layers[_layers.Length - 1].Neurons[i].Value - _expectedResults[row][i]); // SigmoidDerivative to pochodna po funkcji aktywacji z neurona double nodeDelta = difference * MathFuncs.SigmoidDerivative(_layers[_layers.Length - 1].Neurons[i].Value); _layers[_layers.Length - 1].Neurons[i].PreviousPartialDerivative = nodeDelta; // Dla każdego neurona z ostatniej warstwy obsługiwanie jednej z jego synaps wejściowych for (int j = 0; j < connectionsToNeuron; j++) { // Wartości neuronów z poprzedniej warstwy double netInput = _layers[_layers.Length - 2].Neurons[j].Value; double delta = -1 * nodeDelta * netInput; // Aktualizacja wagi // Wcześniejsza waga wpisywana na previousWeight, potrzebne do dalszej propagacji, ponieważ // to ją będziemy uwzględniać ( w Weight będzie waga zaaktualizowana ) _layers[_layers.Length - 1].Neurons[i].Synapses[j].PreviousWeight = _layers[_layers.Length - 1].Neurons[i].Synapses[j].Weight; _layers[_layers.Length - 1].Neurons[i].Synapses[j].Weight += (delta * _learningRate); } } }
private void BackPropagationHidden() { // Iterowanie po warstwach wstecz, od przedostatniej warstwy // stop przy drugiej warstwie for (int i = _layers.Length - 2; i > 0; i--) { // Iterowanie po neuronach w warstwie for (int j = 0; j < _layers[i].Neurons.Length; j++) { // Iterowanie po wejściowych synapsach neuronu // Przygotowanie do aktualizacji ich wag for (int k = 0; k < _layers[i].Neurons[j].Synapses.Length; k++) { // Poprzednia wartość neurona double netInput = _layers[i - 1].Neurons[k].Value; double sumPartial = 0; // Iteracja po neuronach z warstwy następnej ( poprzedniej patrząc na propagacje // jako na iteracje od końca do początku) // Zbieranie wag i poprzednich pochodnych z wcześniejszych połączeń for (int m = 0; m < _layers[i + 1].Neurons.Length; m++) { sumPartial += _layers[i + 1].Neurons[m].Synapses[j].PreviousWeight * _layers[i + 1].Neurons[m].PreviousPartialDerivative; } // Pochodna obecnej warstwy double nodeDelta = sumPartial * MathFuncs.SigmoidDerivative(_layers[i].Neurons[j].Value); _layers[i].Neurons[j].PreviousPartialDerivative = nodeDelta; double delta = -1 * netInput * nodeDelta; // Aktualizacja wagi // Wcześniejsza waga wpisywana na previousWeight, potrzebne do dalszej propagacji, ponieważ // to ją będziemy uwzględniać ( w Weight będzie waga zaaktualizowana ) _layers[i].Neurons[j].Synapses[k].PreviousWeight = _layers[i].Neurons[j].Synapses[k].Weight; _layers[i].Neurons[j].Synapses[k].Weight += (delta * _learningRate); } } } }