SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExactInferenceMethod.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Copyright (C) 2012 Jacob Walker
8  *
9  * Code adapted from Gaussian Process Machine Learning Toolbox
10  * http://www.gaussianprocess.org/gpml/code/matlab/doc/
11  *
12  */
13 #include <shogun/lib/config.h>
14 #ifdef HAVE_EIGEN3
15 #ifdef HAVE_LAPACK
16 
24 
25 using namespace shogun;
26 
28 {
29  update_all();
31 }
32 
34  CMeanFunction* m, CLabels* lab, CLikelihoodModel* mod) :
35  CInferenceMethod(kern, feat, m, lab, mod)
36 {
37  update_all();
38 }
39 
41 {
42 }
43 
45 {
46  if (m_labels)
48  ((CRegressionLabels*) m_labels)->get_labels().clone();
49 
52  ((CDotFeatures*)m_features)->get_computed_dot_feature_matrix();
53 
55  {
56  CDotFeatures* feat =
58  get_first_feature_obj();
59 
60  if (feat->get_num_vectors())
62 
63  SG_UNREF(feat);
64  }
65 
67 
68  if (m_kernel)
70 
72  {
73  update_chol();
74  update_alpha();
75  }
76 }
77 
78 void CExactInferenceMethod::check_members()
79 {
80  if (!m_labels)
81  SG_ERROR("No labels set\n");
82 
84  SG_ERROR("Expected RegressionLabels\n");
85 
86  if (!m_features)
87  SG_ERROR("No features set!\n");
88 
90  SG_ERROR("Number of training vectors does not match number of labels\n");
91 
93  {
94  CDotFeatures* feat =
96  get_first_feature_obj();
97 
98  if (!feat->has_property(FP_DOT))
99  SG_ERROR("Specified features are not of type CFeatures\n");
100 
101  if (feat->get_feature_class() != C_DENSE)
102  SG_ERROR("Expected Simple Features\n");
103 
104  if (feat->get_feature_type() != F_DREAL)
105  SG_ERROR("Expected Real Features\n");
106 
107  SG_UNREF(feat);
108  }
109 
110  else
111  {
113  SG_ERROR("Specified features are not of type CFeatures\n");
114 
116  SG_ERROR("Expected Simple Features\n");
117 
119  SG_ERROR("Expected Real Features\n");
120  }
121 
122  if (!m_kernel)
123  SG_ERROR( "No kernel assigned!\n");
124 
125  if (!m_mean)
126  SG_ERROR( "No mean function assigned!\n");
127 
129  {
130  SG_ERROR("Exact Inference Method can only use " \
131  "Gaussian Likelihood Function.\n");
132  }
133 }
134 
137  CSGObject*>& para_dict)
138 {
139  check_members();
140 
142  update_all();
143 
144  //Get the sigma variable from the likelihood model
145  float64_t m_sigma =
146  dynamic_cast<CGaussianLikelihood*>(m_model)->get_sigma();
147 
148  //Placeholder Matrix
150 
151  //Placeholder Matrix
153 
154  //Derivative Matrix
156 
157  //Vector used to fill diagonal of Matrix.
158  SGVector<float64_t> diagonal(temp1.num_rows);
159  SGVector<float64_t> diagonal2(temp2.num_rows);
160 
161  diagonal.fill_vector(diagonal.vector, temp1.num_rows, 1.0);
162  diagonal2.fill_vector(diagonal2.vector, temp2.num_rows, 0.0);
163 
164  temp1.create_diagonal_matrix(temp1.matrix, diagonal.vector, temp1.num_rows);
165  Q.create_diagonal_matrix(Q.matrix, diagonal.vector, temp2.num_rows);
166  temp2.create_diagonal_matrix(temp2.matrix, diagonal2.vector, temp2.num_rows);
167 
168  memcpy(temp1.matrix, m_L.matrix,
169  m_L.num_cols*m_L.num_rows*sizeof(float64_t));
170 
171  //Solve (L) Q = Identity for Q.
172  clapack_dpotrs(CblasColMajor, CblasUpper,
173  temp1.num_rows, Q.num_cols, temp1.matrix, temp1.num_cols,
174  Q.matrix, Q.num_cols);
175 
176  //Calculate alpha*alpha'
177  cblas_dger(CblasColMajor, m_alpha.vlen, m_alpha.vlen,
178  1.0, m_alpha.vector, 1, m_alpha.vector, 1,
179  temp2.matrix, m_alpha.vlen);
180 
181  temp1.create_diagonal_matrix(temp1.matrix, diagonal.vector, temp1.num_rows);
182 
183  //Subtracct alpha*alpha' from Q.
184  cblas_dsymm(CblasColMajor, CblasLeft, CblasUpper,
185  temp1.num_rows, temp1.num_cols, 1.0/(m_sigma*m_sigma),
186  Q.matrix, temp1.num_cols,
187  temp1.matrix, temp1.num_cols, -1.0,
188  temp2.matrix, temp2.num_cols);
189 
190  memcpy(Q.matrix, temp2.matrix,
191  temp2.num_cols*temp2.num_rows*sizeof(float64_t));
192 
193  float64_t sum = 0;
194 
197 
198  //This will be the vector we return
200  3+para_dict.get_num_elements(),
201  3+para_dict.get_num_elements());
202 
203  for (index_t i = 0; i < para_dict.get_num_elements(); i++)
204  {
205  shogun::CMapNode<TParameter*, CSGObject*>* node =
206  para_dict.get_node_ptr(i);
207 
208  TParameter* param = node->key;
209  CSGObject* obj = node->data;
210 
211  index_t length = 1;
212 
213  if ((param->m_datatype.m_ctype== CT_VECTOR ||
214  param->m_datatype.m_ctype == CT_SGVECTOR) &&
215  param->m_datatype.m_length_y != NULL)
216  length = *(param->m_datatype.m_length_y);
217 
218  SGVector<float64_t> variables(length);
219 
220  bool deriv_found = false;
221 
222  for (index_t g = 0; g < length; g++)
223  {
224 
225  SGMatrix<float64_t> deriv;
226  SGVector<float64_t> mean_derivatives;
227 
228  if (param->m_datatype.m_ctype == CT_VECTOR ||
229  param->m_datatype.m_ctype == CT_SGVECTOR)
230  {
231  deriv = m_kernel->get_parameter_gradient(param, obj, g);
232  mean_derivatives = m_mean->get_parameter_derivative(
233  param, obj, m_feature_matrix, g);
234  }
235 
236  else
237  {
238  mean_derivatives = m_mean->get_parameter_derivative(
239  param, obj, m_feature_matrix);
240 
241  deriv = m_kernel->get_parameter_gradient(param, obj);
242  }
243 
244  sum = 0;
245 
246 
247  if (deriv.num_cols*deriv.num_rows > 0)
248  {
249  for (index_t k = 0; k < Q.num_rows; k++)
250  {
251  for (index_t j = 0; j < Q.num_cols; j++)
252  sum += Q(k,j)*deriv(k,j)*m_scale*m_scale;
253  }
254 
255  sum /= 2.0;
256  variables[g] = sum;
257  deriv_found = true;
258  }
259 
260  else if (mean_derivatives.vlen > 0)
261  {
262  sum = mean_derivatives.dot(mean_derivatives.vector,
264  variables[g] = sum;
265  deriv_found = true;
266  }
267 
268 
269  }
270 
271  if (deriv_found)
272  gradient.add(param, variables);
273 
274  }
275 
276  TParameter* param;
277  index_t index = get_modsel_param_index("scale");
279 
280  sum = 0;
281 
282  for (index_t i = 0; i < Q.num_rows; i++)
283  {
284  for (index_t j = 0; j < Q.num_cols; j++)
285  sum += Q(i,j)*m_ktrtr(i,j)*m_scale*2.0;
286  }
287 
288  sum /= 2.0;
289 
290  SGVector<float64_t> scale(1);
291 
292  scale[0] = sum;
293 
294  gradient.add(param, scale);
295  para_dict.add(param, this);
296 
297  index = m_model->get_modsel_param_index("sigma");
299 
300  sum = m_sigma*Q.trace(Q.matrix, Q.num_rows, Q.num_cols);
301 
302  SGVector<float64_t> sigma(1);
303 
304  sigma[0] = sum;
305  gradient.add(param, sigma);
306  para_dict.add(param, m_model);
307 
308  return gradient;
309 
310 }
311 
313 {
315  update_all();
316 
317  check_members();
318 
319  float64_t m_sigma =
320  dynamic_cast<CGaussianLikelihood*>(m_model)->get_sigma();
321 
322  SGVector<float64_t> result =
324 
325  result.fill_vector(result.vector, m_features->get_num_vectors(),
326  1.0/m_sigma);
327 
328  return result;
329 }
330 
332 {
334  update_all();
335 
336  float64_t result;
337 
339  m_label_vector.vlen)/2.0;
340 
341  float64_t m_sigma =
342  dynamic_cast<CGaussianLikelihood*>(m_model)->get_sigma();
343 
344  for (int i = 0; i < m_L.num_rows; i++)
345  result += CMath::log(m_L(i,i));
346 
347  result += m_L.num_rows * CMath::log(2*CMath::PI*m_sigma*m_sigma)/2.0;
348 
349  return result;
350 }
351 
353 {
355  update_all();
356 
358  return result;
359 }
360 
362 {
364  update_all();
365 
366  SGMatrix<float64_t> result(m_L);
367  return result;
368 }
369 
371 {
372  m_kernel->cleanup();
373 
375 
376  //K(X, X)
378 
379  m_ktrtr=kernel_matrix.clone();
380 }
381 
382 
384 {
385  check_members();
386 
387  float64_t m_sigma =
388  dynamic_cast<CGaussianLikelihood*>(m_model)->get_sigma();
389 
390  //Placeholder Matrices
392  m_ktrtr.num_cols);
393 
394  m_kern_with_noise = SGMatrix<float64_t>(m_ktrtr.num_rows,
395  m_ktrtr.num_cols);
396 
398  m_ktrtr.num_cols);
399 
400  //Vector to fill matrix diagonals
401  SGVector<float64_t> diagonal(temp1.num_rows);
402  diagonal.fill_vector(diagonal.vector, temp1.num_rows, 1.0);
403 
404  temp1.create_diagonal_matrix(temp1.matrix, diagonal.vector, temp1.num_rows);
405  temp2.create_diagonal_matrix(temp2.matrix, diagonal.vector, temp2.num_rows);
406 
407  //Calculate first (K(X, X)+sigma*I)
408  cblas_dsymm(CblasColMajor, CblasLeft, CblasUpper,
409  m_ktrtr.num_rows, temp2.num_cols, (m_scale*m_scale)/(m_sigma*m_sigma),
411  temp2.matrix, temp2.num_cols, 1.0,
412  temp1.matrix, temp1.num_cols);
413 
414  memcpy(m_kern_with_noise.matrix, temp1.matrix,
415  temp1.num_cols*temp1.num_rows*sizeof(float64_t));
416 
417  //Get Lower triangle cholesky decomposition of K(X, X)+sigma*I)
418  clapack_dpotrf(CblasColMajor, CblasUpper,
419  temp1.num_rows, temp1.matrix, temp1.num_cols);
420 
421  m_L = SGMatrix<float64_t>(temp1.num_rows, temp1.num_cols);
422 
423  /* lapack for some reason wants only to calculate the upper triangle
424  * and leave the lower triangle with junk data. Finishing the job
425  * by filling the lower triangle with zero entries.
426  */
427  for (int i = 0; i < temp1.num_rows; i++)
428  {
429  for (int j = 0; j < temp1.num_cols; j++)
430  {
431  if (i > j)
432  temp1(i,j) = 0;
433  }
434  }
435 
436  memcpy(m_L.matrix, temp1.matrix,
437  temp1.num_cols*temp1.num_rows*sizeof(float64_t));
438 }
439 
441 {
442  float64_t m_sigma =
443  dynamic_cast<CGaussianLikelihood*>(m_model)->get_sigma();
444 
445  //Placeholder Matrices
447  m_L.num_cols);
448 
449  for (int i = 0; i < m_label_vector.vlen; i++)
451 
453 
454  memcpy(temp1.matrix, m_L.matrix,
455  m_L.num_cols*m_L.num_rows*sizeof(float64_t));
456 
458  m_label_vector.vlen*sizeof(float64_t));
459 
460  //Solve (K(X, X)+sigma*I) alpha = labels for alpha.
461  clapack_dposv(CblasColMajor, CblasLower,
462  m_kern_with_noise.num_cols, 1, m_kern_with_noise.matrix,
463  m_kern_with_noise.num_cols, m_alpha.vector,
464  m_kern_with_noise.num_cols);
465 
466  for (int i = 0; i < m_alpha.vlen; i++)
467  m_alpha[i] = m_alpha[i]/(m_sigma*m_sigma);
468 
469 }
470 #endif
471 #endif // HAVE_LAPACK

SHOGUN Machine Learning Toolbox - Documentation