double BM::Loglike(const Vector &probvec, Vec &g, Mat &h, uint nd)const{ if (probvec.size() != 1) { report_error("Wrong size argument."); } double p = probvec[0]; if (p < 0 || p > 1) { return negative_infinity(); } double logp = log(p); double logp2 = log(1-p); double ntrials = n_ * suf()->nobs(); double success = n_*suf()->sum(); double fail = ntrials - success; double ans = success * logp + fail * logp2; if(nd>0){ double q = 1-p; g[0] = (success - p*ntrials)/(p*q); if(nd>1){ h(0,0) = -1*(success/(p*p) + fail/(q*q)); } } return ans; }
double BLSSS::log_model_prob(const Selector &g)const{ // borrowed from MLVS.cpp double num = vpri_->logp(g); if(num==BOOM::negative_infinity() || g.nvars() == 0) { // If num == -infinity then it is in a zero support point in the // prior. If g.nvars()==0 then all coefficients are zero // because of the point mass. The only entries remaining in the // likelihood are sums of squares of y[i] that are independent // of g. They need to be omitted here because they are omitted // in the non-empty case below. return num; } SpdMatrix ivar = g.select(pri_->siginv()); num += .5*ivar.logdet(); if(num == BOOM::negative_infinity()) return num; Vector mu = g.select(pri_->mu()); Vector ivar_mu = ivar * mu; num -= .5*mu.dot(ivar_mu); bool ok=true; ivar += g.select(suf().xtx()); Mat L = ivar.chol(ok); if(!ok) return BOOM::negative_infinity(); double denom = sum(log(L.diag())); // = .5 log |ivar| Vec S = g.select(suf().xty()) + ivar_mu; Lsolve_inplace(L,S); denom-= .5*S.normsq(); // S.normsq = beta_tilde ^T V_tilde beta_tilde return num-denom; }
// The likelihood is \prod root(2pi)^-d |siginv|^{n/2} exp{-1/2 * trace(qform)} double MvReg::log_likelihood_ivar(const Matrix &Beta, const SpdMatrix &Siginv) const { double qform = trace(suf()->SSE(Beta) * Siginv); double n = suf()->n(); double normalizing_constant = -.5 * (n * ydim()) * Constants::log_2pi; return normalizing_constant + .5 * n * Siginv.logdet() - .5 * qform; }
double ExponentialModel::Loglike(const Vector &lambda_vector, Vector &g, Matrix &h, uint nd) const { if (lambda_vector.size() != 1) { report_error("Wrong size argument."); } double lam = lambda_vector[0]; double ans = 0; if (lam <= 0) { ans = negative_infinity(); if (nd > 0) { g[0] = std::max(fabs(lam), .10); if (nd > 1) { h(0, 0) = -1; } } return ans; } double n = suf()->n(); double sum = suf()->sum(); ans = n * log(lam) - lam * sum; if (nd > 0) { g[0] = n / lam - sum; if (nd > 1) { h(0, 0) = -n / (lam * lam); } } return ans; }
void ZMMM::mle(){ double n = suf()->n(); if(n < 1) { report_error("Too few degrees of freedom to compute ML in " "ZeroMeanGaussianModel::mle()"); } set_Sigma( suf()->center_sumsq(mu_) / (n-1)); }
void PoissonModel::mle() { double n = suf()->n(); double s = suf()->sum(); if (n > 0) set_lam(s / n); else set_lam(1.0); }
double UM::loglike(const Vector &ab) const { double lo = ab[0]; double hi = ab[1]; bool hi_ok = suf()->hi() <= hi; bool lo_ok = suf()->lo() >= lo; if (hi_ok && lo_ok) return log(nc()); return BOOM::negative_infinity(); }
void LSB::draw_beta_given_gamma(){ const Selector & inc(mod_->inc()); Ominv = inc.select(pri_->siginv()); Spd ivar = Ominv + inc.select(suf()->xtx()); Vec b = inc.select(suf()->xty()) + Ominv * inc.select(pri_->mu()); b = rmvn_suf(ivar, b); mod_->set_included_coefficients(b); }
double MvReg::log_likelihood(const Matrix &Beta, const SpdMatrix &Sigma) const { Cholesky Sigma_cholesky(Sigma); double qform = trace(suf()->SSE(Beta) * Sigma_cholesky.inv()); double ldsi = -1 * Sigma_cholesky.logdet(); double n = suf()->n(); double normalizing_constant = -.5 * (n * ydim()) * Constants::log_2pi; return normalizing_constant + .5 * n * ldsi - .5 * qform; }
// Log likelihood when beta is empty, so that xbeta = 0. In this // case the only parameter is sigma^2 double RM::empty_loglike(Vector &g, Matrix &h, uint nd)const{ double v = sigsq(); double n = suf()->n(); double ss = suf()->yty(); const double log2pi = 1.83787706640935; double ans = -.5*n*(log2pi + log(v)) - .5*ss/v; if(nd > 0){ double v2 = v*v; g[0] = -.5*n/v + .5*ss/v2; if(nd > 1){ h(0,0) = .5*n/v2 - ss/(v2*v); } } return ans; }
double ZMMM::loglike()const{ const double log2pi = 1.83787706641; double dim = mu_.size(); double n = suf()->n(); const Vec ybar = suf()->ybar(); const Spd sumsq = suf()->center_sumsq(); double qform = n*(siginv().Mdist(ybar)); qform+= traceAB(siginv(), sumsq); double nc = 0.5*n*( -dim*log2pi + ldsi()); double ans = nc - .5*qform; return ans; }
//====================================================================== void ArStateModel::observe_state(const ConstVectorView then, const ConstVectorView now, int t){ double y = now[0]; const ConstVectorView &x(then); suf()->add_mixture_data(y, x, 1.0); }
double WeightedMvnModel::loglike(const Vector &mu_siginv_triangle)const{ const double log2pi = 1.83787706641; const ConstVectorView mu(mu_siginv_triangle, 0, dim()); SpdMatrix siginv(dim()); Vector::const_iterator it = mu_siginv_triangle.begin() + dim(); siginv.unvectorize(it, true); double ldsi = siginv.logdet(); double sumlogw = suf()->sumlogw(); const SpdMatrix sumsq = suf()->center_sumsq(); double n = suf()->n(); double ans = n*.5*(log2pi + ldsi) + dim() * .5 *sumlogw; ans -= -.5*traceAB(siginv, suf()->center_sumsq(mu)); return ans; }
double MGSS::loglike(const Vector &mu_ominv)const{ const ConstVectorView mu(mu_ominv, 0, dim()); SpdMatrix siginv(dim()); Vector::const_iterator b(mu_ominv.cbegin() + dim()); siginv.unvectorize(b, true); siginv /= sigsq(); return MvnBase::log_likelihood(Vector(mu), siginv, *suf()); }
double WishartModel::Loglike(const Vector &sumsq_triangle_nu, Vector &g, uint nd)const{ const double log2 = 0.69314718055994529; const double logpi = 1.1447298858494002; int k=dim(); SpdParams Sumsq_arg(dim()); Vector::const_iterator it = Sumsq_arg.unvectorize(sumsq_triangle_nu, true); double nu = *it; const SpdMatrix &SS(Sumsq_arg.var()); if(nu <k) return negative_infinity(); double ldSS = 0; bool ok=true; ldSS = SS.logdet(ok); if(!ok) return negative_infinity(); double n = suf()->n(); double sumldw = suf()->sumldw(); const SpdMatrix &sumW(suf()->sumW()); double tab = traceAB(SS, sumW); double tmp1(0), tmp2(0); for(int i = 1; i<=k; ++i){ double tmp = .5*(nu-i+1); tmp1+= lgamma(tmp); if(nd>0) tmp2+= digamma(tmp); } double ans = .5*( n*(-nu*k*log2 - .5*k*(k-1)*logpi -2*tmp1 + nu*ldSS) +(nu-k-1)*sumldw - tab); if(nd>0){ double dnu = .5*( n*(-k*log2 - tmp2+ldSS) + sumldw); SpdMatrix SSinv(SS.inv()); int m=0; for(int i=0; i<k; ++i){ for(int j=0; j<=i; ++j){ g[m] = .5*n*nu * (i==j? SSinv(i,i) : 2*SSinv(i,j)); g[m] -= .5*(i==j ? sumW(i,i) : 2* sumW(i,j)); ++m; }} g[m] = dnu; } return ans; }
void BLSSS::draw_beta() { Selector g = m_->coef().inc(); if(g.nvars() == 0) { m_->drop_all(); return; } SpdMatrix ivar = g.select(pri_->siginv()); Vector ivar_mu = ivar * g.select(pri_->mu()); ivar += g.select(suf().xtx()); ivar_mu += g.select(suf().xty()); Vector b = ivar.solve(ivar_mu); b = rmvn_ivar(b, ivar); // If model selection is turned off and some elements of beta // happen to be zero (because, e.g., of a failed MH step) we don't // want the dimension of beta to change. m_->set_included_coefficients(b, g); }
double ZGM::Loglike(const Vector &sigsq_vec, Vector &g, Matrix &h, uint nd)const{ double sigsq = sigsq_vec[0]; if(sigsq<0) return BOOM::negative_infinity(); const double log2pi = 1.8378770664093453; double n = suf()->n(); double sumsq = suf()->sumsq(); double SS = sumsq; double ans = -0.5*(n*(log2pi + log(sigsq)) + SS/sigsq); if(nd>0){ double sigsq_sq = sigsq*sigsq; g[0] = -0.5*n/sigsq + 0.5*SS/sigsq_sq; if(nd>1) h(0,0) = (n/2 - SS/sigsq)/sigsq_sq; } return ans; }
double PDM::loglike(const Vector &Nu_columns) const { Matrix Nu(dim(), dim(), Nu_columns.data()); const Matrix &sumlog(suf()->sumlog()); double n = suf()->n(); double ans = 0; for (uint i = 0; i < nrow(Nu); ++i) ans += dirichlet_loglike(Nu.row(i), 0, 0, sumlog.row(i), n); return ans; }
MarkovModel::MarkovModel(const std::vector<std::string> &sdata) : DataPolicy(new MarkovSuf(number_of_unique_elements(sdata))) { uint S = suf()->state_space_size(); NEW(TPM, Q1)(S); NEW(VectorParams, Pi0)(S); ParamPolicy::set_params(Q1, Pi0); Ptr<MarkovDataSeries> ts = make_markov_data(sdata); add_data_series(ts); mle(); }
void RWHSM::observe_state(const ConstVectorView then, const ConstVectorView now, int time_now){ Date today = time_zero_ + time_now; if(holiday_->active(today)){ Date holiday_date = holiday_->nearest(today); int position = today - holiday_->earliest_influence(holiday_date); double delta = now[position] - then[position]; suf()->update_raw(delta); } }
Suffix::Encoding get_encoding(const string& s) // try to deduce type from file name using a lookup table { static int x = init_suffix_map(); string::const_iterator p = find(s.begin(),s.end(),'.'); if (p==s.end()) return Suffix::none; // no suffix string suf(p+1,s.end()); return suffix_map[suf]; }
void RM::use_normal_equations(){ RegSuf *s = suf().get(); NeRegSuf *rs = dynamic_cast<NeRegSuf *>(s); if (rs) return; Ptr<NeRegSuf> ne_reg_suf(new NeRegSuf( s->xtx(), s->xty(), s->yty(), s->n(), s->xbar())); reset_suf_ptr(ne_reg_suf); }
void MarkovModel::mle(){ Mat Q(this->Q()); for(uint i=0; i< Q.nrow(); ++i){ Vec tmp(suf()->trans().row(i)); Q.set_row(i, tmp/tmp.sum());} set_Q(Q); if(pi0_status==Free){ const Vec &tmp(suf()->init()); set_pi0(tmp/sum(tmp)); }else if(pi0_status==Stationary){ set_pi0(get_stat_dist(Q)); } }
double BM::Loglike(const Vector &ab, Vec &g, Mat &h, uint nd) const{ if (ab.size() != 2) { report_error("Wrong size argument."); } double alpha = ab[0]; double beta = ab[1]; if (alpha <= 0 || beta <= 0) { if (nd > 0) { g[0] = (alpha <= 0) ? 1.0 : 0.0; g[1] = (beta <= 0) ? 1.0 : 0.0; if (nd > 1) { h = 0.0; h.diag() = -1.0; } } return negative_infinity(); } double n = suf()->n(); double sumlog = suf()->sumlog(); double sumlogc = suf()->sumlogc(); double ans = n*(lgamma(alpha + beta) - lgamma(alpha)-lgamma(beta)); ans += (alpha-1)*sumlog + (beta-1)*sumlogc; if(nd>0){ double psisum = digamma(alpha + beta); g[0] = n*(psisum-digamma(alpha)) + sumlog; g[1] = n*(psisum-digamma(beta)) + sumlogc; if(nd>1){ double trisum = trigamma(alpha+beta); h(0,0) = n*(trisum - trigamma(alpha)); h(0,1) = h(1,0) = n*trisum; h(1,1) = n*(trisum - trigamma(beta));}} return ans; }
void HierarchicalGammaModel::get_initial_parameter_estimates( const Ptr<GammaModel> &data_model) const { try { data_model->mle(); } catch (...) { double a = 1; double b = 1; Ptr<GammaSuf> suf(data_model->suf()); if (suf->n() > 0) { double mean = suf->sum() / suf->n(); b = 1.0 / mean; } data_model->set_shape_and_scale(a, b); } }
//---------------------------------------------------------------------- double LSB::log_model_prob(const Selector &g)const{ double num = vs_->logp(g); if(num==BOOM::negative_infinity()) return num; Ominv = g.select(pri_->siginv()); num += .5*Ominv.logdet(); if(num == BOOM::negative_infinity()) return num; Vec mu = g.select(pri_->mu()); Vec Ominv_mu = Ominv * mu; num -= .5*mu.dot(Ominv_mu); bool ok=true; iV_tilde_ = Ominv + g.select(suf()->xtx()); Mat L = iV_tilde_.chol(ok); if(!ok) return BOOM::negative_infinity(); double denom = sum(log(L.diag())); // = .5 log |Ominv| Vec S = g.select(suf()->xty()) + Ominv_mu; Lsolve_inplace(L,S); denom-= .5*S.normsq(); // S.normsq = beta_tilde ^T V_tilde beta_tilde return num-denom; }
double PoissonModel::Loglike(const Vector &lambda_vector, Vec &g, Mat &h, uint nd)const{ if (lambda_vector.size() != 1) { report_error("Wrong size argument."); } double lam = lambda_vector[0]; if (lam < 0) { return negative_infinity(); } Ptr<PoissonSuf> s = suf(); double sm = s->sum(); double n = s->n(); double ans = sm*log(lam) - n*lam - s->lognc(); if(nd>0){ g[0] = sm/lam-n; if(nd>1) h(0,0) = -sm/(lam*lam); } return ans; }
//====================================================================== double DirichletModel::Loglike(const Vector &nu, Vector &g, Matrix &h, uint nd) const { /* returns log likelihood for the parameters of a Dirichlet distribution with sufficient statistic sumlogpi(lo..hi). If pi(1)(lo..hi)..pi(nobs)(lo..hi) are probability vectors, then sumlogpi(j) = sum_i log(pi(i,j)) if(nd>0) then the g(lo..hi) is filled with the gradient (with respect to nu). If nd>1 then hess(lo..hi)(lo..hi) is filled with the hessian (wrt nu). Otherwise the algorithm can be called with either g or hess = 0. */ const Vector &sumlogpi(suf()->sumlog()); double nobs = suf()->n(); Vector *G(nd > 0 ? &g : nullptr); Matrix *H(nd > 1 ? &h : nullptr); return dirichlet_loglike(nu, G, H, sumlogpi, nobs); }
double PDM::dloglike(const Vector &Nu_columns, Vector &g) const { Matrix Nu(dim(), dim(), Nu_columns.data()); const Matrix &sumlog(suf()->sumlog()); double n = suf()->n(); uint nr = nrow(Nu); Matrix G(nr, nr); Vector g_row(nr); double ans = 0; for (uint i = 0; i < nrow(Nu); ++i) { ans += dirichlet_loglike(Nu.row(i), &g_row, 0, sumlog.row(i), n); G.row(i) = g_row; } G = G.transpose(); g.assign(G.begin(), G.end()); // need to check that g is vectorized in the right way.. virtual // functions might expect columns instead of rows. return ans; }
double RM::Loglike(const Vector &sigsq_beta, Vector &g, Matrix &h, uint nd)const{ const double log2pi = 1.83787706640935; const double sigsq = sigsq_beta[0]; const Vector b(ConstVectorView(sigsq_beta, 1)); double n = suf()->n(); if(b.size()==0) return empty_loglike(g, h, nd); double SSE = yty() - 2*b.dot(xty()) + xtx().Mdist(b); double ans = -.5*(n * log2pi + n *log(sigsq)+ SSE/sigsq); if(nd>0){ // sigsq derivs come first in CP2 vectorization SpdMatrix xtx = this->xtx(); Vector gbeta = (xty() - xtx*b)/sigsq; double sig4 = sigsq*sigsq; double gsigsq = -n/(2*sigsq) + SSE/(2*sig4); g = concat(gsigsq, gbeta); if(nd>1){ double h11 = .5*n/sig4 - SSE/(sig4*sigsq); h = unpartition(h11, (-1/sigsq)*gbeta, (-1/sigsq)*xtx);}} return ans; }