22 #include <shogun/lib/external/brent.h>
27 using namespace Eigen;
32 #ifndef DOXYGEN_SHOULD_SKIP_THIS
34 class PsiLine :
public func_base
49 virtual double operator() (
double x)
55 (*alpha)=start_alpha+x*dalpha;
56 eigen_f=K*(*alpha)*
CMath::exp(log_scale*2.0)+eigen_m;
65 float64_t result = (*alpha).dot(eigen_f-eigen_m)/2.0-
76 virtual ~SingleLaplaceInferenceMethodCostFunction() {
SG_UNREF(m_obj); }
89 REQUIRE(m_obj,
"Object not set\n");
90 return m_obj->get_psi_wrt_alpha();
92 void unset_target(
bool is_unref)
102 REQUIRE(m_obj,
"Object not set\n");
104 return m_obj->m_alpha;
108 REQUIRE(m_obj,
"Object not set\n");
109 m_obj->get_gradient_wrt_alpha(m_derivatives);
110 return m_derivatives;
112 virtual const char* get_name()
const {
return "SingleLaplaceInferenceMethodCostFunction"; }
118 SG_ADD(&m_derivatives,
"SingleLaplaceInferenceMethodCostFunction__m_derivatives",
119 "derivatives in SingleLaplaceInferenceMethodCostFunction",
MS_NOT_AVAILABLE);
120 SG_ADD((
CSGObject **)&m_obj,
"SingleLaplaceInferenceMethodCostFunction__m_obj",
133 REQUIRE(obj,
"Obj must set\n");
152 void CSingleLaplaceNewtonOptimizer::init()
157 m_opt_tolerance=1e-6;
162 SG_ADD(&m_iter,
"CSingleLaplaceNewtonOptimizer__m_iter",
164 SG_ADD(&m_tolerance,
"CSingleLaplaceNewtonOptimizer__m_tolerance",
166 SG_ADD(&m_opt_tolerance,
"CSingleLaplaceNewtonOptimizer__m_opt_tolerance",
168 SG_ADD(&m_opt_max,
"CSingleLaplaceNewtonOptimizer__m_opt_max",
174 REQUIRE(m_obj,
"Object not set\n");
179 Map<VectorXd> eigen_mean( (m_obj->m_mean_f).vector, (m_obj->m_mean_f).vlen);
182 Map<MatrixXd> eigen_ktrtr( (m_obj->m_ktrtr).matrix, (m_obj->m_ktrtr).num_rows, (m_obj->m_ktrtr).num_cols);
187 m_obj->m_W=m_obj->m_model->get_log_probability_derivative_f(m_obj->m_labels, m_obj->m_mu, 2);
188 m_obj->m_W.scale(-1.0);
190 Map<VectorXd> eigen_alpha(m_obj->m_alpha.vector, m_obj->m_alpha.vlen);
193 m_obj->m_dlp=m_obj->m_model->get_log_probability_derivative_f(m_obj->m_labels, m_obj->m_mu, 1);
197 Map<VectorXd> eigen_sW((m_obj->m_sW).vector, (m_obj->m_sW).vlen);
201 while (Psi_Old-Psi_New>m_tolerance && iter<m_iter)
203 Map<VectorXd> eigen_W( (m_obj->m_W).vector, (m_obj->m_W).vlen);
204 Map<VectorXd> eigen_dlp( (m_obj->m_dlp).vector, (m_obj->m_dlp).vlen);
209 if (eigen_W.minCoeff() < 0)
225 eigen_W+=(2.0/df)*eigen_dlp.cwiseProduct(eigen_dlp);
229 eigen_sW=eigen_W.cwiseSqrt();
231 LLT<MatrixXd> L((eigen_sW*eigen_sW.transpose()).cwiseProduct(eigen_ktrtr*
CMath::exp((m_obj->m_log_scale)*2.0))+
232 MatrixXd::Identity( (m_obj->m_ktrtr).num_rows, (m_obj->m_ktrtr).num_cols));
234 VectorXd b=eigen_W.cwiseProduct(eigen_mu - eigen_mean)+eigen_dlp;
236 VectorXd dalpha=b-eigen_sW.cwiseProduct(
237 L.solve(eigen_sW.cwiseProduct(eigen_ktrtr*b*
CMath::exp((m_obj->m_log_scale)*2.0))))-eigen_alpha;
242 func.log_scale=m_obj->m_log_scale;
245 func.start_alpha=eigen_alpha;
246 func.alpha=&eigen_alpha;
247 func.dlp=&(m_obj->m_dlp);
248 func.f=&(m_obj->m_mu);
249 func.m=&(m_obj->m_mean_f);
250 func.W=&(m_obj->m_W);
251 func.lik=m_obj->m_model;
252 func.lab=m_obj->m_labels;
255 Psi_New=local_min(0, m_opt_max, m_opt_tolerance, func, x);
258 if (Psi_Old-Psi_New>m_tolerance && iter>=m_iter)
260 SG_SWARNING(
"Max iterations (%d) reached, but convergence level (%f) is not yet below tolerance (%f)\n", m_iter, Psi_Old-Psi_New, m_tolerance);
277 void CSingleLaplaceInferenceMethod::init()
302 SG_SERROR(
"Provided inference is not of type CSingleLaplaceInferenceMethod\n")
333 if (eigen_W.minCoeff()<0)
341 result=(eigen_alpha.dot(eigen_mu-eigen_mean))/2.0-
342 lp+log(lu.determinant())/2.0;
346 result=eigen_alpha.dot(eigen_mu-eigen_mean)/2.0-lp+
347 eigen_L.diagonal().array().log().sum();
363 MatrixXd eigen_V=eigen_L.triangularView<Upper>().adjoint().solve(
389 if (eigen_W.minCoeff()>0)
390 eigen_sW=eigen_W.cwiseSqrt();
393 eigen_sW=((eigen_W.array().abs()+eigen_W.array())/2).sqrt()-((eigen_W.array().abs()-eigen_W.array())/2).sqrt();
402 if (eigen_W.minCoeff() < 0)
405 FullPivLU<MatrixXd> lu(
412 eigen_L=eigen_W.asDiagonal()*eigen_L;
421 eigen_L = L.matrixU();
474 Psi_New=eigen_alpha.dot(eigen_mu-eigen_mean)/2.0-
480 if (Psi_Def < Psi_New)
493 REQUIRE(minimizer,
"Minimizer must set\n");
494 if (!dynamic_cast<CSingleLaplaceNewtonOptimizer*>(minimizer))
497 REQUIRE(opt,
"The provided minimizer is not supported\n")
509 if(this->ref_count()>1)
517 REQUIRE(minimizer,
"The provided minimizer is not supported\n");
520 cost_fun->set_target(
this);
521 if(this->ref_count()>1)
526 cost_fun->unset_target(cleanup);
562 if (eigen_W.minCoeff()<0)
577 eigen_Z=eigen_L.triangularView<Upper>().adjoint().solve(
579 eigen_Z=eigen_L.triangularView<Upper>().solve(eigen_Z);
580 eigen_Z=eigen_sW.asDiagonal()*eigen_Z;
583 MatrixXd C=eigen_L.triangularView<Upper>().adjoint().solve(
588 (C.cwiseProduct(C)).colwise().sum().adjoint())/2.0;
596 eigen_dfhat=eigen_g.cwiseProduct(eigen_d3lp);
602 REQUIRE(!strcmp(param->
m_name,
"log_scale"),
"Can't compute derivative of "
603 "the nagative log marginal likelihood wrt %s.%s parameter\n",
617 result[0]=(eigen_Z.cwiseProduct(eigen_K)).sum()/2.0-
618 (eigen_alpha.adjoint()*eigen_K).
dot(eigen_alpha)/2.0;
621 VectorXd b=eigen_K*eigen_dlp;
655 VectorXd b=eigen_K*eigen_dlp_dhyp;
658 result[0]=-eigen_g.dot(eigen_d2lp_dhyp)-eigen_lp_dhyp.sum()-
674 REQUIRE(param,
"Param not set\n");
676 int64_t len=
const_cast<TParameter *
>(param)->m_datatype.get_num_elements();
691 result[i]=(eigen_Z.cwiseProduct(eigen_dK)).sum()/2.0-
692 (eigen_alpha.adjoint()*eigen_dK).
dot(eigen_alpha)/2.0;
695 VectorXd b=eigen_dK*eigen_dlp;
715 REQUIRE(param,
"Param not set\n");
717 int64_t len=
const_cast<TParameter *
>(param)->m_datatype.get_num_elements();
732 result[i]=-eigen_alpha.dot(eigen_dmu)-eigen_dfhat.dot(eigen_dmu-
749 eigen_res=eigen_mu-eigen_mean;
770 float64_t psi = eigen_alpha.dot(eigen_f - eigen_mean_f) * 0.5;
778 "The length of gradients (%d) should the same as the length of parameters (%d)\n",
virtual SGVector< float64_t > get_log_probability_f(const CLabels *lab, SGVector< float64_t > func) const =0
virtual float64_t minimize()
virtual void update_alpha()
virtual void update_chol()
virtual void update_parameter_hash()
CSingleLaplaceInferenceMethod()
SGVector< float64_t > m_mu
Vector::Scalar dot(Vector a, Vector b)
The class Labels models labels, i.e. class assignments of objects.
static const float64_t INFTY
infinity
virtual EInferenceType get_inference_type() const
virtual SGVector< float64_t > get_second_derivative(const CLabels *lab, SGVector< float64_t > func, const TParameter *param) const
virtual int32_t get_num_labels() const =0
SGVector< float64_t > m_d2lp
The build-in minimizer for SingleLaplaceInference.
SGVector< float64_t > m_sW
virtual SGVector< float64_t > get_derivative_wrt_inference_method(const TParameter *param)
virtual void update_deriv()
virtual SGVector< float64_t > get_mean_vector(const CFeatures *features) const =0
float64_t get_degrees_freedom() const
An abstract class of the mean function.
void scale(T alpha)
Scale vector inplace.
SGMatrix< float64_t > m_ktrtr
virtual float64_t get_negative_log_marginal_likelihood()
void set_target(CSingleLaplaceInferenceMethod *obj)
static CSingleLaplaceInferenceMethod * obtain_from_generic(CInference *inference)
virtual ~CSingleLaplaceInferenceMethod()
SGMatrix< float64_t > m_Z
Class SGObject is the base class of all shogun objects.
virtual SGVector< float64_t > get_derivative_wrt_mean(const TParameter *param)
virtual void unset_cost_function(bool is_unref=true)
SGVector< float64_t > m_d3lp
virtual void update_init()
SGVector< float64_t > m_dlp
virtual SGVector< float64_t > get_diagonal_vector()
static T sum(T *vec, int32_t len)
Return sum(vec)
SGMatrix< float64_t > m_L
The first order cost function base class.
Matrix< float64_t,-1,-1, 0,-1,-1 > MatrixXd
virtual float64_t minimize()=0
virtual SGVector< float64_t > get_posterior_mean()
Class that models a Student's-t likelihood.
virtual SGVector< float64_t > get_derivative_wrt_kernel(const TParameter *param)
virtual void register_minimizer(Minimizer *minimizer)
friend class CSingleLaplaceNewtonOptimizer
virtual SGVector< float64_t > get_parameter_derivative(const CFeatures *features, const TParameter *param, index_t index=-1)
SGVector< float64_t > m_mean_f
float64_t get_psi_wrt_alpha()
all of classes and functions are contained in the shogun namespace
The Laplace approximation inference method base class.
The Inference Method base class.
friend class SingleLaplaceInferenceMethodCostFunction
SGMatrix< float64_t > m_Sigma
virtual void compute_gradient()
The class Features is the base class of all feature objects.
void unset_target(bool is_unref)
virtual const char * get_name() const
static float64_t exp(float64_t x)
virtual SGMatrix< float64_t > get_parameter_gradient(const TParameter *param, index_t index=-1)
SGVector< T > clone() const
virtual SGVector< float64_t > get_log_probability_derivative_f(const CLabels *lab, SGVector< float64_t > func, index_t i) const =0
SGVector< float64_t > m_W
static void inverse(SGMatrix< float64_t > matrix)
inverses square matrix in-place
virtual SGVector< float64_t > get_third_derivative(const CLabels *lab, SGVector< float64_t > func, const TParameter *param) const
SGVector< float64_t > m_dfhat
The minimizer base class.
SGVector< float64_t > m_g
static CStudentsTLikelihood * obtain_from_generic(CLikelihoodModel *likelihood)
virtual SGVector< float64_t > get_first_derivative(const CLabels *lab, SGVector< float64_t > func, const TParameter *param) const
The SingleLaplace approximation inference method class for regression and binary Classification.
CLikelihoodModel * m_model
virtual bool parameter_hash_changed()
The Likelihood model base class.
virtual SGVector< float64_t > get_derivative_wrt_likelihood_model(const TParameter *param)
virtual void set_cost_function(FirstOrderCostFunction *fun)
SGVector< float64_t > m_alpha
virtual void update_approx_cov()
void get_gradient_wrt_alpha(SGVector< float64_t > gradient)
The first order minimizer base class.
virtual void register_minimizer(Minimizer *minimizer)