private void ComputeGradients(FeedForwardData feedForwardData) { //output gradients int numberOfOutputNeurons = LayerStructure.numberOfOutputNodes; _outputGradientMatrix = new double[numberOfOutputNeurons]; int outputLayerIndex = feedForwardData.LayerInputs.Count - 1; var outputLayerInputs = feedForwardData.LayerOutputs[outputLayerIndex]; for (int i = 0; i < numberOfOutputNeurons; i++) { _outputGradientMatrix[i] = DerivedErrorMatrix[i] * _outputActivationFunction.DerivedActivationFunctionOutput(outputLayerInputs[i]); } _gradientMatrices.Add(_outputGradientMatrix); //hidden layer gradients int numberOfHiddenLayers = LayerStructure.HiddenLayerList.Count; var forwardLayerGradients = _outputGradientMatrix; for (int i = numberOfHiddenLayers; i > 0; i--) { var currentWeightMatrix = Matrix.Transpose(_weights[i]); //this was transposed in the original... why?! var currentHiddenLayerInputs = feedForwardData.LayerInputs[i]; //this is for regression //var currentHiddenLayerInputs = feedForwardData.LayerOutputs[i]; //this is for classification int numberOfNeuronsInCurrentLayer = feedForwardData.LayerOutputs[i].GetLength(0); int numberOfNeuronsInForwardLayer = feedForwardData.LayerOutputs[i + 1].GetLength(0); var hiddenGradientMatrix = new double[numberOfNeuronsInCurrentLayer]; for (int j = 0; j < numberOfNeuronsInCurrentLayer; j++) { double weightGradientSum = 0.0; for (int k = 0; k < numberOfNeuronsInForwardLayer; k++) { weightGradientSum += currentWeightMatrix[j, k] * forwardLayerGradients[k]; } hiddenGradientMatrix[j] = weightGradientSum * _hiddenActivationFunction.DerivedActivationFunctionOutput(currentHiddenLayerInputs[j]); } _gradientMatrices.Add(hiddenGradientMatrix); forwardLayerGradients = hiddenGradientMatrix; } }