private Tuple <MyVector[], My2DMatrix[]> Backpropagate(MyVector input, MyVector diseredOutput, Cancel cancelFnc) { MyVector[] parcDerivBiases = new MyVector[NumOfLayers]; My2DMatrix[] parcDerivWeights = new My2DMatrix[NumOfLayers]; MyVector activation = new MyVector(input); List <MyVector> activations = new List <MyVector>(NumOfLayers) { activation }; // Feedfoward List <MyVector> weightedInputs = new List <MyVector>(NumOfLayers); for (int i = 1; i < NumOfLayers; i++) { if (cancelFnc != null && cancelFnc()) { return(null); } MyVector weightedInput = (m_weights[i] * activation) + m_biases[i]; weightedInputs.Add(weightedInput); activation = weightedInput.ApplyFunction(Sigmoid); activations.Add(activation); } // Backpropagate MyVector delta = CrossEntrophyDelta(activations[activations.Count - 1], diseredOutput); parcDerivBiases[parcDerivBiases.Length - 1] = delta; parcDerivWeights[parcDerivWeights.Length - 1] = new My2DMatrix(delta, activations[activations.Count - 2]); for (int l = 2; l < NumOfLayers; l++) { if (cancelFnc != null && cancelFnc()) { return(null); } MyVector weightedInput = weightedInputs[weightedInputs.Count - l]; var spv = weightedInput.ApplyFunction(SigmoidPrime); delta = (m_weights[m_weights.Length - l + 1].Transpose() * delta) * spv; parcDerivBiases[parcDerivBiases.Length - l] = delta; // the error parcDerivWeights[parcDerivWeights.Length - l] = new My2DMatrix(delta, activations[activations.Count - l - 1]); // error times the activation from the previous layer (vector times vector^T creates matrix) } return(new Tuple <MyVector[], My2DMatrix[]>(parcDerivBiases, parcDerivWeights)); }