Exemple #1
0
        /// <summary>
        /// Generates the influence matrix based on a given <see cref="T:IFiniteStateMachine`1"/> and an index
        /// that is part of a strongly connected group in the finite state machine.
        /// </summary>
        /// <returns>A 2d-matrix that contains the influence matrix of the strongly connected group.</returns>
        /// <param name="fsm">The given finite state machine to generate the influence matrix from.</param>
        /// <param name="strongIndex">The initial index to generate an influence matrix from.</param>
        /// <remarks>
        /// <para>The given initial index must be part of a strongly connected group. If the index is not part,
        /// the algorithm will loop.</para>
        /// </remarks>
        public void GenerateInfluenceMatrix(IFiniteStateMachine <int> fsm, int strongIndex)
        {
            int n = fsm.Length;
            int s = this.Length;
            int o = this.OutputSize;

            double[] trans = new double[s * s];
            double[,] a = this.a, b = this.b;
            double[] ch1 = new double[s], ch2 = new double[s], cht;
            int      idx, otp, j, i;
            double   sum;

            for (int ori = 0x00; ori < s; ori++)
            {
                for (j = 0x00; j < ori; j++)
                {
                    ch2 [j] = 0.0d;
                }
                ch2 [j] = 1.0d;
                for (j++; j < s; j++)
                {
                    ch2 [j] = 0.0d;
                }
                idx = strongIndex;
                do
                {
                    cht = ch1;
                    ch1 = ch2;
                    ch2 = cht;
                    otp = fsm.GetOutput(idx);
                    for (j = 0x00; j < s; j++)
                    {
                        sum = 0.0d;
                        for (i = 0x00; i < s; i++)
                        {
                            sum += ch1 [i] * a [i, j];
                        }
                        sum    *= b [j, otp];
                        ch2 [j] = sum;
                    }
                    idx = fsm.GetTransitionOfIndex(idx);
                } while(idx != strongIndex);
                for (j = 0x00, i = ori; j < s; i += s, j++)
                {
                    trans [i] = ch2 [j];
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Train this <see cref="IHiddenMarkovModel"/> by using the given <see cref="T:IFiniteStateMachine`1"/>
        /// model. Since such finite state machine generates infinite sequences of output, training that sequence
        /// would result in an underdetermined system. The sample length must thefore be specified.
        /// </summary>
        /// <returns>The error on the training. In other words how different the original Hidden Markov model is from the
        /// given finite state machine.</returns>
        /// <param name="fsm">The finite state machine from which the <see cref="IHiddenMarkovModel"/> learns.</param>
        /// <param name="initialDistribution"> the initial distribution for the states of the finite state machine.</param>
        /// <param name="sampleLength">The length of the samples, has impact on the trained model.</param>
        public double Train(IFiniteStateMachine <int> fsm, IList <int> initialDistribution, int sampleLength)
        {
            int N  = fsm.Length;
            int S  = this.Length;
            int O  = this.OutputSize;
            int T  = sampleLength;
            int T1 = T - 0x01;

            double[] p = this.Probabilities;
            double[,] a        = this.a, b = this.b;
            double[,] alpha    = new double[T, S], beta = new double[T, S], gamma = new double[T, S], bhat = new double[S, O], ahat = new double[S, S];
            double[,,] epsilon = new double[T, S, S];
            double[] asc = new double[S], bsc = new double[S], phat = new double[S];
            for (int si = 0x00; si < S; si++)
            {
                beta [T1, si] = 1.0d;
            }
            double norm, sum, ssum, tmp;

            int[]  os = new int[sampleLength];
            double sprob = 0.0d, prob;
            int    stok = 0x00;

            for (int ni = 0x00; ni < N; ni++)
            {
                stok += initialDistribution [ni];
            }
            for (int ni = 0x00; ni < N; ni++)              //TODO: extremely optimize this
            {
                int tok = initialDistribution [ni];
                if (tok > 0x00)
                {
                    int n = ni;
                    #region Forward algorithm
                    prob = 1.0d;
                    int o = fsm.GetOutput(n);
                    os [0x00] = o;
                    ssum      = 0.0d;
                    for (int si = 0x00; si < S; si++)
                    {
                        sum = p [si] * b [si, o];
                        alpha [0x00, si] = sum;
                        ssum            += sum;
                    }
                    n    = fsm.GetTransitionOfIndex(n);
                    norm = 1.0d / ssum;
                    for (int t = 0x00; t < T1; t++)
                    {
                        o             = fsm.GetOutput(n);
                        os [t + 0x01] = o;
                        ssum          = 0.0d;
                        for (int sj = 0x00; sj < S; sj++)
                        {
                            sum = 0.0d;
                            for (int si = 0x00; si < S; si++)
                            {
                                sum += a [si, sj] * alpha [t, si];
                            }
                            sum  *= norm * b [sj, o];
                            ssum += sum;
                            alpha [t + 0x01, sj] = sum;
                        }
                        n     = fsm.GetTransitionOfIndex(n);
                        prob *= ssum;
                        norm  = 1.0d / ssum;
                    }
                    sprob += Math.Abs((double)tok / stok - prob);
                    #endregion
                    #region Backward algorithm
                    norm = 1.0d;
                    for (int t = sampleLength - 0x01; t > 0x00; t--)
                    {
                        o    = os [t];                     //OST: soundtrack
                        ssum = 0.0d;
                        for (int si = S - 0x01; si >= 0x00; si--)
                        {
                            sum = 0.0d;
                            for (int sj = S - 0x01; sj >= 0x00; sj--)
                            {
                                sum += a [si, sj] * beta [t, sj] * b [sj, o];
                            }
                            sum  *= norm;
                            ssum += sum;
                            beta [t - 0x01, si] = sum;
                        }
                        norm = 1.0d / ssum;
                    }
                    #endregion
                    #region Gamma/Xi values
                    for (int t = 0x00; t < T; t++)
                    {
                        sum = 0.0d;
                        o   = os [t];
                        for (int si = 0x00; si < S; si++)
                        {
                            tmp           = alpha [t, si] * beta [t, si];
                            sum          += tmp;
                            gamma [t, si] = tmp;
                        }
                        sum = 1.0d / sum;
                        for (int si = 0x00; si < S; si++)
                        {
                            tmp           = gamma [t, si];
                            tmp          *= sum;
                            gamma [t, si] = tmp;
                            asc [si]     += tok * tmp;
                            bhat [si, o] += tok * tmp;
                        }
                    }
                    for (int si = 0x00; si < S; si++)
                    {
                        phat [si] = tok * gamma [0x00, si];
                        bsc [si] += tok * gamma [T1, si];
                    }
                    for (int t = 0x00; t < T1; t++)
                    {
                        o = os [t + 0x01];
                        for (int si = 0x00; si < S; si++)
                        {
                            sum = 0.0d;
                            for (int sj = 0x00; sj < S; sj++)
                            {
                                tmp  = alpha [t, si] * beta [t + 0x01, sj] * a [si, sj] * b [sj, o];
                                sum += tmp;
                                epsilon [t, si, sj] = tmp;
                            }
                            sum = gamma [t, si] / sum;
                            for (int sj = 0x00; sj < S; sj++)
                            {
                                tmp                 = epsilon [t, si, sj];
                                tmp                *= sum;
                                ahat [si, sj]      += tok * tmp;
                                epsilon [t, si, sj] = tmp;
                            }
                        }
                    }
                    #endregion
                }
            }
            #region Updates (should be moved after tokenselect)
            sum = 1.0d / stok;
            for (int si = 0x00; si < S; si++)
            {
                p [si] = phat [si] * stok;
                tmp    = 1.0d / asc [si];
                for (int o = 0x00; o < O; o++)
                {
                    b [si, o] = bhat [si, o] * tmp;
                }
                tmp = 1.0d / (asc [si] - bsc [si]);
                for (int sj = 0x00; sj < S; sj++)
                {
                    a [si, sj] = ahat [si, sj] * tmp;
                }
            }
            #endregion
            return(sprob / stok);
        }
        /// <summary>
        /// Train this <see cref="IHiddenMarkovModel"/> by using the given <see cref="T:IFiniteStateMachine`1"/>
        /// model. Since such finite state machine generates infinite sequences of output, training that sequence
        /// would result in an underdetermined system. The sample length must thefore be specified.
        /// </summary>
        /// <returns>The error on the training. In other words how different the original Hidden Markov model is from the
        /// given finite state machine.</returns>
        /// <param name="fsm">The finite state machine from which the <see cref="IHiddenMarkovModel"/> learns.</param>
        /// <param name="initialDistribution"> the initial distribution for the states of the finite state machine.</param>
        /// <param name="sampleLength">The length of the samples, has impact on the trained model.</param>
        public double Train(IFiniteStateMachine<int> fsm, IList<int> initialDistribution, int sampleLength)
        {
            int N = fsm.Length;
            int S = this.Length;
            int O = this.OutputSize;
            int T = sampleLength;
            int T1 = T - 0x01;
            double[] p = this.Probabilities;
            double[,] a = this.a, b = this.b;
            double[,] alpha = new double[T, S], beta = new double[T, S], gamma = new double[T, S], bhat = new double[S, O], ahat = new double[S, S];
            double[,,] epsilon = new double[T, S, S];
            double[] asc = new double[S], bsc = new double[S], phat = new double[S];
            for (int si = 0x00; si < S; si++) {
                beta [T1, si] = 1.0d;
            }
            double norm, sum, ssum, tmp;
            int[] os = new int[sampleLength];
            double sprob = 0.0d, prob;
            int stok = 0x00;
            for (int ni = 0x00; ni < N; ni++) {
                stok += initialDistribution [ni];
            }
            for (int ni = 0x00; ni < N; ni++) {//TODO: extremely optimize this
                int tok = initialDistribution [ni];
                if (tok > 0x00) {
                    int n = ni;
                    #region Forward algorithm
                    prob = 1.0d;
                    int o = fsm.GetOutput (n);
                    os [0x00] = o;
                    ssum = 0.0d;
                    for (int si = 0x00; si < S; si++) {
                        sum = p [si] * b [si, o];
                        alpha [0x00, si] = sum;
                        ssum += sum;
                    }
                    n = fsm.GetTransitionOfIndex (n);
                    norm = 1.0d / ssum;
                    for (int t = 0x00; t < T1; t++) {
                        o = fsm.GetOutput (n);
                        os [t + 0x01] = o;
                        ssum = 0.0d;
                        for (int sj = 0x00; sj < S; sj++) {
                            sum = 0.0d;
                            for (int si = 0x00; si < S; si++) {
                                sum += a [si, sj] * alpha [t, si];
                            }
                            sum *= norm * b [sj, o];
                            ssum += sum;
                            alpha [t + 0x01, sj] = sum;
                        }
                        n = fsm.GetTransitionOfIndex (n);
                        prob *= ssum;
                        norm = 1.0d / ssum;
                    }
                    sprob += Math.Abs ((double)tok / stok - prob);
                    #endregion
                    #region Backward algorithm
                    norm = 1.0d;
                    for (int t = sampleLength-0x01; t > 0x00; t--) {
                        o = os [t];//OST: soundtrack
                        ssum = 0.0d;
                        for (int si = S-0x01; si >= 0x00; si--) {
                            sum = 0.0d;
                            for (int sj = S-0x01; sj >= 0x00; sj--) {
                                sum += a [si, sj] * beta [t, sj] * b [sj, o];
                            }
                            sum *= norm;
                            ssum += sum;
                            beta [t - 0x01, si] = sum;
                        }
                        norm = 1.0d / ssum;
                    }
                    #endregion
                    #region Gamma/Xi values
                    for (int t = 0x00; t < T; t++) {
                        sum = 0.0d;
                        o = os [t];
                        for (int si = 0x00; si < S; si++) {
                            tmp = alpha [t, si] * beta [t, si];
                            sum += tmp;
                            gamma [t, si] = tmp;
                        }
                        sum = 1.0d / sum;
                        for (int si = 0x00; si < S; si++) {
                            tmp = gamma [t, si];
                            tmp *= sum;
                            gamma [t, si] = tmp;
                            asc [si] += tok * tmp;
                            bhat [si, o] += tok * tmp;
                        }
                    }
                    for (int si = 0x00; si < S; si++) {
                        phat [si] = tok * gamma [0x00, si];
                        bsc [si] += tok * gamma [T1, si];
                    }
                    for (int t = 0x00; t < T1; t++) {
                        o = os [t + 0x01];
                        for (int si = 0x00; si < S; si++) {
                            sum = 0.0d;
                            for (int sj = 0x00; sj < S; sj++) {
                                tmp = alpha [t, si] * beta [t + 0x01, sj] * a [si, sj] * b [sj, o];
                                sum += tmp;
                                epsilon [t, si, sj] = tmp;
                            }
                            sum = gamma [t, si] / sum;
                            for (int sj = 0x00; sj < S; sj++) {
                                tmp = epsilon [t, si, sj];
                                tmp *= sum;
                                ahat [si, sj] += tok * tmp;
                                epsilon [t, si, sj] = tmp;
                            }
                        }

                    }
                    #endregion
                }
            }
            #region Updates (should be moved after tokenselect)
            sum = 1.0d / stok;
            for (int si = 0x00; si < S; si++) {
                p [si] = phat [si] * stok;
                tmp = 1.0d / asc [si];
                for (int o = 0x00; o < O; o++) {
                    b [si, o] = bhat [si, o] * tmp;
                }
                tmp = 1.0d / (asc [si] - bsc [si]);
                for (int sj = 0x00; sj < S; sj++) {
                    a [si, sj] = ahat [si, sj] * tmp;
                }
            }
            #endregion
            return sprob / stok;
        }
 /// <summary>
 /// Generates the influence matrix based on a given <see cref="T:IFiniteStateMachine`1"/> and an index
 /// that is part of a strongly connected group in the finite state machine.
 /// </summary>
 /// <returns>A 2d-matrix that contains the influence matrix of the strongly connected group.</returns>
 /// <param name="fsm">The given finite state machine to generate the influence matrix from.</param>
 /// <param name="strongIndex">The initial index to generate an influence matrix from.</param>
 /// <remarks>
 /// <para>The given initial index must be part of a strongly connected group. If the index is not part,
 /// the algorithm will loop.</para>
 /// </remarks>
 public void GenerateInfluenceMatrix(IFiniteStateMachine<int> fsm, int strongIndex)
 {
     int n = fsm.Length;
     int s = this.Length;
     int o = this.OutputSize;
     double[] trans = new double[s * s];
     double[,] a = this.a, b = this.b;
     double[] ch1 = new double[s], ch2 = new double[s], cht;
     int idx, otp, j, i;
     double sum;
     for (int ori = 0x00; ori < s; ori++) {
         for (j = 0x00; j < ori; j++) {
             ch2 [j] = 0.0d;
         }
         ch2 [j] = 1.0d;
         for (j++; j < s; j++) {
             ch2 [j] = 0.0d;
         }
         idx = strongIndex;
         do {
             cht = ch1;
             ch1 = ch2;
             ch2 = cht;
             otp = fsm.GetOutput (idx);
             for (j = 0x00; j < s; j++) {
                 sum = 0.0d;
                 for (i = 0x00; i < s; i++) {
                     sum += ch1 [i] * a [i, j];
                 }
                 sum *= b [j, otp];
                 ch2 [j] = sum;
             }
             idx = fsm.GetTransitionOfIndex (idx);
         } while(idx != strongIndex);
         for (j = 0x00, i = ori; j < s; i += s, j++) {
             trans [i] = ch2 [j];
         }
     }
 }