#pragma warning disable SA1313 // Variable names must begin with lower-case letter private Buffers BeamSearch(Buffers flip, Buffers flop, int T, int A, float[] ylog, Context context) #pragma warning restore SA1313 // Variable names must begin with lower-case letter { State initialState = context.InitialState; // add blank int[] initial = new int[1]; flop.Add(initial, 0, Buffer.InitialHash, ylog[this.BlankLabelIndex], float.NegativeInfinity, initialState); // add characters from context IDictionary <char, State> nextstates = initialState.NextStates(); if (nextstates != null) { foreach (State nextstate in nextstates.Values) { int idx = this.TryGetClass(nextstate.Char); float prob = idx >= 0 ? ylog[idx] : this.missingProb; if (this.UseStatistics) { prob += nextstate.CharProbability; } initial[0] = idx; flop.Add(initial, 1, Buffer.HashCode(Buffer.InitialHash, idx), float.NegativeInfinity, prob, nextstate); } } // flip between buffers for (int t = 1, off = A; t < T; t++, off += A) { Swapping.Swap(ref flip, ref flop); for (Buffer buffer = flip.Head; buffer != null; buffer = buffer.Next) { int[] values = buffer.Classes; int length = buffer.Length; State state = buffer.State; int lastIdx = length > 0 ? values[length - 1] : CTCBeamSearch.NoClass; // repeat buffer with added blank and duplicated last character float probBlank = buffer.Prob + ylog[off + this.BlankLabelIndex]; // no length check here - // if prob is not neg. infinity it means there is at least one character float probNoBlank = float.NegativeInfinity; if (!float.IsNegativeInfinity(buffer.ProbNoBlank)) { probNoBlank = buffer.ProbNoBlank + (lastIdx >= 0 ? ylog[off + lastIdx] : this.missingProb); } flop.Add(values, length, buffer.Hash, probBlank, probNoBlank, state); // add context characters nextstates = state.NextStates(); if (nextstates != null) { foreach (State nextstate in nextstates.Values) { int idx = this.TryGetClass(nextstate.Char); float prob = idx >= 0 ? ylog[off + idx] : this.missingProb; if (idx == lastIdx) { // when there are two consecutive same characters - // append only there is a blank between them if (float.IsNegativeInfinity(buffer.ProbBlank)) { continue; } // same character - append to blank path only prob += buffer.ProbBlank; } else { // different character - append to both blank and noblank paths prob += buffer.Prob; } if (this.UseStatistics) { prob += nextstate.CharProbability; } values[length] = idx; flop.Add(values, length + 1, Buffer.HashCode(buffer.Hash, idx), float.NegativeInfinity, prob, nextstate); } } } flip.Free(); } return(flop); }
#pragma warning disable SA1313 // Variable names must begin with lower-case letter private Buffers BeamSearch(Buffers flip, Buffers flop, int T, int A, float[] ylog) #pragma warning restore SA1313 // Variable names must begin with lower-case letter { // create array that contains classes indexes // and then sort both probabilities and indexes int[] cls = new int[ylog.Length]; for (int t = 0, off = 0; t < T; t++, off += A) { for (int i = 0; i < A; i++) { cls[off + i] = i; } Vectors.Sort(A, ylog, off, cls, off, false); } // initialize first buffer int[] initial = new int[1]; for (int i = 0; i < A && i < 3; i++) { int idx = cls[i]; float prob = ylog[i]; if (idx == this.BlankLabelIndex) { flop.Add(initial, 0, Buffer.InitialHash, prob, float.NegativeInfinity, null); } else if (idx != this.spaceLabelIndex) { // do not start with spaces initial[0] = idx; flop.Add(initial, 1, Buffer.HashCode(Buffer.InitialHash, idx), float.NegativeInfinity, prob, null); } } // flip between buffers for (int t = 1, off = A; t < T; t++, off += A) { Swapping.Swap(ref flip, ref flop); for (Buffer buffer = flip.Head; buffer != null; buffer = buffer.Next) { int[] values = buffer.Classes; int length = buffer.Length; int lastIdx = length > 0 ? values[length - 1] : CTCBeamSearch.NoClass; float probBlank = float.NegativeInfinity; float probNoBlank = float.NegativeInfinity; for (int i = 0; i < A && i < 3; i++) { int idx = cls[off + i]; float prob = ylog[off + i]; if (idx == this.BlankLabelIndex) { // get probability of blank character probBlank = buffer.Prob + prob; } else { if (idx == lastIdx) { // get probability of duplicated last character if (!float.IsNegativeInfinity(buffer.ProbNoBlank)) { probNoBlank = buffer.ProbNoBlank + prob; } // when there are two consecutive same characters - // append only there is a blank between them if (float.IsNegativeInfinity(buffer.ProbBlank)) { continue; } // do not repeat blanks if (idx == this.spaceLabelIndex) { continue; } // same character - append to blank path only prob += buffer.ProbBlank; } else { // different character - append to both blank and noblank paths prob += buffer.Prob; } values[length] = idx; flop.Add(values, length + 1, Buffer.HashCode(buffer.Hash, idx), float.NegativeInfinity, prob, null); } } // repeat buffer with blank and duplicated characters if (!float.IsNegativeInfinity(probBlank) || !float.IsNegativeInfinity(probNoBlank)) { flop.Add(values, length, buffer.Hash, probBlank, probNoBlank, null); } } flip.Free(); } return(flop); }