SHOGUN  4.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
LogitLikelihood.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) The Shogun Machine Learning Toolbox
3  * Written (W) 2013 Roman Votyakov
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are those
27  * of the authors and should not be interpreted as representing official policies,
28  * either expressed or implied, of the Shogun Development Team.
29  *
30  */
32 
33 #ifdef HAVE_EIGEN3
34 
39 
40 using namespace shogun;
41 using namespace Eigen;
42 
43 namespace shogun
44 {
45 
46 #ifndef DOXYGEN_SHOULD_SKIP_THIS
47 
49 class CNormalPDF : public CFunction
50 {
51 public:
53  CNormalPDF()
54  {
55  m_mu=0.0;
56  m_sigma=1.0;
57  }
58 
64  CNormalPDF(float64_t mu, float64_t sigma)
65  {
66  m_mu=mu;
67  m_sigma=sigma;
68  }
69 
74  void set_mu(float64_t mu) { m_mu=mu; }
75 
80  void set_sigma(float64_t sigma) { m_sigma=sigma; }
81 
88  virtual float64_t operator() (float64_t x)
89  {
90  return (1.0/(CMath::sqrt(2*CMath::PI)*m_sigma))*
91  CMath::exp(-CMath::sq(x-m_mu)/(2.0*CMath::sq(m_sigma)));
92  }
93 
94 private:
95  /* mean */
96  float64_t m_mu;
97 
98  /* standard deviation */
99  float64_t m_sigma;
100 };
101 
103 class CSigmoidFunction : public CFunction
104 {
105 public:
107  CSigmoidFunction()
108  {
109  m_a=0.0;
110  }
111 
116  CSigmoidFunction(float64_t a)
117  {
118  m_a=a;
119  }
120 
125  void set_a(float64_t a) { m_a=a; }
126 
133  virtual float64_t operator() (float64_t x)
134  {
135  return 1.0/(1.0+CMath::exp(-m_a*x));
136  }
137 
138 private:
140  float64_t m_a;
141 };
142 
144 class CProductFunction : public CFunction
145 {
146 public:
152  CProductFunction(CFunction* f, CFunction* g)
153  {
154  SG_REF(f);
155  SG_REF(g);
156  m_f=f;
157  m_g=g;
158  }
159 
160  virtual ~CProductFunction()
161  {
162  SG_UNREF(m_f);
163  SG_UNREF(m_g);
164  }
165 
172  virtual float64_t operator() (float64_t x)
173  {
174  return (*m_f)(x)*(*m_g)(x);
175  }
176 
177 private:
179  CFunction* m_f;
181  CFunction* m_g;
182 };
183 
185 class CLinearFunction : public CFunction
186 {
187 public:
189  CLinearFunction() { }
190 
191  virtual ~CLinearFunction() { }
192 
199  virtual float64_t operator() (float64_t x)
200  {
201  return x;
202  }
203 };
204 
206 class CQuadraticFunction : public CFunction
207 {
208 public:
210  CQuadraticFunction() { }
211 
212  virtual ~CQuadraticFunction() { }
213 
220  virtual float64_t operator() (float64_t x)
221  {
222  return CMath::sq(x);
223  }
224 };
225 
226 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
227 
229 {
230 }
231 
233 {
234 }
235 
237  SGVector<float64_t> mu, SGVector<float64_t> s2, const CLabels* lab) const
238 {
240  Map<VectorXd> eigen_lp(lp.vector, lp.vlen);
241 
243  Map<VectorXd> eigen_r(r.vector, r.vlen);
244 
245  // evaluate predictive mean: ymu=2*p-1
246  // Note that the distribution is Bernoulli distribution with p(x=1)=p and
247  // p(x=-1)=(1-p)
248  // the mean of the Bernoulli distribution is 2*p-1
249  eigen_r=2.0*eigen_lp.array().exp()-1.0;
250 
251  return r;
252 }
253 
255  SGVector<float64_t> mu, SGVector<float64_t> s2, const CLabels* lab) const
256 {
258  Map<VectorXd> eigen_lp(lp.vector, lp.vlen);
259 
261  Map<VectorXd> eigen_r(r.vector, r.vlen);
262 
263  // evaluate predictive variance: ys2=1-(2*p-1).^2
264  // Note that the distribution is Bernoulli distribution with p(x=1)=p and
265  // p(x=-1)=(1-p)
266  // the variance of the Bernoulli distribution is 1-(2*p-1).^2
267  eigen_r=1-(2.0*eigen_lp.array().exp()-1.0).square();
268 
269  return r;
270 }
271 
273  SGVector<float64_t> func) const
274 {
275  // check the parameters
276  REQUIRE(lab, "Labels are required (lab should not be NULL)\n")
278  "Labels must be type of CBinaryLabels\n")
279  REQUIRE(lab->get_num_labels()==func.vlen, "Number of labels must match "
280  "length of the function vector\n")
281 
282  SGVector<float64_t> y=((CBinaryLabels*)lab)->get_labels();
283  Map<VectorXd> eigen_y(y.vector, y.vlen);
284 
285  Map<VectorXd> eigen_f(func.vector, func.vlen);
286 
287  SGVector<float64_t> r(func.vlen);
288  Map<VectorXd> eigen_r(r.vector, r.vlen);
289 
290  // compute log probability: -log(1+exp(-f.*y))
291  eigen_r=-(1.0+(-eigen_y.array()*eigen_f.array()).exp()).log();
292 
293  return r;
294 }
295 
297  const CLabels* lab, SGVector<float64_t> func, index_t i) const
298 {
299  // check the parameters
300  REQUIRE(lab, "Labels are required (lab should not be NULL)\n")
302  "Labels must be type of CBinaryLabels\n")
303  REQUIRE(lab->get_num_labels()==func.vlen, "Number of labels must match "
304  "length of the function vector\n")
305  REQUIRE(i>=1 && i<=3, "Index for derivative should be 1, 2 or 3\n")
306 
307  SGVector<float64_t> y=((CBinaryLabels*)lab)->get_labels();
308  Map<VectorXd> eigen_y(y.vector, y.vlen);
309 
310  Map<VectorXd> eigen_f(func.vector, func.vlen);
311 
312  SGVector<float64_t> r(func.vlen);
313  Map<VectorXd> eigen_r(r.vector, r.vlen);
314 
315  // compute s(f)=1./(1+exp(-f))
316  VectorXd eigen_s=(VectorXd::Ones(func.vlen)).cwiseQuotient((1.0+
317  (-eigen_f).array().exp()).matrix());
318 
319  // compute derivatives of log probability wrt f
320  if (i == 1)
321  {
322  // compute the first derivative: dlp=(y+1)/2-s(f)
323  eigen_r=(eigen_y.array()+1.0)/2.0-eigen_s.array();
324  }
325  else if (i == 2)
326  {
327  // compute the second derivative: d2lp=-s(f).*(1-s(f))
328  eigen_r=-eigen_s.array()*(1.0-eigen_s.array());
329  }
330  else if (i == 3)
331  {
332  // compute the third derivative: d2lp=-s(f).*(1-s(f)).*(1-2*s(f))
333  eigen_r=-eigen_s.array()*(1.0-eigen_s.array())*(1.0-2.0*eigen_s.array());
334  }
335  else
336  {
337  SG_ERROR("Invalid index for derivative\n")
338  }
339 
340  return r;
341 }
342 
344  SGVector<float64_t> mu, SGVector<float64_t> s2, const CLabels* lab) const
345 {
347 
348  if (lab)
349  {
350  REQUIRE((mu.vlen==s2.vlen) && (mu.vlen==lab->get_num_labels()),
351  "Length of the vector of means (%d), length of the vector of "
352  "variances (%d) and number of labels (%d) should be the same\n",
353  mu.vlen, s2.vlen, lab->get_num_labels())
355  "Labels must be type of CBinaryLabels\n")
356 
357  y=((CBinaryLabels*)lab)->get_labels();
358  }
359  else
360  {
361  REQUIRE(mu.vlen==s2.vlen, "Length of the vector of means (%d) and "
362  "length of the vector of variances (%d) should be the same\n",
363  mu.vlen, s2.vlen)
364 
366  y.set_const(1.0);
367  }
368 
369  // create an object of normal pdf function
370  CNormalPDF* f=new CNormalPDF();
371 
372  // create an object of sigmoid function
373  CSigmoidFunction* g=new CSigmoidFunction();
374 
375  // create an object of product of sigmoid and normal pdf functions
376  CProductFunction* h=new CProductFunction(f, g);
377  SG_REF(h);
378 
379  // compute probabilities using numerical integration
381 
382  for (index_t i=0; i<mu.vlen; i++)
383  {
384  // set normal pdf parameters
385  f->set_mu(mu[i]);
386  f->set_sigma(CMath::sqrt(s2[i]));
387 
388  // set sigmoid parameters
389  g->set_a(y[i]);
390 
391  // evaluate integral on (-inf, inf)
394  }
395 
396  SG_UNREF(h);
397 
398  for (index_t i=0; i<r.vlen; i++)
399  r[i]=CMath::log(r[i]);
400 
401  return r;
402 }
403 
405  SGVector<float64_t> s2, const CLabels *lab, index_t i) const
406 {
407  // check the parameters
408  REQUIRE(lab, "Labels are required (lab should not be NULL)\n")
409  REQUIRE((mu.vlen==s2.vlen) && (mu.vlen==lab->get_num_labels()),
410  "Length of the vector of means (%d), length of the vector of "
411  "variances (%d) and number of labels (%d) should be the same\n",
412  mu.vlen, s2.vlen, lab->get_num_labels())
413  REQUIRE(i>=0 && i<=mu.vlen, "Index (%d) out of bounds!\n", i)
415  "Labels must be type of CBinaryLabels\n")
416 
417  SGVector<float64_t> y=((CBinaryLabels*)lab)->get_labels();
418 
419  // create an object of f(x)=N(x|mu,sigma^2)
420  CNormalPDF* f=new CNormalPDF(mu[i], CMath::sqrt(s2[i]));
421 
422  // create an object of g(x)=sigmoid(x)
423  CSigmoidFunction* g=new CSigmoidFunction(y[i]);
424 
425  // create an object of h(x)=N(x|mu,sigma^2)*sigmoid(x)
426  CProductFunction* h=new CProductFunction(f, g);
427 
428  // create an object of l(x)=x
429  CLinearFunction* l=new CLinearFunction();
430 
431  // create an object of k(x)=x*N(x|mu,sigma^2)*sigmoid(x)
432  CProductFunction* k=new CProductFunction(l, h);
433  SG_REF(k);
434 
435  // compute Z = \int N(x|mu,sigma)*sigmoid(a*x) dx
438 
439  // compute 1st moment: E[x] = Z^-1 * \int x*N(x|mu,sigma)*sigmoid(a*x)dx
442 
443  SG_UNREF(k);
444 
445  return Ex;
446 }
447 
449  SGVector<float64_t> s2, const CLabels *lab, index_t i) const
450 {
451  // check the parameters
452  REQUIRE(lab, "Labels are required (lab should not be NULL)\n")
453  REQUIRE((mu.vlen==s2.vlen) && (mu.vlen==lab->get_num_labels()),
454  "Length of the vector of means (%d), length of the vector of "
455  "variances (%d) and number of labels (%d) should be the same\n",
456  mu.vlen, s2.vlen, lab->get_num_labels())
457  REQUIRE(i>=0 && i<=mu.vlen, "Index (%d) out of bounds!\n", i)
459  "Labels must be type of CBinaryLabels\n")
460 
461  SGVector<float64_t> y=((CBinaryLabels*)lab)->get_labels();
462 
463  // create an object of f(x)=N(x|mu,sigma^2)
464  CNormalPDF* f=new CNormalPDF(mu[i], CMath::sqrt(s2[i]));
465 
466  // create an object of g(x)=sigmoid(a*x)
467  CSigmoidFunction* g=new CSigmoidFunction(y[i]);
468 
469  // create an object of h(x)=N(x|mu,sigma^2)*sigmoid(a*x)
470  CProductFunction* h=new CProductFunction(f, g);
471 
472  // create an object of l(x)=x
473  CLinearFunction* l=new CLinearFunction();
474 
475  // create an object of k(x)=x*N(x|mu,sigma^2)*sigmoid(a*x)
476  CProductFunction* k=new CProductFunction(l, h);
477  SG_REF(k);
478 
479  // create an object of q(x)=x^2
480  CQuadraticFunction* q=new CQuadraticFunction();
481 
482  // create an object of p(x)=x^2*N(x|mu,sigma^2)*sigmoid(x)
483  CProductFunction* p=new CProductFunction(q, h);
484  SG_REF(p);
485 
486  // compute Z = \int N(x|mu,sigma)*sigmoid(a*x) dx
489 
490  // compute 1st moment: E[x] = Z^-1 * \int x*N(x|mu,sigma)*sigmoid(a*x)dx
493 
494  // compute E[x^2] = Z^-1 * \int x^2*N(x|mu,sigma)*sigmoid(a*x)dx
497 
498  SG_UNREF(k);
499  SG_UNREF(p);
500 
501  // return 2nd moment: Var[x]=E[x^2]-E[x]^2
502  return Ex2-CMath::sq(Ex);;
503 }
504 }
505 
506 #endif /* HAVE_EIGEN3 */
virtual SGVector< float64_t > get_predictive_means(SGVector< float64_t > mu, SGVector< float64_t > s2, const CLabels *lab=NULL) const
virtual SGVector< float64_t > get_predictive_variances(SGVector< float64_t > mu, SGVector< float64_t > s2, const CLabels *lab=NULL) const
virtual ELabelType get_label_type() const =0
binary labels +1/-1
Definition: LabelTypes.h:18
int32_t index_t
Definition: common.h:62
static float64_t integrate_quadgk(CFunction *f, float64_t a, float64_t b, float64_t abs_tol=1e-10, float64_t rel_tol=1e-5, uint32_t max_iter=1000, index_t sn=10)
The class Labels models labels, i.e. class assignments of objects.
Definition: Labels.h:43
static const float64_t INFTY
infinity
Definition: Math.h:2048
virtual int32_t get_num_labels() const =0
static T sq(T x)
Definition: Math.h:450
Definition: SGMatrix.h:20
#define SG_ERROR(...)
Definition: SGIO.h:129
#define REQUIRE(x,...)
Definition: SGIO.h:206
#define SG_REF(x)
Definition: SGObject.h:51
virtual float64_t get_second_moment(SGVector< float64_t > mu, SGVector< float64_t > s2, const CLabels *lab, index_t i) const
Class of a function of one variable.
Definition: Function.h:22
index_t vlen
Definition: SGVector.h:494
virtual SGVector< float64_t > get_log_probability_derivative_f(const CLabels *lab, SGVector< float64_t > func, index_t i) const
virtual SGVector< float64_t > get_log_zeroth_moments(SGVector< float64_t > mu, SGVector< float64_t > s2, const CLabels *lab) const
double float64_t
Definition: common.h:50
#define SG_UNREF(x)
Definition: SGObject.h:52
all of classes and functions are contained in the shogun namespace
Definition: class_list.h:18
static float64_t exp(float64_t x)
Definition: Math.h:621
static float64_t log(float64_t v)
Definition: Math.h:922
virtual float64_t get_first_moment(SGVector< float64_t > mu, SGVector< float64_t > s2, const CLabels *lab, index_t i) const
Binary Labels for binary classification.
Definition: BinaryLabels.h:37
virtual SGVector< float64_t > get_log_probability_f(const CLabels *lab, SGVector< float64_t > func) const
static float32_t sqrt(float32_t x)
Definition: Math.h:459
The Likelihood model base class.
void set_const(T const_elem)
Definition: SGVector.cpp:152
static const float64_t PI
Definition: Math.h:2055

SHOGUN Machine Learning Toolbox - Documentation