public BackPropagationLearning(ActivationNetwork network) { this.network = network; // create error and deltas arrays neuronErrors = new double[network.Layers.Length][]; weightsUpdates = new double[network.Layers.Length][][]; thresholdsUpdates = new double[network.Layers.Length][]; // initialize errors and deltas arrays for each layer for (int i = 0; i < network.Layers.Length; i++) { ActivationLayer layer = network.Layers[i]; neuronErrors[i] = new double[layer.Neurons.Length]; weightsUpdates[i] = new double[layer.Neurons.Length][]; thresholdsUpdates[i] = new double[layer.Neurons.Length]; // for each neuron for (int j = 0; j < weightsUpdates[i].Length; j++) { weightsUpdates[i][j] = new double[layer.InputsCount]; } } }
/// <summary> /// Calculate weights updates. /// </summary> /// /// <param name="input">Network's input vector.</param> /// private void CalculateUpdates(double[] input) { // 1 - calculate updates for the first layer ActivationLayer layer = network.Layers[0]; double[] errors = neuronErrors[0]; double[][] layerWeightsUpdates = weightsUpdates[0]; double[] layerThresholdUpdates = thresholdsUpdates[0]; // cache for frequently used values double cachedMomentum = learningRate * momentum; double cached1mMomentum = learningRate * (1 - momentum); double cachedError; // for each neuron of the layer for (int i = 0; i < layer.Neurons.Length; i++) { cachedError = errors[i] * cached1mMomentum; double[] neuronWeightUpdates = layerWeightsUpdates[i]; // for each weight of the neuron for (int j = 0; j < neuronWeightUpdates.Length; j++) { // calculate weight update neuronWeightUpdates[j] = cachedMomentum * neuronWeightUpdates[j] + cachedError * input[j]; } // calculate threshold update layerThresholdUpdates[i] = cachedMomentum * layerThresholdUpdates[i] + cachedError; } // 2 - for all other layers for (int k = 1; k < network.Layers.Length; k++) { ActivationLayer layerPrev = network.Layers[k - 1]; layer = network.Layers[k]; errors = neuronErrors[k]; layerWeightsUpdates = weightsUpdates[k]; layerThresholdUpdates = thresholdsUpdates[k]; // for each neuron of the layer for (int i = 0; i < layer.Neurons.Length; i++) { cachedError = errors[i] * cached1mMomentum; double[] neuronWeightUpdates = layerWeightsUpdates[i]; // for each synapse of the neuron for (int j = 0; j < neuronWeightUpdates.Length; j++) { // calculate weight update neuronWeightUpdates[j] = cachedMomentum * neuronWeightUpdates[j] + cachedError * layerPrev.Neurons[j].Output; } // calculate threshold update layerThresholdUpdates[i] = cachedMomentum * layerThresholdUpdates[i] + cachedError; } } }
public ActivationNetwork(SigmoidFunction function, int inputsCount, params int[] neuronsCount) { ActivationFunction = function; InputsCount = Math.Max(1, inputsCount); Layers = new ActivationLayer[neuronsCount.Length]; // create each layer for (int i = 0; i < Layers.Length; i++) { Layers[i] = new ActivationLayer(neuronsCount[i], (i == 0) ? inputsCount : neuronsCount[i - 1]); } }