49 using namespace Eigen;
53 #ifndef DOXYGEN_SHOULD_SKIP_THIS
54 class KLDualInferenceMethodCostFunction:
public FirstOrderCostFunction
56 friend class CKLDualInferenceMethodMinimizer;
58 KLDualInferenceMethodCostFunction():FirstOrderCostFunction() { init(); }
59 virtual ~KLDualInferenceMethodCostFunction() {
SG_UNREF(m_obj); }
60 void set_target(CKLDualInferenceMethod *obj)
70 void unset_target(
bool is_unref)
80 REQUIRE(m_obj,
"Object not set\n");
81 bool status=m_obj->precompute();
84 float64_t nlml=m_obj->get_dual_objective_wrt_parameters();
87 return CMath::NOT_A_NUMBER;
89 virtual SGVector<float64_t> obtain_variable_reference()
91 REQUIRE(m_obj,
"Object not set\n");
92 m_derivatives = SGVector<float64_t>((m_obj->m_W).vlen);
95 virtual SGVector<float64_t> get_gradient()
97 REQUIRE(m_obj,
"Object not set\n");
98 m_obj->get_gradient_of_dual_objective_wrt_parameters(m_derivatives);
101 virtual const char* get_name()
const {
return "KLDualInferenceMethodCostFunction"; }
103 SGVector<float64_t> m_derivatives;
107 m_derivatives = SGVector<float64_t>();
108 SG_ADD(&m_derivatives,
"KLDualInferenceMethodCostFunction__m_derivatives",
110 SG_ADD((CSGObject **)&m_obj,
"KLDualInferenceMethodCostFunction__m_obj",
113 CKLDualInferenceMethod *m_obj;
114 CDualVariationalGaussianLikelihood* get_dual_variational_likelihood()
const
116 REQUIRE(m_obj,
"Object not set\n");
117 return m_obj->get_dual_variational_likelihood();
120 #endif //DOXYGEN_SHOULD_SKIP_THIS
122 void CKLDualInferenceMethodMinimizer::init_minimization()
124 ELBFGSLineSearch linesearch=LBFGSLineSearchHelper::get_lbfgs_linear_search(m_linesearch_id);
128 "The provided line search method is not supported. Please use backtracking line search methods\n");
129 CLBFGSMinimizer::init_minimization();
137 lbfgs_param.
linesearch = LBFGSLineSearchHelper::get_lbfgs_linear_search(m_linesearch_id);
139 lbfgs_param.
delta = m_delta;
140 lbfgs_param.
past = m_past;
141 lbfgs_param.
epsilon = m_epsilon;
144 lbfgs_param.
ftol = m_ftol;
145 lbfgs_param.
wolfe = m_wolfe;
146 lbfgs_param.
gtol = m_gtol;
147 lbfgs_param.
xtol = m_xtol;
155 int error_code=
lbfgs(m_target_variable.vlen, m_target_variable.vector,
156 &cost, CKLDualInferenceMethodMinimizer::evaluate,
157 NULL,
this, &lbfgs_param, CKLDualInferenceMethodMinimizer::adjust_step);
161 SG_SWARNING(
"Error(s) happened during L-BFGS optimization (error code:%d)\n",
167 float64_t CKLDualInferenceMethodMinimizer::evaluate(
void *obj,
const float64_t *variable,
174 REQUIRE(obj_prt,
"The instance object passed to L-BFGS optimizer should not be NULL\n");
177 if (CMath::is_nan(cost) || CMath::is_infinity(cost))
182 "The length of gradient (%d) and the length of variable (%d) do not match\n",
189 float64_t CKLDualInferenceMethodMinimizer::adjust_step(
void *obj,
const float64_t *parameters,
193 CKLDualInferenceMethodMinimizer * obj_prt
194 =
static_cast<CKLDualInferenceMethodMinimizer *
>(obj);
196 REQUIRE(obj_prt,
"The instance object passed to L-BFGS optimizer should not be NULL\n");
199 SGVector<float64_t> sg_direction(non_const_direction, dim,
false);
201 KLDualInferenceMethodCostFunction* fun=
dynamic_cast<KLDualInferenceMethodCostFunction*
>(obj_prt->m_fun);
202 REQUIRE(fun,
"The cost function must be KLDualInferenceMethodCostFunction\n");
204 CDualVariationalGaussianLikelihood* lik=fun->get_dual_variational_likelihood();
206 float64_t adjust_stp=lik->adjust_step_wrt_dual_parameter(sg_direction, step);
230 SG_SERROR(
"Provided inference is not of type CKLDualInferenceMethod!\n");
254 "The provided likelihood model is not a variational dual Likelihood model.\n");
273 REQUIRE(opt,
"The minimizer must be an instance of CKLDualInferenceMethodMinimizer\n");
278 void CKLDualInferenceMethod::init()
284 "Square root of noise matrix W",
287 "the gradient of the variational expection wrt sigma2",
290 "the gradient of the variational expection wrt mu",
292 SG_ADD(&m_is_dual_valid,
"is_dual_valid",
293 "whether the lambda (m_W) is valid or not",
296 m_is_dual_valid=
false;
309 if (!m_is_dual_valid)
315 eigen_alpha=-eigen_alpha;
318 eigen_sW=eigen_W.array().sqrt().matrix();
325 eigen_V=eigen_L.triangularView<Upper>().adjoint().solve(eigen_sW.asDiagonal()*eigen_K*
CMath::exp(
m_log_scale*2.0));
329 eigen_s2=(eigen_K.diagonal().array()*
CMath::exp(
m_log_scale*2.0)-(eigen_V.array().pow(2).colwise().sum().transpose())).abs().matrix();
342 if (!m_is_dual_valid)
354 float64_t result=0.5*eigen_alpha.dot(eigen_mu-eigen_mean)+a;
355 result+=eigen_mean.dot(eigen_alpha);
356 result-=eigen_L.diagonal().array().log().sum();
364 "The length of gradients (%d) should the same as the length of parameters (%d)\n",
367 if (!m_is_dual_valid)
380 eigen_gradient=-eigen_mu-0.5*eigen_s2+eigen_d_lambda;
403 MatrixXd eigen_t=eigen_L.triangularView<Upper>().adjoint().solve(MatrixXd::Identity(eigen_L.rows(),eigen_L.cols()));
405 for(
index_t idx=0; idx<eigen_t.rows(); idx++)
406 trace +=(eigen_t.col(idx).array().pow(2)).sum();
409 float64_t result=-a+eigen_L.diagonal().array().log().
sum();
411 result+=0.5*(-eigen_K.rows()+eigen_alpha.dot(eigen_mu-eigen_mean)+trace);
439 MatrixXd eigen_U=eigen_L.triangularView<Upper>().adjoint().solve(
MatrixXd(eigen_sW.asDiagonal()));
442 MatrixXd eigen_A=MatrixXd::Identity(len, len)-eigen_V.transpose()*eigen_U;
448 VectorXd z=AdK.diagonal()+(eigen_A.array()*AdK.array()).rowwise().sum().matrix()
449 -(eigen_A.transpose().array()*AdK.array()).colwise().sum().transpose().matrix();
451 float64_t result=eigen_alpha.dot(eigen_dK*(eigen_alpha/2.0-eigen_df))-z.dot(eigen_dv);
473 eigen_sW=eigen_W.array().sqrt().matrix();
482 eigen_alpha=-eigen_alpha;
494 eigen_s2=(eigen_K.diagonal().array()*
CMath::exp(
m_log_scale*2.0)-(eigen_V.array().pow(2).colwise().sum().transpose())).abs().matrix();
498 nlml_def=get_nlml_wrapper(alpha_tmp, mu_tmp, L_tmp);
500 if (nlml_new<=nlml_def)
538 REQUIRE(minimizer,
"The minimizer must be an instance of KLDualInferenceMethodMinimizer\n");
540 cost_fun->set_target(
this);
543 if(this->ref_count()>1)
549 cost_fun->unset_target(cleanup);
virtual SGVector< float64_t > get_gradient()=0
virtual bool precompute()
friend class KLDualInferenceMethodCostFunction
virtual CDualVariationalGaussianLikelihood * get_dual_variational_likelihood() const
int32_t lbfgs(int32_t n, float64_t *x, float64_t *ptr_fx, lbfgs_evaluate_t proc_evaluate, lbfgs_progress_t proc_progress, void *instance, lbfgs_parameter_t *_param, lbfgs_adjust_step_t proc_adjust_step)
virtual void set_dual_parameters(SGVector< float64_t > the_lambda, const CLabels *lab)
static SGMatrix< float64_t > get_choleksy(SGVector< float64_t > W, SGVector< float64_t > sW, SGMatrix< float64_t > kernel, float64_t scale)
virtual SGVector< float64_t > get_mu_dual_parameter() const =0
The class Labels models labels, i.e. class assignments of objects.
static const float64_t INFTY
infinity
virtual EInferenceType get_inference_type() const
virtual int32_t get_num_labels() const =0
static SGMatrix< float64_t > get_inverse(SGMatrix< float64_t > L, SGMatrix< float64_t > kernel, SGVector< float64_t > sW, SGMatrix< float64_t > V, float64_t scale)
virtual bool dual_parameters_valid() const
TParameter * get_parameter(int32_t idx)
virtual void set_model(CLikelihoodModel *mod)
FirstOrderCostFunction * m_fun
virtual SGVector< float64_t > get_dual_objective_value()=0
virtual SGVector< float64_t > get_mean_vector(const CFeatures *features) const =0
Build-in minimizer for KLDualInference.
An abstract class of the mean function.
SGMatrix< float64_t > m_ktrtr
virtual void check_dual_inference(CLikelihoodModel *mod) const
The dual KL approximation inference method class.
virtual void register_minimizer(Minimizer *minimizer)
virtual void update_chol()
void set_model(CLikelihoodModel *mod)
The KL approximation inference method class.
virtual void get_gradient_of_dual_objective_wrt_parameters(SGVector< float64_t > gradient)
virtual void update_approx_cov()
virtual SGVector< float64_t > get_alpha()
virtual void unset_cost_function(bool is_unref=true)
static CKLDualInferenceMethod * obtain_from_generic(CInference *inference)
virtual bool set_variational_distribution(SGVector< float64_t > mu, SGVector< float64_t > s2, const CLabels *lab)
virtual SGVector< float64_t > get_dual_first_derivative(const TParameter *param) const =0
SGVector< float64_t > m_mu
static T sum(T *vec, int32_t len)
Return sum(vec)
SGMatrix< float64_t > m_L
virtual void update_deriv()
Matrix< float64_t,-1,-1, 0,-1,-1 > MatrixXd
virtual float64_t get_cost()=0
SGMatrix< float64_t > m_Sigma
virtual float64_t get_derivative_related_cov(SGMatrix< float64_t > dK)
virtual SGVector< float64_t > get_variational_expection()
virtual void register_minimizer(Minimizer *minimizer)
SGVector< float64_t > m_s2
all of classes and functions are contained in the shogun namespace
The Inference Method base class.
virtual float64_t optimization()
The class Features is the base class of all feature objects.
static float64_t exp(float64_t x)
Binary Labels for binary classification.
virtual float64_t minimize()
The minimizer base class.
virtual float64_t get_dual_objective_wrt_parameters()
virtual void update_alpha()
virtual float64_t get_negative_log_marginal_likelihood_helper()
virtual SGVector< float64_t > get_diagonal_vector()
CLikelihoodModel * m_model
virtual SGVector< float64_t > get_variational_first_derivative(const TParameter *param) const
virtual bool parameter_hash_changed()
Class that models dual variational likelihood.
The Likelihood model base class.
static const float64_t NOT_A_NUMBER
not a number
virtual void set_cost_function(FirstOrderCostFunction *fun)
virtual ~CKLDualInferenceMethod()
SGVector< float64_t > m_alpha