void BoxPlus(tLLRPair* L1, tLLRPair* L2, tLLRPair* Res, unsigned Len_1) { double tmp = LogSum(0, L1[1] + L2[1]); for (unsigned i = 2; i <= Len_1; ++i) tmp = LogSum(tmp, L1[i] + L2[i]); Res[0] = 0; for (unsigned i = 1; i <= Len_1; ++i) { Res[i] = LogSum(L2[i], L1[1] + L2[i ^ 1]); for (unsigned j = 2; j <= Len_1; ++j) Res[i] = LogSum(Res[i], L1[j] + L2[i ^ j]); Res[i] -= tmp; } }
float LogSumVec(const std::vector<float>& logvec) { float sum = 0.; sum = logvec[0]; for (int i = 1; i < logvec.size(); ++i) { sum = LogSum(sum, logvec[i]); } return sum; }
/**** phi: dimensions is doc_id, matrix is topic * doc_size z_bar: topic*doc_id ****/ void VarRTM::Infer(CorpusC &cor, RTMC &m, RTMVar* var) const { var->Init(cor, m); for(int it = 1; it < var_max_iter_; ++it) { for (size_t d = 0; d < cor.Len(); d++) { for(int it2 = 1; it2 < doc_var_max_iter_; ++it2) { Vec vec(m.TopicNum()); vec.setZero(); for (SpMatInIt it(net, d); it; ++it) { Vec pi = var->z_bar.col(d).cwiseProduct(var->z_bar.col(it.index())); vec += (1 - Sigmoid(m.eta.dot(pi)))*var->z_bar.col(it.index()); } Vec gradient = vec.cwiseProduct(m.eta); gradient /= cor.TLen(d); //every word is considered to be different Vec expect_theta; ExpectTheta(var->gamma.col(d), &expect_theta); for (size_t n = 0; n < cor.ULen(d); n++) { for (int k = 0; k < m.TopicNum(); k++) { (var->phi)[d](k, n) = expect_theta[k] + m.ln_w(k, cor.Word(d, n)) + gradient[k]; } double ln_phi_sum = LogSum((var->phi)[d].col(n)); for (int k = 0; k < m.TopicNum(); k++) { //normalize phi (var->phi)[d](k, n) = exp((var->phi)[d](k, n) - ln_phi_sum); } } var->gamma.setConstant(m.alpha); for (size_t n = 0; n < cor.ULen(d); n++) { for (int k = 0; k < m.TopicNum(); k++) { var->gamma(k, d) += cor.Count(d, n) * (var->phi)[d](k, n); } } var->z_bar.col(d) = ZBar(cor.docs[d], var->phi[d]); } } } }
double VarMGCTM::Infer(DocC &doc, MGCTMC &m, MGVar* para) const { double c = 1; InitVar(doc, m, para); MGVar &p = *para; for(int it = 1; (c > converged_.var_converged_) && (it < converged_.var_max_iter_); ++it) { //indicate variable eta Vec g_theta_ep; GThetaEp(p.g_theta, &g_theta_ep); Mat l_theta_ep; LThetaEp(p.l_theta, &l_theta_ep); for (int j = 0; j < m.LTopicNum1(); j++) { p.eta[j] = log(m.pi[j]); int l_topic_num = m.LTopicNum2(); p.eta[j] += lgamma(l_topic_num*m.l_alpha[j]); p.eta[j] -= l_topic_num*lgamma(m.l_alpha[j]); for (int k = 0; k < m.LTopicNum2(); k++) { p.eta[j] += (m.l_alpha[j] - 1)*l_theta_ep(k, j); } for (size_t n = 0; n < doc.ULen(); n++) { double a = 0; for (int k = 0; k < m.LTopicNum2(); k++) { a += p.l_z[j](k, n) * l_theta_ep(k, j); a += p.l_z[j](k, n) * m.l_ln_w[j](k, doc.Word(n)); } p.eta[j] += p.delta[n]*a*doc.Count(n); } } double ln_eta_sum = LogSum(p.eta); for (int j = 0; j < m.LTopicNum1(); j++) { //normalize eta p.eta[j] = exp(p.eta[j] - ln_eta_sum); } //omega p.omega[1] = m.gamma[1]; for (size_t n = 0; n < doc.ULen(); n++) { p.omega[1] += p.delta(n)*doc.Count(n); } p.omega[0] = m.gamma[0]; for (size_t n = 0; n < doc.ULen(); n++) { p.omega[0] += (1 - p.delta(n))*doc.Count(n); } //local theta for (int j = 0; j < m.LTopicNum1(); j++) { for (int k = 0; k < m.LTopicNum2(); k++) { p.l_theta(k, j) = p.eta[j] * m.l_alpha[j]; } } for (int j = 0; j < m.LTopicNum1(); j++) { for (int k = 0; k < m.LTopicNum2(); k++) { for (size_t n = 0; n < doc.ULen(); n++) { p.l_theta(k, j) += doc.Count(n)* p.delta[n]*p.eta[j]* p.l_z[j](k, n); } p.l_theta(k, j) += 1 - p.eta[j]; } } //global theta p.g_theta.setConstant(m.g_alpha); for (size_t n = 0; n < doc.ULen(); n++) { for (int k = 0; k < m.GTopicNum(); k++) { p.g_theta[k] += doc.Count(n) * p.g_z(k, n) * (1 - p.delta[n]); } } for (size_t n = 0; n < doc.ULen(); n++) { //variable delta double tmp = DiGamma(m.gamma[1]) - DiGamma(m.gamma[0]); for (int j = 0; j < m.LTopicNum1(); j++) { for (int k = 0; k < m.LTopicNum2(); k++) { tmp += p.eta[j]*p.l_z[j](k, n)*l_theta_ep(k,j); tmp += p.eta[j]*p.l_z[j](k, n)*m.l_ln_w[j](k, doc.Word(n)); } } for (int k = 0; k < m.GTopicNum(); k++) { tmp -= p.g_z(k, n) * g_theta_ep[k]; tmp -= p.g_z(k, n) * m.g_ln_w(k, doc.Word(n)); } p.delta[n] = Sigmoid(tmp); //local z for (int j = 0; j < m.LTopicNum1(); j++) { for (int k = 0; k < m.LTopicNum2(); k++) { p.l_z[j](k, n) = p.delta[n]*p.eta[j]*(l_theta_ep(k, j) + m.l_ln_w[j](k, doc.Word(n))); } double ln_local_z_sum = LogSum(p.l_z[j].col(n)); for (int k = 0; k < m.LTopicNum2(); k++) { p.l_z[j](k, n) = exp(p.l_z[j](k, n) - ln_local_z_sum); } } //global z for (int k = 0; k < m.GTopicNum(); k++) { p.g_z(k, n) = (1 - p.delta[n])*(g_theta_ep[k] + m.g_ln_w(k, doc.Word(n))); } double ln_z_sum = LogSum(p.g_z.col(n)); for (int k = 0; k < m.GTopicNum(); k++) { //normalize g_z p.g_z(k, n) = exp(p.g_z(k, n) - ln_z_sum); } } } return Likelihood(doc, p, m); }
/* Function: P7Logoddsify() * * Purpose: Take an HMM with valid probabilities, and * fill in the integer log-odds score section of the model. * * Notes on log-odds scores: * type of parameter probability score * ----------------- ----------- ------ * any emission p_x log_2 p_x/null_x * N,J,C /assume/ p_x = null_x so /always/ score zero. * transition to emitters t_x log_2 t_x/p1 * (M,I; N,C; J) * NN and CC loops are often equal to p1, so usu. score zero. * C->T transition t_x log_2 t_x/p2 * often zero, usu. C->T = p2. * all other transitions t_x log_2 t_x * (no null model counterpart, so null prob is 1) * * Notes on entry/exit scores, B->M and M->E: * The probability form model includes delete states 1 and M. * these states are removed from a search form model to * prevent B->D...D->E->J->B mute cycles, which would complicate * dynamic programming algorithms. The data-independent * S/W B->M and M->E transitions are folded together with * data-dependent B->D...D->M and M->D...D->E paths. * * This process is referred to in the code as "wing folding" * or "wing retraction"... the analogy is to a swept-wing * fighter in landing vs. high speed flight configuration. * * Note on Viterbi vs. forward flag: * Wing retraction must take forward vs. Viterbi * into account. If forward, sum two paths; if Viterbi, take * max. I tried to slide this by as a sum, without * the flag, but Alex detected it as a bug, because you can * then find cases where the Viterbi score doesn't match * the P7TraceScore(). * * Args: hmm - the hmm to calculate scores in. * viterbi_mode - TRUE to fold wings in Viterbi configuration. * * Return: (void) * hmm scores are filled in. */ void P7Logoddsify(struct plan7_s *hmm, int viterbi_mode) { int k; /* counter for model position */ int x; /* counter for symbols */ float accum; float tbm, tme; if (hmm->flags & PLAN7_HASBITS) return; /* Symbol emission scores */ for (k = 1; k <= hmm->M; k++) { /* match/insert emissions in main model */ for (x = 0; x < Alphabet_size; x++) { hmm->msc[x][k] = Prob2Score(hmm->mat[k][x], hmm->null[x]); if (k < hmm->M) hmm->isc[x][k] = Prob2Score(hmm->ins[k][x], hmm->null[x]); } /* degenerate match/insert emissions */ for (x = Alphabet_size; x < Alphabet_iupac; x++) { hmm->msc[x][k] = DegenerateSymbolScore(hmm->mat[k], hmm->null, x); if (k < hmm->M) hmm->isc[x][k] = DegenerateSymbolScore(hmm->ins[k], hmm->null, x); } } /* State transitions. * * A note on "folding" of D_1 and D_M. * These two delete states are folded out of search form models * in order to prevent null cycles in the dynamic programming * algorithms (see code below). However, we use their log transitions * when we save the model! So the following log transition probs * are used *only* in save files, *never* in search algorithms: * log (tbd1), D1 -> M2, D1 -> D2 * Mm-1 -> Dm, Dm-1 -> Dm * * In a search algorithm, these have to be interpreted as -INFTY * because their contributions are folded into bsc[] and esc[] * entry/exit scores. They can't be set to -INFTY here because * we need them in save files. */ for (k = 1; k < hmm->M; k++) { hmm->tsc[k][TMM] = Prob2Score(hmm->t[k][TMM], hmm->p1); hmm->tsc[k][TMI] = Prob2Score(hmm->t[k][TMI], hmm->p1); hmm->tsc[k][TMD] = Prob2Score(hmm->t[k][TMD], 1.0); hmm->tsc[k][TIM] = Prob2Score(hmm->t[k][TIM], hmm->p1); hmm->tsc[k][TII] = Prob2Score(hmm->t[k][TII], hmm->p1); hmm->tsc[k][TDM] = Prob2Score(hmm->t[k][TDM], hmm->p1); hmm->tsc[k][TDD] = Prob2Score(hmm->t[k][TDD], 1.0); } /* B->M entry transitions. Note how D_1 is folded out. * M1 is just B->M1 * M2 is sum (or max) of B->M2 and B->D1->M2 * M_k is sum (or max) of B->M_k and B->D1...D_k-1->M_k * These have to be done in log space, else you'll get * underflow errors; and we also have to watch for log(0). * A little sloppier than it probably has to be; historically, * doing in this in log space was in response to a bug report. */ accum = hmm->tbd1 > 0.0 ? log(hmm->tbd1) : -9999.; for (k = 1; k <= hmm->M; k++) { tbm = hmm->begin[k] > 0. ? log(hmm->begin[k]) : -9999.; /* B->M_k part */ /* B->D1...D_k-1->M_k part we get from accum*/ if (k > 1 && accum > -9999.) { if (hmm->t[k-1][TDM] > 0.0) { if (viterbi_mode) tbm = MAX(tbm, accum + log(hmm->t[k-1][TDM])); else tbm = LogSum(tbm, accum + log(hmm->t[k-1][TDM])); } accum = (hmm->t[k-1][TDD] > 0.0) ? accum + log(hmm->t[k-1][TDD]) : -9999.; } /* Convert from log_e to scaled integer log_2 odds. */ if (tbm > -9999.) hmm->bsc[k] = (int) floor(0.5 + INTSCALE * 1.44269504 * (tbm - log(hmm->p1))); else hmm->bsc[k] = -INFTY; } /* M->E exit transitions. Note how D_M is folded out. * M_M is 1 by definition * M_M-1 is sum of M_M-1->E and M_M-1->D_M->E, where D_M->E is 1 by definition * M_k is sum of M_k->E and M_k->D_k+1...D_M->E * Must be done in log space to avoid underflow errors. * A little sloppier than it probably has to be; historically, * doing in this in log space was in response to a bug report. */ hmm->esc[hmm->M] = 0; accum = 0.; for (k = hmm->M-1; k >= 1; k--) { tme = hmm->end[k] > 0. ? log(hmm->end[k]) : -9999.; if (accum > -9999.) { if (hmm->t[k][TMD] > 0.0) { if (viterbi_mode) tme = MAX(tme, accum + log(hmm->t[k][TMD])); else tme = LogSum(tme, accum + log(hmm->t[k][TMD])); } accum = (hmm->t[k][TDD] > 0.0) ? accum + log(hmm->t[k][TDD]) : -9999.; } /* convert from log_e to scaled integer log odds. */ hmm->esc[k] = (tme > -9999.) ? (int) floor(0.5 + INTSCALE * 1.44269504 * tme) : -INFTY; } /* special transitions */ hmm->xsc[XTN][LOOP] = Prob2Score(hmm->xt[XTN][LOOP], hmm->p1); hmm->xsc[XTN][MOVE] = Prob2Score(hmm->xt[XTN][MOVE], 1.0); hmm->xsc[XTE][LOOP] = Prob2Score(hmm->xt[XTE][LOOP], 1.0); hmm->xsc[XTE][MOVE] = Prob2Score(hmm->xt[XTE][MOVE], 1.0); hmm->xsc[XTC][LOOP] = Prob2Score(hmm->xt[XTC][LOOP], hmm->p1); hmm->xsc[XTC][MOVE] = Prob2Score(hmm->xt[XTC][MOVE], 1.-hmm->p1); hmm->xsc[XTJ][LOOP] = Prob2Score(hmm->xt[XTJ][LOOP], hmm->p1); hmm->xsc[XTJ][MOVE] = Prob2Score(hmm->xt[XTJ][MOVE], 1.0); hmm->flags |= PLAN7_HASBITS; /* raise the log-odds ready flag */ }