void _optimize_likelihood() { par::init(); typedef std::pair<Eigen::VectorXd, double> pair_t; auto body = [ = ](int i) { // we need a copy because each thread should touch a copy of the GP! auto gp = *this; Eigen::VectorXd v = rprop::optimize([&](const Eigen::VectorXd & v) { return gp.log_likelihood(v); }, [&](const Eigen::VectorXd & v) { return gp.log_likelihood_grad(v, false); }, this->kernel_function().h_params_size(), Params::gp_auto::n_rprop()); double lik = gp.log_likelihood(v); return std::make_pair(v, lik); }; auto comp = [](const pair_t& v1, const pair_t& v2) { return v1.second > v2.second; }; pair_t init(Eigen::VectorXd::Zero(1), -std::numeric_limits<float>::max()); auto m = par::max(init, Params::gp_auto::rprop_restart(), body, comp); std::cout << "likelihood:" << m.second << std::endl; this->_kernel_function.set_h_params(m.first); }
inline double pmcmc_do (vsmc::Sampler<T> &sampler, std::size_t model_num) { const std::size_t nchain = static_cast<std::size_t>(sampler.size()); std::vector<double> log_likelihood(nchain); sampler.particle().value().comp_num(model_num); sampler.initialize(); sampler.iterate(BurninNum); for (std::size_t k = 0; k != nchain; ++k) log_likelihood[k] = 0; for (std::size_t j = 0; j != IterNum; ++j) { sampler.iterate(); for (std::size_t k = 0; k != nchain; ++k) { log_likelihood[k] += sampler.particle().value(). state(k, 0).log_likelihood(); } } for (std::size_t k = 0; k != nchain; ++k) log_likelihood[k] /= IterNum; double ps = sampler.particle().value().log_likelihood_const(); for (std::size_t k = 1; k != nchain; ++k) { ps += sampler.particle().value().state(k, 0).alpha_inc() * 0.5 * (log_likelihood[k -1] + log_likelihood[k]); } return ps; }
/* * Sample the parameter space uniformly. Very slow! */ void explore_prior_space(live_point* livpnt,double llstar,unsigned num_dim, unsigned num_par,ellipsis_mt19937_rng* rng, void (*log_likelihood)(double *cube, unsigned ndim, unsigned npar, double *lnew)) { /*Evolve the object within the likelihood constraint*/ unsigned i; double llik; live_point* trial_lvpnt=(live_point*)malloc(sizeof(live_point)); init_live_point(trial_lvpnt,num_dim); for(;;) { for(i=0;i<num_dim;++i) { trial_lvpnt->x[i]=genrand_uniform(rng); } log_likelihood(trial_lvpnt->x,num_dim,num_par,&llik); trial_lvpnt->log_lik=llik; /*accpet if and only if within l > lstar */ if(trial_lvpnt->log_lik > llstar) { copy_live_point(livpnt,trial_lvpnt); break; } } free(trial_lvpnt); }
void CGppe::Approx_CGppe_Laplace(const VectorXd & theta_x, const VectorXd& theta_t, const double& sigma, const MatrixXd& t, const MatrixXd &x, const TypePair & all_pairs, const VectorXd & idx_global, const VectorXd& idx_global_1, const VectorXd& idx_global_2, const VectorXd& ind_t, const VectorXd& ind_x, int M, int N) { //Parameters function initialization double eps = 1E-6, psi_new, psi_old; M = all_pairs.rows(); int n = M * N; f = VectorXd::Zero(n); VectorXd fvis = VectorXd::Zero(idx_global.rows()); VectorXd deriv; double loglike = 0; covfunc_t->SetTheta(theta_t); covfunc_x->SetTheta(theta_x); MatrixXd Kt = covfunc_t->ComputeGrandMatrix(t); Kx = covfunc_x->ComputeGrandMatrix(x); MatrixXd K = GetMat(Kt, ind_t, ind_t).array() * GetMat(Kx, ind_x, ind_x).array(); loglike = log_likelihood( sigma, all_pairs, idx_global_1, idx_global_2, M, N); Kinv = K.inverse(); psi_new = loglike - 0.5 * fvis.transpose() * Kinv * fvis; psi_old = INT_MIN; while ((psi_new - psi_old) > eps) { psi_old = psi_new; deriv = deriv_log_likelihood_CGppe_fast( sigma, all_pairs, idx_global_1, idx_global_2, M, N); W = -deriv2_log_likelihood_CGppe_fast(sigma, all_pairs, idx_global_1, idx_global_2, M, N); W = GetMat(W, idx_global, idx_global); llt.compute(W + Kinv); L = llt.matrixL(); //no need to extract the triangular matrix here fvis = llt.solve(GetVec(deriv, idx_global) + W * fvis); for (int w = 0;w < idx_global.rows();w++) { f(idx_global(w)) = fvis(w); } loglike = log_likelihood( sigma, all_pairs, idx_global_1, idx_global_2, M, N); psi_new = loglike - 0.5 * fvis.transpose() * Kinv * fvis; } }
void calc_theta_loglik() { loglik_theta = 0.0; for (int i=0; i!=m->nparams; ++i) { loglik_theta += log_likelihood(m->param_dists[i], theta[i], m->param_hyper[i]); loglik_theta += jacobian_adj(m->param_trans[i], theta[i], m->param_hyper[i]); } }
float score_gmm (int gmm_index, float *input) { gmm *g = &gmms[gmm_index]; const float *mixtures = g->mixture_weights; float score = 0.0f; int k=0; for(k = 0; k < g->count; k++) { float likelihood = log_likelihood( &g->gaussians[k], input) + mixtures[k]; score = logsum(score, likelihood); } return score; }
double LRM::Loglike(Vec &g, Mat &h, uint nd)const{ if(nd>=2) return log_likelihood(Beta(), &g, &h); if(nd==1) return log_likelihood(Beta(), &g, 0); return log_likelihood(Beta(), 0, 0); }
double log_likelihood() const { return log_likelihood(discount, strength); }
void run(std::string tree_filename, std::string fasta_filename, std::string model_name) { Model Mod; // The model Counts data; // the counts Parameters Par; // the parameters std::vector<double> br; // branch lengths double eps = 1e-8; // The threshold for the EM algorithm. Parameters Parsim; // used for simulating data. std::vector<double> brsim; // branch lengths of simulated data. std::vector<std::vector<double> > Cov; // Covariance matrix std::vector<double> variances; // The variances bool simulate; bool nonident; std::string parameters_filename; std::string covariances_filename; // initialize random number generator with time(0). random_initialize(); parameters_filename = strip_extension(fasta_filename) + ".dat"; covariances_filename = strip_extension(fasta_filename) + ".cov"; // Creates the pointers to the model-specific functions. Mod = create_model(model_name); std::cout << "Model: " << Mod.name << std::endl; // Reads the tree. Tree T = read_tree(tree_filename); // Prints the Tree std::cout << "Tree:" << std::endl; print_tree(T); // Check for possible nonidentifiability issues. nonident = nonident_warning(T); // Initialize the parameters for simulation of K81 data for testing Parsim = create_parameters(T); if (fasta_filename == ":test") { // if fasta file is :test generate random data. simulate = true; // Warn std::cout << "WARNING: Using simulated data " << std::endl << std::endl; // Generate random parameters random_parameters_length(T, Mod, Parsim); // Simulate the data data = random_fake_counts(T, 1000, Parsim); // Prints branch-lengths for future check. branch_lengths(Parsim, brsim); std::cout << "Simulated branch lengths:" << std::endl; print_vector(brsim); } else { // otherwise read the data simulate = false; // Read the counts. std::cout << "Reading fasta file:" << std::endl; read_counts(T, data, fasta_filename); add_pseudocounts(0.01, data); std::cout << std::endl; } // Check whether the data and the tree match. if (T.nalpha != data.nalpha || T.nleaves != data.nspecies) { throw std::invalid_argument("The order of the sequences or their number and the phylogenetic tree do not match."); } //Par = create_parameters(T); //print_parameters(Par); //print_vector(Par.r); //clock_t long start_time, end_time; // Runs the EM algorithm. Par is used as initial parameters. // After execution, Par contains the MLE computed by the algorithm. // for local max over multiple iterations Parameters Parmax = Par; Model Modmax = Mod; float likelL = 0.0; float likelMax = -1000000.0; float timerec; float timemax; int outfiles; //whether to save output std::cout << "Starting the EM algorithm: " << std::endl; int s; int S = 0; //count of cases with neg branches int iter; int iterMax; for (int it_runs = 0; it_runs < 10; it_runs++) { Par = create_parameters(T); Mod = create_model(model_name); std::cout << it_runs << ", " ; start_time = clock(); std::tie(likelL, iter) = EMalgorithm(T, Mod, Par, data, eps); end_time = clock(); //print_parameters(Par); // Choses the best permutation. guess_permutation(T, Mod, Par); branch_lengths(Par, br); //print_vector(br); s = find_negative(br); S +=s; timerec = ((float)end_time - start_time) / CLOCKS_PER_SEC; //assign the 1st iter time value, inc ase it's the best if (it_runs == 0){ timemax = timerec; iterMax = iter; } if (likelL > likelMax){ Parmax = Par; Modmax = Mod; timemax = timerec; likelMax = likelL; iterMax = iter; } } // If parameters are not identifiable, the computation of the covariance matrix will // fail as the Fisher info matrix will not be invertible. if (!nonident) { // Compute the covariance matrix using observed Fisher. full_MLE_observed_covariance_matrix(T, Modmax, Parmax, data, Cov); variances.resize(Cov.size()); for(unsigned int i=0; i < Cov.size(); i++) { variances[i] = Cov[i][i]; } // OUTPUT Save the sigmas into a file //save_sigmas_to(covariances_filename, Cov); } std::cout << std::endl; std::cout << "Finished." << std::endl; std::cout << "Likelihood: " << log_likelihood(T, Parmax, data) << std::endl ; std::cout << "Time: " << timemax << std::endl << std::endl; std::cout << "negative branches: " << S << std::endl; std::cout << "Iter: " << iterMax << std::endl; //std::cout << "Branch lengths: " << std::endl; //print_vector(br); outfiles = 0; if (!nonident && outfiles) { std::cout << "Parameter variances: " << std::endl; print_vector(variances); } std::cout << "Newick Tree:" << std::endl; print_newick_tree(T, br); // if is a simulation, print the L2 distance ! if (simulate) { std::cout << "L2 distance: " << parameters_distance(Par, Parsim) << std::endl; std::cout << "KL divergence: " << KL_divergence(T, Par, Parsim) << std::endl; std::cout << std::endl; } // if it is not a simulation, store the parameters in a file ! if (!simulate && outfiles) { std::fstream st; st.precision(15); st.setf(std::ios::fixed,std::ios::floatfield); st.open(parameters_filename.c_str(), std::ios::out); print_parameters(Par, st); } }
/* * Explore the parameter space with MCMC. * See Sivia & Skilling 2006, page 193 for more details */ void explore_prior_space_with_mcmc(live_point* livpnt,double llstar,unsigned num_dim, unsigned num_par,ellipsis_mt19937_rng* rng, void (*log_likelihood)(double *cube, unsigned ndim, unsigned npar, double *lnew)) { /*Evolve the object within the likelihood constraint*/ unsigned num_samples=20; double step=0.1; unsigned accept=0; unsigned reject=0; unsigned i; double llik; unsigned samps=0; double* uvals; double* uvals_new; double* xvals; double* xvals_new; double llik_new; uvals=(double*)malloc(num_dim*sizeof(double)); uvals_new=(double*)malloc(num_dim*sizeof(double)); xvals=(double*)malloc(num_dim*sizeof(double)); xvals_new=(double*)malloc(num_dim*sizeof(double)); for(i=0;i<num_dim;++i) { uvals[i]=livpnt->u[i]; xvals[i]=livpnt->x[i]; llik_new=livpnt->log_lik; } for(;;) { for(i=0;i<num_dim;++i) { uvals_new[i]=uvals[i]+step*(2.*genrand_uniform(rng)-1.); uvals_new[i]-=floor(uvals_new[i]); xvals_new[i]=uvals_new[i]; } log_likelihood(xvals_new,num_dim,num_par,&llik); /*accpet if and only if within l > lstar */ if(llik > llstar) { for(i=0;i<num_dim;++i) { uvals[i]=uvals_new[i]; xvals[i]=xvals_new[i]; } llik_new=llik; ++accept; } else { ++reject; } /*refine step size to let acceptance ratio converge around 50% */ if(accept>reject) { step*=exp(1./(double)accept); } if(accept<reject) { step/=exp(1./(double)reject); } if(accept>0 && samps>=num_samples) { for(i=0;i<num_dim;++i) { livpnt->u[i]=uvals[i]; livpnt->x[i]=xvals[i]; } livpnt->log_lik=llik_new; break; } ++samps; } free(uvals); free(uvals_new); free(xvals); free(xvals_new); }
/* *This function implements an approximation to Mukherjee's Ellipsoidal methods. * EXPERIMENTAL -> DO NOT USE */ void explore_prior_space_with_mcmc_var_tuned(live_point* livpnt,double llstar, live_point* phys_live_points,unsigned num_phys_live,unsigned num_dim,unsigned num_par, ellipsis_mt19937_rng* rng, void (*log_likelihood)(double *cube, unsigned ndim, unsigned npar, double *lnew)) { /*Evolve the object within the likelihood constraint*/ unsigned num_samples=20; unsigned i,j; double llik; unsigned samps=0; unsigned accept=0; unsigned reject=0; double step=2.; double* sigma; double* mean; double sum; double sum2; double enlarge_fact=2.; double* uvals; double* uvals_new; double* xvals; double* xvals_new; double llik_new; unsigned best=0; /*From the available live points, estimate the variance in each dimension*/ sigma=(double*)malloc(num_dim*sizeof(double)); mean=(double*)malloc(num_dim*sizeof(double)); for(i=0;i<num_phys_live;++i) { if(phys_live_points[i].log_lik>phys_live_points[best].log_lik) { best=i; } } /*printf("\nbest= %d\tval=%f\n",best,phys_live_points[best].log_lik);*/ for(i=0;i<num_dim;++i) { sum=0; sum2=0; for(j=0;j<num_phys_live;++j) { sum+=phys_live_points[j].u[i]; sum2+=phys_live_points[j].u[i]*phys_live_points[j].u[i]; } sigma[i]=sqrt( (sum2-sum*sum/(double)num_phys_live)/(double)num_phys_live ); /*mean[i]=sum/(double)num_phys_live;*/ mean[i]=(phys_live_points[best].u[i]+sum/(double)num_phys_live)*0.5; /*printf("%f\t",mean[i]);*/ } /*printf("\n");*/ uvals=(double*)malloc(num_dim*sizeof(double)); uvals_new=(double*)malloc(num_dim*sizeof(double)); xvals=(double*)malloc(num_dim*sizeof(double)); xvals_new=(double*)malloc(num_dim*sizeof(double)); /*printf("\nllstar= %f\n",llstar);*/ for(i=0;i<num_dim;++i) { uvals[i]=livpnt->u[i]; xvals[i]=livpnt->x[i]; llik_new=livpnt->log_lik; } for(;;) { for(i=0;i<num_dim;++i) { uvals_new[i]=(uvals[i]+mean[i])*0.5+sigma[i]*genrand_uniform(rng); xvals_new[i]=uvals_new[i]; } log_likelihood(xvals_new,num_dim,num_par,&llik); /*trial_lvpnt->log_lik=llik*/ /*accpet if and only if within l > lstar */ if(llik > llstar) { for(i=0;i<num_dim;++i) { uvals[i]=uvals_new[i]; xvals[i]=xvals_new[i]; } llik_new=llik; ++accept; } else { ++reject; } /*refine step size to let acceptance ratio converge around 50% */ if(accept>reject) { step*=exp(1./(double)accept); } if(accept<reject) { step/=exp(1./(double)reject); } if(accept>0 && samps>=num_samples) { /*copy_live_point(livpnt,trial_lvpnt);*/ for(i=0;i<num_dim;++i) { livpnt->u[i]=uvals[i]; livpnt->x[i]=xvals[i]; } livpnt->log_lik=llik_new; break; } ++samps; /*printf("accept=%d\tsamps= %d\n",accept,samps);*/ } free(uvals); free(uvals_new); free(xvals); free(xvals_new); free(sigma); free(mean); }
/* * Compute the following entities: * - responsibilities r(k|ij) * - mu_ij_k * - Lambda_ij_k * - log determinante Lamda_ij_k * * And then use these to compute likelihood and gradients */ void Likelihood_Protein::compute_f_df(int hessian_pseudocount) { //initialize parameters for second gaussian mu_ij_k.zeros(400, this->nr_components); lambda_ij_k.zeros(400, 400, this->nr_components); lambda_ij_k_inv.zeros(400, 400, this->nr_components); log_det_lambda_ij_k.zeros(this->nr_components); responsibilities.zeros(this->nr_components); //initialize likelihood vector log_likelihood.zeros(this->number_of_pairs); //intialize gradients to zero grad_weight.zeros(this->nr_components, 2); grad_mu.zeros(400,this-> nr_components); grad_precMat.zeros(400, this->nr_components); for(int pair = 0; pair < this->number_of_pairs; pair++){ int i = this->i_indices(pair); int j = this->j_indices(pair); int lin_index = i*(L - (i+1)/2.0 - 1) + j - 1; //i*L - i*(i+1)/2 + j-(i+1); int contact = this->protein_contacts(pair); //for computation of likelihood arma::vec log_density(this->nr_components, arma::fill::zeros); arma::vec vqij = mq_ij.col(lin_index); double N_ij = mN_ij(i,j); arma::vec w_ij = w_ij3d.tube(i,j); //diagonal matrix Qij = diag(q'ji) //q'ijab = q(x_i=a, x_j=b) - (lambda_w * wijab / N_ij) --> has been precomputed arma::mat Qij = arma::diagmat(vqij); //outer product arma::mat qij_prod = vqij * vqij.t(); //determine negative Hessian = Hij arma::mat diff = Qij - qij_prod; arma::mat H_ij = N_ij * diff + regularizer_w; //eq 37 // remove after debugging --------------------------------------------------------------------------------- //debugging artefacts in learning //add counts to Hessian to see if we have problems with non-informative data H_ij.diag() += hessian_pseudocount; //H_ij = arma::diagmat(H_ij); // remove after debugging --------------------------------------------------------------------------------- //precompute product H_ij * wij arma::vec Hij_wij_prod = H_ij * w_ij; for(int k = 0; k < this->nr_components; k++){ //gaussian parameters of coupling prior double weight_k = this->parameters.get_weight(k, contact); arma::vec mu_k = this->parameters.get_mean(k); arma::mat lambda_k = this->parameters.get_precMat(k); //---------------- simplify computation in case that lambda_k is diagonal matrix // A, A_inv, lambda_k, Qij are diagonal matrices arma::vec A = N_ij * vqij + lambda_k.diag(); //represents diagonal matrix arma::vec A_inv = 1.0 / A; //represents diagonal matrix double log_det_A = arma::sum(arma::log(A)); arma::vec Ainv_qij_product = A_inv % vqij; ////column vector double triple_product = arma::sum(vqij % Ainv_qij_product); //---------------- matrix computations in case lambda_k is NOT diagonal matrix //A is a diagonal matrix, as Qij and lambda_k are diagonal matrices //arma::mat A = N_ij * Qij + lambda_k; //diagonal //arma::mat A_inv = arma::diagmat(1.0 / A.diag()); //diagonal //double log_det_A = arma::sum(arma::log(A.diag())); //arma::vec Ainv_qij_product = arma::vec(A_inv * vqij); //400x1 dim matrix //double triple_product = arma::as_scalar(vqij.t() * Ainv_qij_product); //compute lambda_ij_k_mat arma::mat lambda_ij_k_mat = H_ij - regularizer_w + lambda_k; lambda_ij_k.slice(k) = lambda_ij_k_mat; //debugging: we assume diagonal Hessian ================================================================ // arma::mat lambda_ij_k_mat_inv(400,400,arma::fill::zeros); // lambda_ij_k_mat_inv.diag() = 1.0 / lambda_ij_k_mat.diag(); //debugging======================================================================================= //compute inverse of lambda_ij_k_mat //---------------- simplify computation in case that lambda_k is diagonal matrix arma::mat lambda_ij_k_mat_inv = arma::diagmat(A_inv) + (Ainv_qij_product * Ainv_qij_product.t()) / (1.0/N_ij - triple_product); //---------------- matrix computations in case lambda_k is NOT diagonal matrix //arma::mat lambda_ij_k_mat_inv = A_inv + (Ainv_qij_product * Ainv_qij_product.t()) / (1.0/N_ij - triple_product); lambda_ij_k_inv.slice(k) = lambda_ij_k_mat_inv; //compute mu_ij_k from precomputed entities arma::vec mu_ij_k_vec = lambda_ij_k_mat_inv * ( Hij_wij_prod + lambda_k * mu_k); mu_ij_k.col(k) = mu_ij_k_vec; //debugging: we assume diagonal Hessian ================================================================ // log_det_lambda_ij_k(k) = arma::sum(arma::log(lambda_ij_k_mat.diag())); //debugging======================================================================================= //save log determinant of lambda_ij_k, see page 16 Saikats theory log_det_lambda_ij_k(k) = log(1 - N_ij * triple_product) + log_det_A; //ratio of two gaussians in log space // N(0 | mu_k, lambda_k) //------------------------------ // N(0 | mu_ij_k, lambda_ij,k) double gaussian_ratio_logdensity = log_density_gaussian_ratio( mu_k, mu_ij_k_vec, lambda_k, lambda_ij_k_mat, this->parameters.get_log_det_inv_covMat(k), log_det_lambda_ij_k(k) ); if(this->debug > 0 and gaussian_ratio_logdensity>1000){ std::cout << protein_id << " " << i << " " << j << " " << pair << " " << contact << " " << k << std::endl; std::cout << "Gaussian log density > 1: " << gaussian_ratio_logdensity << std::endl; std::cout << "A_inv.max() : " << A_inv.max() << std::endl; arma::uword max_ind = index_max(A_inv); std::cout << "A(max_ind) : " << A(max_ind) << std::endl; std::cout << "vqij(max_ind): " << vqij(max_ind) << std::endl; std::cout << "N_ij: " << N_ij << std::endl; std::cout << "mu_ij_k_vec(max_ind) : " << mu_ij_k_vec(max_ind) << std::endl; std::cout << "mu_k(max_ind) : " << mu_k(max_ind) << std::endl; std::cout << "lambda_ij_k_mat(max_ind, max_ind) : " << lambda_ij_k_mat(max_ind, max_ind) << std::endl; std::cout << "lambda_ij_k_mat_inv(max_ind, max_ind) : " << lambda_ij_k_mat_inv(max_ind, max_ind) << std::endl; std::cout << "lambda_k(max_ind, max_ind) : " << lambda_k(max_ind, max_ind) << std::endl; std::cout << "parameters.get_log_det_inv_covMat(k) : " << this->parameters.get_log_det_inv_covMat(k) << std::endl; std::cout << "log_det_lambda_ij_k(k) : " << log_det_lambda_ij_k(k) << std::endl; } log_density(k) = log(weight_k) + gaussian_ratio_logdensity; }//end loop over components k //Johannes suggestion how to precisely compute the responsibilities double a_max = arma::max(log_density); this->responsibilities = arma::exp(log_density - a_max);//r_nk = exp( a_nk - a_max) double sum_resp = arma::sum(this->responsibilities); //sum += r_nk this->responsibilities /= sum_resp; //normalization of responsibilities, NOT in log space => r_nk /= sum; //save neg likelihood of current pair double f = log(sum_resp) + a_max; if(! std::isnormal(f)) { std::cout << "ERROR: likelihood cannot be computed for protein " << protein_id << ", i " << i << ", j " << j << " ("<< contact <<"): " << f << std::endl; std::cout << "Nij: " << N_ij << ", sum_resp: " << sum_resp << ", a_max: " << a_max << std::endl; for(int k = 0; k < this->nr_components; k++){ std::cout << "component: " << k << ", sum_precMat(k)diag: "<< arma::sum(this->parameters.get_precMat(k).diag()) << ", responsibilty:" << this->responsibilities(k) << ", log_density: " << log_density(k) << ", log_det_lambda_ij_k: " << log_det_lambda_ij_k(k) << std::endl; } continue; } else log_likelihood(pair) = f; // Compute ALL gradients for ALL components for(int k = 0; k < this->nr_components; k++){ //weights (either for contact or non_contact) grad_weight(k, contact) += gradient_weight_comp(k, contact); //mu grad_mu.col(k) += gradient_mu_comp(k); //precMat - diagonal arma::mat grad_precMat_protein = gradient_precisionMatrix_comp(k); grad_precMat.col(k) += grad_precMat_protein.diag(); }//end components }//end loop over ij pairs }
/* * This function calculates the Hessian and mu_ij_k and Lambda_ij_k * for all pairs (i,j) in the batch * and for all components k * */ void Likelihood_Protein::compute_negLL(int nr_threads_prot) { //initialize likelihood vector log_likelihood.zeros(this->number_of_pairs); #pragma omp parallel for num_threads(nr_threads_prot) for(int pair = 0; pair < this->number_of_pairs; pair++){ int i = this->i_indices(pair); int j = this->j_indices(pair); int lin_index = i*(L - (i+1)/2.0 - 1) + j - 1; //i*L - i*(i+1)/2 + j-(i+1); int contact = this->protein_contacts(pair); //for computation of likelihood arma::vec log_density(this->nr_components, arma::fill::zeros); arma::vec vqij = mq_ij.col(lin_index); double N_ij = mN_ij(i,j); arma::vec w_ij = w_ij3d.tube(i,j); //arma::vec vqij = q_ij3d.tube(i,j); //diagonal matrix Qij = diag(q'ji) //q'ijab = q(x_i=a, x_j=b) - (lambda_w * wijab / N_ij) --> has been precomputed arma::mat Qij = arma::diagmat(vqij); //outer product arma::mat qij_prod = vqij * vqij.t(); //determine negative Hessian = Hij arma::mat diff = Qij - qij_prod; arma::mat H_ij = N_ij * diff + regularizer_w; //eq 37 //precompute product H_ij * wij arma::vec Hij_wij_prod = H_ij * w_ij; for(int k = 0; k < this->nr_components; k++){ //gaussian parameters of coupling prior double weight_k = this->parameters.get_weight(k, contact); arma::vec mu_k = this->parameters.get_mean(k); arma::mat lambda_k = this->parameters.get_precMat(k); //---------------- simplify computation in case that lambda_k is diagonal matrix // A, A_inv, lambda_k, Qij are diagonal matrices arma::vec A = N_ij * vqij + lambda_k.diag(); //represents diagonal matrix arma::vec A_inv = 1.0 / A; //represents diagonal matrix double log_det_A = arma::sum(arma::log(A)); arma::vec Ainv_qij_product = A_inv % vqij; ////column vector double triple_product = arma::sum(vqij % Ainv_qij_product); //---------------- matrix computations in case lambda_k is NOT diagonal matrix //A is a diagonal matrix, as Qij and lambda_k are diagonal matrices //arma::mat A = N_ij * Qij + lambda_k; //diagonal //arma::mat A_inv = arma::diagmat(1.0 / A.diag()); //diagonal //double log_det_A = arma::sum(arma::log(A.diag())); //arma::vec Ainv_qij_product = arma::vec(A_inv * vqij); //400x1 dim matrix //double triple_product = arma::as_scalar(vqij.t() * Ainv_qij_product); //compute lambda_ij_k_mat arma::mat lambda_ij_k_mat = H_ij - regularizer_w + lambda_k; //debugging: we assume diagonal Hessian ================================================================ // arma::mat lambda_ij_k_mat_inv(400,400,arma::fill::zeros); // lambda_ij_k_mat_inv.diag() = 1.0 / lambda_ij_k_mat.diag(); //debugging======================================================================================= //compute inverse of lambda_ij_k_mat //---------------- simplify computation in case that lambda_k is diagonal matrix arma::mat lambda_ij_k_mat_inv = arma::diagmat(A_inv) + (Ainv_qij_product * Ainv_qij_product.t()) / (1.0/N_ij - triple_product); //---------------- matrix computations in case lambda_k is NOT diagonal matrix //arma::mat lambda_ij_k_mat_inv = A_inv + (Ainv_qij_product * Ainv_qij_product.t()) / (1.0/N_ij - triple_product); //compute mu_ij_k from precomputed entities arma::vec mu_ij_k_vec = lambda_ij_k_mat_inv * ( Hij_wij_prod + lambda_k * mu_k); //debugging: we assume diagonal Hessian ================================================================ // log_det_lambda_ij_k(k) = arma::sum(arma::log(lambda_ij_k_mat.diag())); //debugging======================================================================================= //save log determinant of lambda_ij_k, see page 16 Saikats theory double log_det_lambda_ij = log(1 - N_ij * triple_product) + log_det_A; //ratio of two gaussians in log space // N(0 | mu_k, lambda_k) //------------------------------ // N(0 | mu_ij_k, lambda_ij,k) double gaussian_ratio_logdensity = log_density_gaussian_ratio( mu_k, mu_ij_k_vec, lambda_k, lambda_ij_k_mat, this->parameters.get_log_det_inv_covMat(k), log_det_lambda_ij); log_density(k) = log(weight_k) + gaussian_ratio_logdensity; // if ((i == 0) && (j == 12)){ // std::cout << " " << std::endl; // std::cout << protein_id << " i: " << i << " j: " << j << " contact=" << contact << " component: " << k << std::endl; // std::cout << "triple_product : " << triple_product << std::endl; // std::cout << "log_det_A : " << log_det_A << std::endl; // std::cout << "lambda_ij_k_mat(0,1) : " << lambda_ij_k_mat(0,1) << "lambda_ij_k_mat(0,2) : " << lambda_ij_k_mat(0,2) << "lambda_ij_k_mat(2,0) : " << lambda_ij_k_mat(2,0) << std::endl; // std::cout << "mu_ij_k_vec(0) : " << mu_ij_k_vec(0) << "mu_ij_k_vec(1) : " << mu_ij_k_vec(1) << "mu_ij_k_vec(2) : " << mu_ij_k_vec(2) << std::endl; // std::cout << "Gaussian log density: " << gaussian_ratio_logdensity << std::endl; // std::cout << "log_density(k): " << log_density(k)<< std::endl; // std::cout << "log(weight_k): " << log(weight_k) << " weight_k: " << weight_k << std::endl ; // } }//end loop over components k //Johannes suggestion how to precisely compute the responsibilities double a_max = arma::max(log_density); arma::vec resps = arma::exp(log_density - a_max);//r_nk = exp( a_nk - a_max) double sum_resp = arma::sum(resps); //sum += r_nk //save neg likelihood of current pair double f = log(sum_resp) + a_max; // if ((i == 0) && (j == 12)){ // std::cout << "a_max : " << a_max << std::endl; // std::cout << "sum_resp : " << sum_resp << std::endl; // std::cout << "f : " << f << std::endl; // } if(! std::isnormal(f)) { std::cout << "ERROR: likelihood cannot be computed for protein " << protein_id << ", i " << i << ", j " << j << " ("<< contact <<"): " << f << std::endl; std::cout << "Nij " << N_ij << ", sum_resp: " << sum_resp << ", a_max: " << a_max << std::endl; for(int k = 0; k < this->nr_components; k++){ std::cout << "component: " << k << ", sum_precMat(k)diag: "<< arma::sum(this->parameters.get_precMat(k).diag()) << ", responsibilty:" << resps(k)/sum_resp << ", log_density: " << log_density(k) << std::endl; } continue; } else log_likelihood(pair) = f; }//end of parallelized for loop over ij pairs }
int main(int argc, char *argv[]) { int nobs, sizex, nsample = 0; char *location = NULL; int ret = 0; ////////////////////////////////////// /////////////// PARSERS ////////////// ////////////////////////////////////// // Parse the command line ret = parse_command_line(argc,argv,&nobs,&sizex,&nsample,&location); if( ret != PARSER_SUCCESS ) { printf("Parsing failed ! Exiting...\n"); return EXIT_FAILURE; } // Parse the data on master double *buffer_X = (double*)malloc(nobs*sizex*sizeof(double)); double *isigma = (double*)malloc(sizex*sizex*sizeof(double)); double *mu = (double*)malloc(sizex*sizeof(double)); double det_sigma = 0.0; ret = read_data(buffer_X, isigma, &det_sigma, mu, &nobs, &sizex, location); if( ret != PARSER_SUCCESS ) { printf("Parsing failed ! Exiting...\n"); return EXIT_FAILURE; } //////////////////////////////////////// /////////////// Variables ////////////// //////////////////////////////////////// // Thread variables int nthreads = 1; int th_num = 0; int th_nobs = nobs; nthreads = get_num_threads(); // Timing variables double tic, toc, tot_time = 0.0; //// Arrays for all threads // The pool is allocated inside the shared memory double *pool_LV = (double*)malloc(nobs*sizex*sizeof(double)); // Left hand side vector (X-mu) double *pool_tmp = (double*)malloc(nobs*sizex*sizeof(double)); // Temporary holder for (X-mu)*SIG double *pool_ones = (double*)malloc(nobs*sizeof(double)); // Temporary holder to create LV double *pool_res = (double*)malloc(nthreads*sizeof(double)); // Each thread puts its result in pool_res // Use pointers to get the correct location in the array double *LV = NULL; double *tmp = NULL; double *ones = NULL; double *X = NULL; // Holder for final sum double final_sum = 0.0; //////////////////////////////////////// /////////////// Algorithm ////////////// //////////////////////////////////////// //// Start time sampling for(int k = 0; k < nsample; k++) { tic = omp_get_wtime(); final_sum = 0.0; // Main driver #pragma omp parallel private(th_num,th_nobs,LV,tmp,ones,X) default(shared) { // Get thread number th_num = omp_get_thread_num(); // Total number of observations for that thread th_nobs = nobs/nthreads; // Use the address to point to the correct location in the vector X = &buffer_X[th_num*nobs*sizex/nthreads]; LV = &pool_LV[th_num*th_nobs*sizex]; tmp = &pool_tmp[th_num*th_nobs*sizex]; ones = &pool_ones[th_num*th_nobs]; // Each process can now calculate the term in the // exponent for a subset of random vectors // Naive approach: for loop on each vector X // pool_res[th_num] += exp_term(); // Guru approach: BLAS log_likelihood(X,isigma,mu,det_sigma,th_nobs,sizex,&pool_res[th_num],LV,tmp,ones); #pragma omp barrier // Reduction: sum all the intermediary results #pragma omp for reduction(+:final_sum) for(int i = 0; i < nthreads; i++) final_sum = final_sum + pool_res[i]; } toc = omp_get_wtime(); tot_time += toc-tic; } printf("Result: %f\n",final_sum); printf("Total time: %f\n",tot_time/(double)nsample); //////////////////////////////////////// /////////////// Clean up /////////////// //////////////////////////////////////// free(pool_res); free(pool_ones); free(pool_tmp); free(pool_LV); free(buffer_X); free(isigma); free(mu); free(location); return EXIT_SUCCESS; }
double LRM::Loglike(const Vector &beta, Vector &g, Matrix &h, uint nd)const{ if(nd>=2) return log_likelihood(beta, &g, &h); if(nd==1) return log_likelihood(beta, &g, 0); return log_likelihood(beta, 0, 0); }