/// <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]; } } }
/// <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]; } } }