Example #1
0
#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);
        }
Example #2
0
#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);
        }