Exemplo n.º 1
0
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;
}