private double[,] LogSpaceGamma(int[] O, double[,] logAlpha, double[,] logBeta) { int N = states; int M = observationSymbols; int T = O.Length; var logGamma = new double[T, N]; #region Calculating digamma and gamma for (int t = 0; t < T; t++) { double normalizer = MathE.LOGZERO; for (int i = 0; i < N; i++) { logGamma[t, i] = MathE.elnproduct(logAlpha[t, i], logBeta[t, i]); normalizer = MathE.elnsum(normalizer, logGamma[t, i]); } for (int i = 0; i < N; i++) { logGamma[t, i] = MathE.elnproduct(logGamma[t, i], -normalizer); } } #endregion return(logGamma); }
private double[, ,] LogSpaceEta(int[] O, double[,] logAlpha, double[,] logBeta) { int N = states; int M = observationSymbols; int T = O.Length; var logEta = new double[T, N, N]; #region Calculating digamma and gamma for (int t = 0; t < T - 1; t++) { double normalizer = MathE.LOGZERO; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { //logEta[t, i, j] = MathE.elnproduct(logAlpha[t, i], MathE.elnproduct(MathE.eln(transition[i, j]), // MathE.elnproduct(MathE.eln(emission[j, O[t + 1]]), logBeta[t + 1, j]))); /*logEta[t, i, j] = MathE.elnproduct(logAlpha[t, i], MathE.elnproduct(logTransition[i, j], * MathE.elnproduct(logEmission[j, O[t + 1]], logBeta[t + 1, j]))); */ logEta[t, i, j] = MathE.elnproduct(logAlpha[t, i], logTransition[i, j], logEmission[j, O[t + 1]], logBeta[t + 1, j]); normalizer = MathE.elnsum(normalizer, logEta[t, i, j]); } } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { logEta[t, i, j] = MathE.elnproduct(logEta[t, i, j], -normalizer); } } } #endregion return(logEta); }
// ln(b_t(i)) private double[,] LogSpaceBackward(int[] O) { int N = states; int M = observationSymbols; int T = O.Length; var logBeta = new double[T, N]; #region Beta Pass for (int i = 0; i < N; i++) { logBeta[T - 1, i] = 0; } // Beta pass for (int t = T - 2; t >= 0; t--) { for (int i = 0; i < N; i++) { double logbeta = MathE.LOGZERO; for (int j = 0; j < N; j++) { // logbeta = MathE.elnsum(logbeta, MathE.elnproduct(MathE.eln(transition[i, j]), // MathE.elnproduct(emission[j, O[t + 1]], logBeta[t + 1, j]))); // mISTAKE ??? MathE.elnproduct(emission[j, O[t + 1]],... logbeta = MathE.elnsum(logbeta, MathE.elnproduct(logTransition[i, j], MathE.elnproduct(logEmission[j, O[t + 1]], logBeta[t + 1, j]))); } logBeta[t, i] = logbeta; } } #endregion return(logBeta); }
// ln(a_t(i)) private double[,] LogSpaceForward(int[] O) { int N = states; int M = observationSymbols; int T = O.Length; var logAlpha = new double[T, N]; #region Alpha Pass for (int i = 0; i < N; i++) { //logAlpha[0, i] = MathE.elnproduct(MathE.eln(pi[i]), MathE.eln(emission[i, O[0]])); logAlpha[0, i] = MathE.elnproduct(logPi[i], logEmission[i, O[0]]); } //compute a_t(i) for (int t = 1; t < T; t++) { for (int i = 0; i < N; i++) { double logalpha = MathE.LOGZERO; //alpha[t, i] = 0; for (int j = 0; j < N; j++) { //logalpha = MathE.elnsum(logalpha, MathE.elnproduct(logAlpha[t - 1, j], MathE.eln(transition[j, i]))); logalpha = MathE.elnsum(logalpha, MathE.elnproduct(logAlpha[t - 1, j], logTransition[j, i])); } // logAlpha[t, i] = MathE.elnproduct(logalpha, MathE.eln(emission[i, O[t]])); logAlpha[t, i] = MathE.elnproduct(logalpha, logEmission[i, O[t]]); } } return(logAlpha); #endregion }
private void UpdateModel(int[][] Obs) { int N = states; int M = observationSymbols; int K = Obs.GetLength(0); Dictionary <int, double[, ]> alphas = new Dictionary <int, double[, ]>(); Dictionary <int, double[, ]> betas = new Dictionary <int, double[, ]>(); Dictionary <int, double[, ]> gammas = new Dictionary <int, double[, ]>(); Dictionary <int, double[, , ]> etas = new Dictionary <int, double[, , ]>(); for (int k = 0; k < K; k++) { int[] O = Obs[k]; int T = O.Length; var logAlpha = LogSpaceForward(O); var logBeta = LogSpaceBackward(O); var logGamma = LogSpaceGamma(O, logAlpha, logBeta); var logEta = LogSpaceEta(O, logAlpha, logBeta); alphas[k] = logAlpha; betas[k] = logBeta; gammas[k] = logGamma; etas[k] = logEta; } #region Re-estimation of parameters // re-sestimate pi for (int i = 0; i < N; i++) { double logpi = MathE.LOGZERO; for (int k = 0; k < K; k++) { var logGamma = gammas[k]; int T = Obs[k].Length; logpi = MathE.elnsum(logpi, logGamma[0, i]); } logPi[i] = MathE.elnproduct(logpi, -K); } // re-estimate A for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { double numer = MathE.LOGZERO; double denom = MathE.LOGZERO; for (int k = 0; k < K; k++) { var logEta = etas[k]; var logGamma = gammas[k]; int T = Obs[k].Length; for (int t = 0; t < T - 1; t++) { numer = MathE.elnsum(numer, logEta[t, i, j]); denom = MathE.elnsum(denom, logGamma[t, i]); } } logTransition[i, j] = MathE.elnproduct(numer, -denom); } } // re-estimate B for (int j = 0; j < N; j++) { for (int ki = 0; ki < M; ki++) { double numer = MathE.LOGZERO; double denom = MathE.LOGZERO; for (int k = 0; k < K; k++) { var logEta = etas[k]; var logGamma = gammas[k]; int T = Obs[k].Length; for (int t = 0; t < T; t++) { if (Obs[k][t] == ki) { numer = MathE.elnsum(numer, logGamma[t, j]); } denom = MathE.elnsum(denom, logGamma[t, j]); } } logEmission[j, ki] = MathE.elnproduct(numer, -denom); } } #endregion }