float64_t CKLDualInferenceMethod::get_nlml_wrapper(SGVector<float64_t> alpha, SGVector<float64_t> mu, SGMatrix<float64_t> L) { Map<MatrixXd> eigen_L(L.matrix, L.num_rows, L.num_cols); Map<VectorXd> eigen_alpha(alpha.vector, alpha.vlen); Map<MatrixXd> eigen_K(m_ktrtr.matrix, m_ktrtr.num_rows, m_ktrtr.num_cols); //get mean vector and create eigen representation of it SGVector<float64_t> mean=m_mean->get_mean_vector(m_features); Map<VectorXd> eigen_mu(mu.vector, mu.vlen); Map<VectorXd> eigen_mean(mean.vector, mean.vlen); CDualVariationalGaussianLikelihood *lik=get_dual_variational_likelihood(); SGVector<float64_t>lab=((CBinaryLabels*)m_labels)->get_labels(); Map<VectorXd> eigen_lab(lab.vector, lab.vlen); float64_t a=SGVector<float64_t>::sum(lik->get_variational_expection()); float64_t trace=0; //L_inv=L\eye(n); //trace(L_inv'*L_inv) %V*inv(K) MatrixXd eigen_t=eigen_L.triangularView<Upper>().adjoint().solve(MatrixXd::Identity(eigen_L.rows(),eigen_L.cols())); for(index_t idx=0; idx<eigen_t.rows(); idx++) trace +=(eigen_t.col(idx).array().pow(2)).sum(); //nlZ = -a -logdet(V*inv(K))/2 -n/2 +(alpha'*K*alpha)/2 +trace(V*inv(K))/2; float64_t result=-a+eigen_L.diagonal().array().log().sum(); result+=0.5*(-eigen_K.rows()+eigen_alpha.dot(eigen_mu-eigen_mean)+trace); return result; }
SGVector<float64_t> CLogitVGPiecewiseBoundLikelihood::get_variational_first_derivative( const TParameter* param) const { //This function is based on the Matlab code //function [f, gm, gv] = Ellp(m, v, bound, ind), to compute gm and gv //and the formula of the appendix REQUIRE(param, "Param is required (param should not be NULL)\n"); REQUIRE(param->m_name, "Param name is required (param->m_name should not be NULL)\n"); //We take the derivative wrt to param. Only mu or sigma2 can be the param REQUIRE(!(strcmp(param->m_name, "mu") && strcmp(param->m_name, "sigma2")), "Can't compute derivative of the variational expection ", "of log LogitLikelihood using the piecewise bound ", "wrt %s.%s parameter. The function only accepts mu and sigma2 as parameter", get_name(), param->m_name); const Map<VectorXd> eigen_c(m_bound.get_column_vector(0), m_bound.num_rows); const Map<VectorXd> eigen_b(m_bound.get_column_vector(1), m_bound.num_rows); const Map<VectorXd> eigen_a(m_bound.get_column_vector(2), m_bound.num_rows); const Map<VectorXd> eigen_mu(m_mu.vector, m_mu.vlen); const Map<VectorXd> eigen_s2(m_s2.vector, m_s2.vlen); Map<VectorXd> eigen_l(m_bound.get_column_vector(3), m_bound.num_rows); Map<VectorXd> eigen_h(m_bound.get_column_vector(4), m_bound.num_rows); index_t num_rows = m_bound.num_rows; index_t num_cols = m_mu.vlen; const Map<MatrixXd> eigen_cdf_diff(m_cdf_diff.matrix, num_rows, num_cols); const Map<MatrixXd> eigen_pl(m_pl.matrix, num_rows, num_cols); const Map<MatrixXd> eigen_ph(m_ph.matrix, num_rows, num_cols); const Map<MatrixXd> eigen_weighted_pdf_diff(m_weighted_pdf_diff.matrix, num_rows, num_cols); const Map<MatrixXd> eigen_h2_plus_s2(m_h2_plus_s2.matrix, num_rows, num_cols); const Map<MatrixXd> eigen_l2_plus_s2(m_l2_plus_s2.matrix, num_rows, num_cols); float64_t l_bak = eigen_l(0); //l(1) = 0; eigen_l(0) = 0; float64_t h_bak = eigen_h(eigen_h.size()-1); //h(end) = 0; eigen_h(eigen_h.size()-1) = 0; SGVector<float64_t> result(m_mu.vlen); if (strcmp(param->m_name, "mu") == 0) { //Compute the derivative wrt mu //bsxfun(@plus, bsxfun(@plus, l.^2, v), v).*pl - bsxfun(@plus, bsxfun(@plus, h.^2, v), v).*ph; MatrixXd eigen_dmu2 = ((eigen_l2_plus_s2.array().rowwise()+eigen_s2.array().transpose())*eigen_pl.array() - (eigen_h2_plus_s2.array().rowwise()+eigen_s2.array().transpose())*eigen_ph.array()).matrix(); //bsxfun(@times, ch-cl, (2.0*mu)) eigen_dmu2 += (eigen_cdf_diff.array().rowwise()*(2.0*eigen_mu).array().transpose()).matrix(); SGVector<float64_t> & gmu = result; Map<VectorXd> eigen_gmu(gmu.vector, gmu.vlen); //gmu = bsxfun(@times, dmu2, _a) + bsxfun(@times, pl.*l - ph.*h + ch - chl, b) + bsxfun(@times, pl - ph, c) //gmu = sum(gmu,1) eigen_gmu = ((eigen_dmu2.array().colwise()*eigen_a.array()) + ((eigen_weighted_pdf_diff + eigen_cdf_diff).array().colwise()*eigen_b.array()) + ( (eigen_pl - eigen_ph).array().colwise()*eigen_c.array())).colwise().sum().matrix(); Map<VectorXd>eigen_lab(m_lab.vector, m_lab.vlen); eigen_gmu = eigen_lab - eigen_gmu; } else { //Compute the derivative wrt sigma2 //gv_0 = bsxfun(@plus, l, -mu).*pl - bsxfun(@plus, h, -mu).*ph; MatrixXd eigen_gs2_0 = (((-eigen_mu).replicate(1,eigen_l.rows()).array().transpose().colwise() + eigen_l.array())*eigen_pl.array() - ((-eigen_mu).replicate(1,eigen_h.rows()).array().transpose().colwise() + eigen_h.array())*eigen_ph.array()).matrix(); //gv_0 = bsxfun(times, gv_0, c); eigen_gs2_0 = (eigen_gs2_0.array().colwise()*eigen_c.array()).matrix(); //tmpl = l2_plus_v - bsxfun(@times, l, mu) MatrixXd tmpl = (eigen_l2_plus_s2 - (eigen_mu.replicate(1,eigen_l.rows()).array().transpose().colwise()*eigen_l.array()).matrix() ).cwiseProduct(eigen_pl); //tmph = h2_plus_v - bsxfun(@times, h, mu) MatrixXd tmph = (eigen_h2_plus_s2 - (eigen_mu.replicate(1,eigen_h.rows()).array().transpose().colwise()*eigen_h.array()).matrix() ).cwiseProduct(eigen_ph); //gv_1 = bsxfun(@times, tmpl - tmph, b); MatrixXd eigen_gs2_1 = ((tmpl - tmph).array().colwise()*eigen_b.array()).matrix(); //gv_2 = bsxfun(@times, tmpl, l) - bsxfun(@times, tmph, h); MatrixXd eigen_gs2_2 = (tmpl.array().colwise()*eigen_l.array() - tmph.array().colwise()*eigen_h.array()).matrix(); //gv_2 = bsxfun(@times, gv_2, a); eigen_gs2_2 = (eigen_gs2_2.array().colwise()*eigen_a.array()).matrix(); SGVector<float64_t> & gs2 = result; Map<VectorXd> eigen_gs2(gs2.vector, gs2.vlen); //gv = (bsxfun(@times, ch - cl + 0.5*pl.*l - ph.*h, a) + bsxfun(@times, gv_0 + gv_1 + gv_2, 1.0/(2.0*v)) //gv = sum(gv,1); eigen_gs2 = ((eigen_cdf_diff + 0.5*eigen_weighted_pdf_diff).array().colwise()*eigen_a.array() + (eigen_gs2_0 + eigen_gs2_1 + eigen_gs2_2).array().rowwise()/(2.0*eigen_s2).array().transpose() ).colwise().sum().matrix(); //gv = -gv eigen_gs2 = -eigen_gs2; } eigen_l(0) = l_bak; eigen_h(eigen_h.size()-1) = h_bak; return result; }
SGVector<float64_t> CLogitVGPiecewiseBoundLikelihood::get_variational_expection() { //This function is based on the Matlab code, //function [f, gm, gv] = Ellp(m, v, bound, ind), to compute f //and the formula of the appendix const Map<VectorXd> eigen_c(m_bound.get_column_vector(0), m_bound.num_rows); const Map<VectorXd> eigen_b(m_bound.get_column_vector(1), m_bound.num_rows); const Map<VectorXd> eigen_a(m_bound.get_column_vector(2), m_bound.num_rows); const Map<VectorXd> eigen_mu(m_mu.vector, m_mu.vlen); const Map<VectorXd> eigen_s2(m_s2.vector, m_s2.vlen); Map<VectorXd> eigen_l(m_bound.get_column_vector(3), m_bound.num_rows); Map<VectorXd> eigen_h(m_bound.get_column_vector(4), m_bound.num_rows); index_t num_rows = m_bound.num_rows; index_t num_cols = m_mu.vlen; const Map<MatrixXd> eigen_cdf_diff(m_cdf_diff.matrix, num_rows, num_cols); const Map<MatrixXd> eigen_pl(m_pl.matrix, num_rows, num_cols); const Map<MatrixXd> eigen_ph(m_ph.matrix, num_rows, num_cols); float64_t l_bak = eigen_l(0); //l(1) = 0; eigen_l(0) = 0; float64_t h_bak = eigen_h(eigen_h.size()-1); //h(end) = 0; eigen_h(eigen_h.size()-1) = 0; //ex0 = ch-cl; const Map<MatrixXd> & eigen_ex0 = eigen_cdf_diff; //%ex1= v.*(pl-ph) + m.*(ch-cl); MatrixXd eigen_ex1 = ((eigen_pl - eigen_ph).array().rowwise()*eigen_s2.array().transpose() + eigen_cdf_diff.array().rowwise()*eigen_mu.array().transpose()).matrix(); //ex2 = bsxfun(@times, v, (bsxfun(@plus, l, m)).*pl - (bsxfun(@plus, h, m)).*ph) + bsxfun(@times, (v+m.^2), ex0); //bsxfun(@plus, l, m)).*pl - (bsxfun(@plus, h, m)).*ph MatrixXd eigen_ex2 = ((eigen_mu.replicate(1,eigen_l.rows()).array().transpose().colwise() + eigen_l.array())*eigen_pl.array() - (eigen_mu.replicate(1,eigen_h.rows()).array().transpose().colwise() + eigen_h.array())*eigen_ph.array()).matrix(); //bsxfun(@times, v, (bsxfun(@plus, l, m).*pl - bsxfun(@plus, h, m).*ph eigen_ex2 = (eigen_ex2.array().rowwise()*eigen_s2.array().transpose()).matrix(); //ex2 = bsxfun(@times, v, (bsxfun(@plus, l, m)).*pl - (bsxfun(@plus, h, m)).*ph) + bsxfun(@times, (v+m.^2), ex0); eigen_ex2 += (eigen_cdf_diff.array().rowwise()*(eigen_mu.array().pow(2) + eigen_s2.array()).transpose()).matrix(); SGVector<float64_t> f(m_mu.vlen); Map<VectorXd> eigen_f(f.vector, f.vlen); //%f = sum((a.*ex2 + b.*ex1 + c.*ex0),1); eigen_f = (eigen_ex2.array().colwise()*eigen_a.array() + eigen_ex1.array().colwise()*eigen_b.array() + eigen_ex0.array().colwise()*eigen_c.array()).colwise().sum().matrix(); eigen_l(0) = l_bak; eigen_h(eigen_h.size()-1) = h_bak; Map<VectorXd>eigen_lab(m_lab.vector, m_lab.vlen); eigen_f = eigen_lab.cwiseProduct(eigen_mu) - eigen_f; return f; }