/// <summary> /// Pass error from the last layer to the first layer /// </summary> /// <param name="pSequence"></param> /// <param name="seqFinalOutput"></param> /// <param name="isCRF"></param> /// <returns></returns> private void ComputeDeepErr(Sequence pSequence, SimpleLayer[] seqFinalOutput, out List <double[][]> fErrLayers, out List <double[][]> bErrLayers, bool isCRF = false) { int numStates = pSequence.States.Length; int numLayers = forwardHiddenLayers.Count; //Calculate output layer error for (int curState = 0; curState < numStates; curState++) { int label = pSequence.States[curState].Label; SimpleLayer layer = seqFinalOutput[curState]; if (isCRF == false) { for (int c = 0; c < layer.LayerSize; c++) { layer.er[c] = -layer.cellOutput[c]; } layer.er[label] = 1.0 - layer.cellOutput[label]; } else { double[] CRFOutputLayer = CRFSeqOutput[curState]; for (int c = 0; c < layer.LayerSize; c++) { layer.er[c] = -CRFOutputLayer[c]; } layer.er[label] = 1 - CRFOutputLayer[label]; } } //Now we already have err in output layer, let's pass them back to other layers fErrLayers = new List <double[][]>(); bErrLayers = new List <double[][]>(); for (int i = 0; i < numLayers; i++) { fErrLayers.Add(null); bErrLayers.Add(null); } //Pass error from i+1 to i layer SimpleLayer forwardLayer = forwardHiddenLayers[numLayers - 1]; SimpleLayer backwardLayer = backwardHiddenLayers[numLayers - 1]; double[][] errLayer = new double[numStates][]; Parallel.For(0, numStates, parallelOption, curState => { errLayer[curState] = new double[forwardLayer.LayerSize]; forwardLayer.ComputeLayerErr(seqFinalOutput[curState], errLayer[curState], seqFinalOutput[curState].er); }); fErrLayers[numLayers - 1] = errLayer; bErrLayers[numLayers - 1] = errLayer; // Forward for (int i = numLayers - 2; i >= 0; i--) { forwardLayer = forwardHiddenLayers[i]; errLayer = new double[numStates][]; double[][] srcErrLayer = fErrLayers[i + 1]; Parallel.For(0, numStates, parallelOption, curState => { int curState2 = numStates - curState - 1; errLayer[curState2] = new double[forwardLayer.LayerSize]; forwardLayer.ComputeLayerErr(forwardHiddenLayers[i + 1], errLayer[curState2], srcErrLayer[curState2]); }); fErrLayers[i] = errLayer; } // Backward for (int i = numLayers - 2; i >= 0; i--) { backwardLayer = backwardHiddenLayers[i]; errLayer = new double[numStates][]; double[][] srcErrLayer = bErrLayers[i + 1]; Parallel.For(0, numStates, parallelOption, curState => { errLayer[curState] = new double[backwardLayer.LayerSize]; backwardLayer.ComputeLayerErr(backwardHiddenLayers[i + 1], errLayer[curState], srcErrLayer[curState]); }); bErrLayers[i] = errLayer; } }