Example #1
0
        /// <summary> Calculates the changes this <see cref="NeuronLayer"/> wishes to make to its <see cref="neurons"/>. </summary>
        /// <param name="neuronLayerChange"> The changes to make to the <see cref="NeuronLayer"/>. </param>
        /// <param name="weightLayerChange"> The changes to make to the <see cref="WeightLayer"/>. </param>
        /// <param name="deltaOrError"> The delta or error of the next <see cref="NeuronLayer"/>, or calculated from the output of the <see cref="NeuralNetwork"/>. </param>
        public void CalculateChanges(NeuronLayerChange neuronLayerChange, WeightLayerChange weightLayerChange, IReadOnlyList <float> deltaOrError)
        {
#if DEBUG
            if (neuronLayerChange.NeuronLayer != this)
            {
                throw new Exception("Neuron layer mismatch.");
            }
            if (weightLayerChange.WeightLayer != PreviousWeightLayer)
            {
                throw new Exception("Weight layer mismatch.");
            }
#endif

            // If this is the output layer, calculate based on the error.
            if (NextWeightLayer is null)
            {
                for (uint i = 0; i < Count; i++)
                {
                    neuronLayerChange.SetDelta(this[i], neurons[i].CalculateChanges(neuronLayerChange, weightLayerChange, deltaOrError[(int)i]));
                }
            }
            // Otherwise; if this is a hidden layer, calculate based on the delta of the next layer.
            else
            {
                for (uint i = 0; i < Count; i++)
                {
                    neuronLayerChange.SetDelta(this[i], neurons[i].CalculateErrorThenChanges(neuronLayerChange, weightLayerChange, deltaOrError));
                }
            }
        }
Example #2
0
        /// <summary> Calculates and adds the changes to make to this <see cref="Neuron"/> to the given <paramref name="neuronLayerChange"/> and <paramref name="weightLayerChange"/> using the given <paramref name="delta"/>. </summary>
        /// <param name="neuronLayerChange"> The changes to make to the containing <see cref="NeuronLayer"/>. </param>
        /// <param name="weightLayerChange"> The changes to make to the previous <see cref="WeightLayer"/>. </param>
        /// <param name="delta"> The calculated delta, used to calculate the desired change. </param>
        private void addChanges(NeuronLayerChange neuronLayerChange, WeightLayerChange weightLayerChange, float delta)
        {
            // Calculate the change in bias based on the delta.
            neuronLayerChange.AddBias(this, delta);

            // Calculate the changes to the input weights of this neuron.
            // The change to make is based on the output of the neuron to which the weight is connected. "Neurons that fire together, wire together".
            foreach (uint previousLayerNeuronID in NeuronLayer.PreviousWeightLayer.GetPreviousLayerConnections(this))
            {
                weightLayerChange.AddWeightChangeBetweenNeurons(previousNeuronLayer[previousLayerNeuronID], this, previousNeuronLayer[previousLayerNeuronID].Output * delta);
            }
        }
Example #3
0
        /// <summary> Calculates and adds the changes to be made to this <see cref="Neuron"/> from the given <paramref name="previousDelta"/>. </summary>
        /// <param name="neuronLayerChange"> The changes to make to the containing <see cref="NeuronLayer"/>. </param>
        /// <param name="weightLayerChange"> The changes to make to the previous <see cref="WeightLayer"/>. </param>
        /// <param name="previousDelta"> The calculated deltas from the previous <see cref="NeuronLayer"/> of this <see cref="Neuron"/>. </param>
        /// <returns> The calculated delta of this <see cref="Neuron"/>. </returns>
        public float CalculateErrorThenChanges(NeuronLayerChange neuronLayerChange, WeightLayerChange weightLayerChange, IReadOnlyList <float> previousDelta)
        {
            // Calculate the summed error using the connections from this neuron to the next layer.
            float summedError = 0;

            foreach (uint nextLayerNeuronID in NeuronLayer.NextWeightLayer.GetNextLayerConnections(this))
            {
                summedError += NeuronLayer.NextWeightLayer.GetWeightBetweenNeurons(this, nextNeuronLayer[nextLayerNeuronID]) * previousDelta[(int)nextLayerNeuronID];
            }

            // Finish the delta calculations with the summed error.
            return(CalculateChanges(neuronLayerChange, weightLayerChange, summedError));
        }
Example #4
0
        /// <summary> Creates a new <see cref="NetworkChange"/> for the given <paramref name="neuralNetwork"/>. </summary>
        /// <param name="neuralNetwork"> The <see cref="IReadOnlyNeuralNetwork"/> whose changes are being stored. </param>
        public NetworkChange(IReadOnlyNeuralNetwork neuralNetwork)
        {
            // Set the neural network.
            NeuralNetwork = neuralNetwork;

            // Initialise the neuron and weight changes.
            neuronLayerChanges = new NeuronLayerChange[neuralNetwork.NeuronLayerCount - 1];
            weightLayerChanges = new WeightLayerChange[neuralNetwork.WeightLayerCount];
            for (int i = 0; i < neuronLayerChanges.Length; i++)
            {
                neuronLayerChanges[i] = new NeuronLayerChange(neuralNetwork.GetNeuronLayer(i + 1));
            }
            for (int i = 0; i < weightLayerChanges.Length; i++)
            {
                weightLayerChanges[i] = new WeightLayerChange(neuralNetwork.GetWeightLayer(i));
            }
        }
Example #5
0
        /// <summary> Calculates and adds the changes to be made to this <see cref="Neuron"/> from the given <paramref name="error"/>. </summary>
        /// <param name="neuronLayerChange"> The changes to make to the containing <see cref="NeuronLayer"/>. </param>
        /// <param name="weightLayerChange"> The changes to make to the previous <see cref="WeightLayer"/>. </param>
        /// <param name="error"> The previously calculated delta. </param>
        /// <returns> The calculated delta of this <see cref="Neuron"/>. </returns>
        public float CalculateChanges(NeuronLayerChange neuronLayerChange, WeightLayerChange weightLayerChange, float error)
        {
            // Calculate the delta.
            float delta = activationFunction.ActivationDerivative(Output) * error;

            float p = activationFunction.ActivationDerivative(Output);

            if (p < 0)
            {
                throw new Exception();
            }

            // Add the changes to be made.
            addChanges(neuronLayerChange, weightLayerChange, delta);

            // Return the calculated delta.
            return(delta);
        }