public int[][] DecodeNBestCRF(Sequence seq, int N) { //ys contains the output of RNN for each word Matrix <double> ys = PredictSentence(seq, RunningMode.Test); int n = seq.States.Length; int K = L2; Matrix <double> STP = CRFTagTransWeights; PAIR <int, int>[, ,] vPath = new PAIR <int, int> [n, K, N]; int DUMP_LABEL = -1; double[,] vPreAlpha = new double[K, N]; double[,] vAlpha = new double[K, N]; int nStartTagIndex = 0; int nEndTagIndex = 0; double MIN_VALUE = double.MinValue; //viterbi algorithm for (int i = 0; i < K; i++) { for (int j = 0; j < N; j++) { vPreAlpha[i, j] = MIN_VALUE; vPath[0, i, j] = new PAIR <int, int>(DUMP_LABEL, 0); } } vPreAlpha[nStartTagIndex, 0] = ys[0][nStartTagIndex]; vPath[0, nStartTagIndex, 0].first = nStartTagIndex; AdvUtils.PriorityQueue <double, PAIR <int, int> > q = new AdvUtils.PriorityQueue <double, PAIR <int, int> >(); for (int t = 1; t < n; t++) { for (int j = 0; j < K; j++) { while (q.Count() > 0) { q.Dequeue(); } double _stp = STP[j][0]; double _y = ys[t][j]; for (int k = 0; k < N; k++) { double score = vPreAlpha[0, k] + _stp + _y; q.Enqueue(score, new PAIR <int, int>(0, k)); } for (int i = 1; i < K; i++) { _stp = STP[j][i]; for (int k = 0; k < N; k++) { double score = vPreAlpha[i, k] + _stp + _y; if (score <= q.Peek().Key) { break; } q.Dequeue(); q.Enqueue(score, new PAIR <int, int>(i, k)); } } int idx = N - 1; while (q.Count() > 0) { vAlpha[j, idx] = q.Peek().Key; vPath[t, j, idx] = q.Peek().Value; idx--; q.Dequeue(); } } vPreAlpha = vAlpha; vAlpha = new double[K, N]; } //backtrace to get the n-best result path int[][] vTagOutput = new int[N][]; for (int i = 0; i < N; i++) { vTagOutput[i] = new int[n]; } for (int k = 0; k < N; k++) { vTagOutput[k][n - 1] = nEndTagIndex; PAIR <int, int> decision = new PAIR <int, int>(nEndTagIndex, k); for (int t = n - 2; t >= 0; t--) { vTagOutput[k][t] = vPath[t + 1, decision.first, decision.second].first; decision = vPath[t + 1, decision.first, decision.second]; } } return(vTagOutput); }
public int[][] DecodeNBestCRF(Sequence seq, int N) { //ys contains the output of RNN for each word Matrix<double> ys = ProcessSequence(seq, RunningMode.Test); int n = seq.States.Length; int K = OutputLayer.LayerSize; Matrix<double> STP = CRFTagTransWeights; PAIR<int, int>[,,] vPath = new PAIR<int, int>[n, K, N]; int DUMP_LABEL = -1; double[,] vPreAlpha = new double[K, N]; double[,] vAlpha = new double[K, N]; int nStartTagIndex = 0; int nEndTagIndex = 0; double MIN_VALUE = double.MinValue; //viterbi algorithm for (int i = 0; i < K; i++) { for (int j = 0; j < N; j++) { vPreAlpha[i, j] = MIN_VALUE; vPath[0, i, j] = new PAIR<int, int>(DUMP_LABEL, 0); } } vPreAlpha[nStartTagIndex, 0] = ys[0][nStartTagIndex]; vPath[0, nStartTagIndex, 0].first = nStartTagIndex; AdvUtils.PriorityQueue<double, PAIR<int, int>> q = new AdvUtils.PriorityQueue<double, PAIR<int, int>>(); for (int t = 1; t < n; t++) { for (int j = 0; j < K; j++) { while (q.Count() > 0) q.Dequeue(); double _stp = STP[j][0]; double _y = ys[t][j]; for (int k = 0; k < N; k++) { double score = vPreAlpha[0, k] + _stp + _y; q.Enqueue(score, new PAIR<int, int>(0, k)); } for (int i = 1; i < K; i++) { _stp = STP[j][i]; for (int k = 0; k < N; k++) { double score = vPreAlpha[i, k] + _stp + _y; if (score <= q.Peek().Key) break; q.Dequeue(); q.Enqueue(score, new PAIR<int, int>(i, k)); } } int idx = N - 1; while (q.Count() > 0) { vAlpha[j, idx] = q.Peek().Key; vPath[t, j, idx] = q.Peek().Value; idx--; q.Dequeue(); } } vPreAlpha = vAlpha; vAlpha = new double[K, N]; } //backtrace to get the n-best result path int[][] vTagOutput = new int[N][]; for (int i = 0; i < N; i++) { vTagOutput[i] = new int[n]; } for (int k = 0; k < N; k++) { vTagOutput[k][n - 1] = nEndTagIndex; PAIR<int, int> decision = new PAIR<int, int>(nEndTagIndex, k); for (int t = n - 2; t >= 0; t--) { vTagOutput[k][t] = vPath[t + 1, decision.first, decision.second].first; decision = vPath[t + 1, decision.first, decision.second]; } } return vTagOutput; }