SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CustomKernel.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  * Written (W) 1999-2009 Soeren Sonnenburg
8  * Written (W) 2012 Heiko Strathmann
9  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
10  */
11 
12 #include <shogun/lib/common.h>
17 #include <shogun/io/SGIO.h>
19 
20 using namespace shogun;
21 
22 #ifdef HAVE_LINALG_LIB
24 
25 using namespace linalg;
26 #endif // HAVE_LINALG_LIB
27 
28 void CCustomKernel::init()
29 {
30  m_row_subset_stack=new CSubsetStack();
31  SG_REF(m_row_subset_stack)
32  m_col_subset_stack=new CSubsetStack();
33  SG_REF(m_col_subset_stack)
34  m_is_symmetric=false;
35  m_free_km=true;
36 
37  SG_ADD((CSGObject**)&m_row_subset_stack, "row_subset_stack",
38  "Subset stack of rows", MS_NOT_AVAILABLE);
39  SG_ADD((CSGObject**)&m_col_subset_stack, "col_subset_stack",
40  "Subset stack of columns", MS_NOT_AVAILABLE);
41  SG_ADD(&m_free_km, "free_km", "Whether kernel matrix should be freed in "
42  "destructor", MS_NOT_AVAILABLE);
43  SG_ADD(&m_is_symmetric, "is_symmetric", "Whether kernel matrix is symmetric",
44  MS_NOT_AVAILABLE);
45  SG_ADD(&kmatrix, "kmatrix", "Kernel matrix.", MS_NOT_AVAILABLE);
46  SG_ADD(&upper_diagonal, "upper_diagonal", "Upper diagonal", MS_NOT_AVAILABLE);
47 
48  /* new parameter from param version 0 to 1 */
49  m_parameter_map->put(
50  new SGParamInfo("free_km", CT_SCALAR, ST_NONE, PT_BOOL, 1),
51  new SGParamInfo()
52  );
53 
54  /* new parameter from param version 0 to 1 */
55  m_parameter_map->put(
56  new SGParamInfo("row_subset_stack", CT_SCALAR, ST_NONE, PT_SGOBJECT, 1),
57  new SGParamInfo()
58  );
59 
60  /* new parameter from param version 0 to 1 */
61  m_parameter_map->put(
62  new SGParamInfo("col_subset_stack", CT_SCALAR, ST_NONE, PT_SGOBJECT, 1),
63  new SGParamInfo()
64  );
65  m_parameter_map->finalize_map();
66 }
67 
69 : CKernel(10), kmatrix(), upper_diagonal(false)
70 {
71  SG_DEBUG("created CCustomKernel\n")
72  init();
73 }
74 
76 : CKernel(10)
77 {
78  SG_DEBUG("created CCustomKernel\n")
79  init();
80 
81  /* if constructed from a custom kernel, use same kernel matrix */
82  if (k->get_kernel_type()==K_CUSTOM)
83  {
84  CCustomKernel* casted=(CCustomKernel*)k;
87  m_free_km=false;
88  }
89  else
90  {
93  }
94 }
95 
97 : CKernel(10), upper_diagonal(false)
98 {
99  SG_DEBUG("Entering\n")
100  init();
102  SG_DEBUG("Leaving\n")
103 }
104 
106 : CKernel(10), upper_diagonal(false)
107 {
108  SG_DEBUG("Entering\n")
109  init();
111  SG_DEBUG("Leaving\n")
112 }
113 
115 {
116  SG_DEBUG("Entering\n")
117  cleanup();
120  SG_DEBUG("Leaving\n")
121 }
122 
123 bool CCustomKernel::dummy_init(int32_t rows, int32_t cols)
124 {
125  return init(new CDummyFeatures(rows), new CDummyFeatures(cols));
126 }
127 
128 bool CCustomKernel::init(CFeatures* l, CFeatures* r)
129 {
130  /* make it possible to call with NULL values since features are useless
131  * for custom kernel matrix */
132  if (!l)
133  l=lhs;
134 
135  if (!r)
136  r=rhs;
137 
138  /* Make sure l and r should not be NULL */
139  REQUIRE(l, "CFeatures l should not be NULL\n")
140  REQUIRE(r, "CFeatures r should not be NULL\n")
141 
142  /* Make sure l and r have the same type of CFeatures */
144  "Different FeatureClass: l is %d, r is %d\n",
147  "Different FeatureType: l is %d, r is %d\n",
149 
150  /* If l and r are the type of CIndexFeatures,
151  * the init function adds a subset to kernel matrix.
152  * Then call get_kernel_matrix will get the submatrix
153  * of the kernel matrix.
154  */
156  {
157  CIndexFeatures* l_idx = (CIndexFeatures*)l;
158  CIndexFeatures* r_idx = (CIndexFeatures*)r;
159 
162 
165 
167 
168  return true;
169  }
170 
171  /* For other types of CFeatures do the default actions below */
172  CKernel::init(l, r);
173 
175 
176  SG_DEBUG("num_vec_lhs: %d vs num_rows %d\n", l->get_num_vectors(), kmatrix.num_rows)
177  SG_DEBUG("num_vec_rhs: %d vs num_cols %d\n", r->get_num_vectors(), kmatrix.num_cols)
180  return init_normalizer();
181 }
182 
183 #ifdef HAVE_LINALG_LIB
184 #ifdef HAVE_EIGEN3
186  index_t block_size, bool no_diag)
187 {
188  SG_DEBUG("Entering\n");
189 
191  {
192  SG_INFO("Row/col subsets initialized! Falling back to "
193  "CKernel::sum_symmetric_block (slower)!\n");
194  return CKernel::sum_symmetric_block(block_begin, block_size, no_diag);
195  }
196 
197  REQUIRE(kmatrix.matrix, "The kernel matrix is not initialized!\n")
198  REQUIRE(m_is_symmetric, "The kernel matrix is not symmetric!\n")
199  REQUIRE(block_begin>=0 && block_begin<kmatrix.num_cols,
200  "Invalid block begin index (%d, %d)!\n", block_begin, block_begin)
201  REQUIRE(block_begin+block_size<=kmatrix.num_cols,
202  "Invalid block size (%d) at starting index (%d, %d)! "
203  "Please use smaller blocks!", block_size, block_begin, block_begin)
204  REQUIRE(block_size>=1, "Invalid block size (%d)!\n", block_size)
205 
206  SG_DEBUG("Leaving\n");
207 
208  return sum_symmetric<Backend::EIGEN3>(block(kmatrix, block_begin,
209  block_begin, block_size, block_size), no_diag);
210 }
211 
212 float64_t CCustomKernel::sum_block(index_t block_begin_row,
213  index_t block_begin_col, index_t block_size_row,
214  index_t block_size_col, bool no_diag)
215 {
216  SG_DEBUG("Entering\n");
217 
219  {
220  SG_INFO("Row/col subsets initialized! Falling back to "
221  "CKernel::sum_block (slower)!\n");
222  return CKernel::sum_block(block_begin_row, block_begin_col,
223  block_size_row, block_size_col, no_diag);
224  }
225 
226  REQUIRE(kmatrix.matrix, "The kernel matrix is not initialized!\n")
227  REQUIRE(block_begin_row>=0 && block_begin_row<kmatrix.num_rows &&
228  block_begin_col>=0 && block_begin_col<kmatrix.num_cols,
229  "Invalid block begin index (%d, %d)!\n",
230  block_begin_row, block_begin_col)
231  REQUIRE(block_begin_row+block_size_row<=kmatrix.num_rows &&
232  block_begin_col+block_size_col<=kmatrix.num_cols,
233  "Invalid block size (%d, %d) at starting index (%d, %d)! "
234  "Please use smaller blocks!", block_size_row, block_size_col,
235  block_begin_row, block_begin_col)
236  REQUIRE(block_size_row>=1 && block_size_col>=1,
237  "Invalid block size (%d, %d)!\n", block_size_row, block_size_col)
238 
239  // check if removal of diagonal is required/valid
240  if (no_diag && block_size_row!=block_size_col)
241  {
242  SG_WARNING("Not removing the main diagonal since block is not square!\n");
243  no_diag=false;
244  }
245 
246  SG_DEBUG("Leaving\n");
247 
248  return sum<Backend::EIGEN3>(block(kmatrix, block_begin_row, block_begin_col,
249  block_size_row, block_size_col), no_diag);
250 }
251 
253  block_begin, index_t block_size, bool no_diag)
254 {
255  SG_DEBUG("Entering\n");
256 
258  {
259  SG_INFO("Row/col subsets initialized! Falling back to "
260  "CKernel::row_wise_sum_symmetric_block (slower)!\n");
261  return CKernel::row_wise_sum_symmetric_block(block_begin, block_size,
262  no_diag);
263  }
264 
265  REQUIRE(kmatrix.matrix, "The kernel matrix is not initialized!\n")
266  REQUIRE(m_is_symmetric, "The kernel matrix is not symmetric!\n")
267  REQUIRE(block_begin>=0 && block_begin<kmatrix.num_cols,
268  "Invalid block begin index (%d, %d)!\n", block_begin, block_begin)
269  REQUIRE(block_begin+block_size<=kmatrix.num_cols,
270  "Invalid block size (%d) at starting index (%d, %d)! "
271  "Please use smaller blocks!", block_size, block_begin, block_begin)
272  REQUIRE(block_size>=1, "Invalid block size (%d)!\n", block_size)
273 
274  SGVector<float32_t> s=rowwise_sum<Backend::EIGEN3>(block(kmatrix, block_begin,
275  block_begin, block_size, block_size), no_diag);
276 
277  // casting to float64_t vector
278  SGVector<float64_t> sum(s.vlen);
279  for (index_t i=0; i<s.vlen; ++i)
280  sum[i]=s[i];
281 
282  SG_DEBUG("Leaving\n");
283 
284  return sum;
285 }
286 
288  index_t block_begin, index_t block_size, bool no_diag)
289 {
290  SG_DEBUG("Entering\n");
291 
293  {
294  SG_INFO("Row/col subsets initialized! Falling back to "
295  "CKernel::row_wise_sum_squared_sum_symmetric_block (slower)!\n");
297  block_size, no_diag);
298  }
299 
300  REQUIRE(kmatrix.matrix, "The kernel matrix is not initialized!\n")
301  REQUIRE(m_is_symmetric, "The kernel matrix is not symmetric!\n")
302  REQUIRE(block_begin>=0 && block_begin<kmatrix.num_cols,
303  "Invalid block begin index (%d, %d)!\n", block_begin, block_begin)
304  REQUIRE(block_begin+block_size<=kmatrix.num_cols,
305  "Invalid block size (%d) at starting index (%d, %d)! "
306  "Please use smaller blocks!", block_size, block_begin, block_begin)
307  REQUIRE(block_size>=1, "Invalid block size (%d)!\n", block_size)
308 
309  // initialize the matrix that accumulates the row/col-wise sum
310  // the first column stores the sum of kernel values
311  // the second column stores the sum of squared kernel values
312  SGMatrix<float64_t> row_sum(block_size, 2);
313 
314  SGVector<float32_t> sum=rowwise_sum<Backend::EIGEN3>(block(kmatrix,
315  block_begin, block_begin, block_size, block_size), no_diag);
316 
317  SGVector<float32_t> sq_sum=rowwise_sum<Backend::EIGEN3>(
318  elementwise_square<Backend::EIGEN3>(block(kmatrix,
319  block_begin, block_begin, block_size, block_size)), no_diag);
320 
321  for (index_t i=0; i<sum.vlen; ++i)
322  row_sum(i, 0)=sum[i];
323 
324  for (index_t i=0; i<sq_sum.vlen; ++i)
325  row_sum(i, 1)=sq_sum[i];
326 
327  SG_DEBUG("Leaving\n");
328 
329  return row_sum;
330 }
331 
333  block_begin_row, index_t block_begin_col, index_t block_size_row,
334  index_t block_size_col, bool no_diag)
335 {
336  SG_DEBUG("Entering\n");
337 
339  {
340  SG_INFO("Row/col subsets initialized! Falling back to "
341  "CKernel::row_col_wise_sum_block (slower)!\n");
342  return CKernel::row_col_wise_sum_block(block_begin_row, block_begin_col,
343  block_size_row, block_size_col, no_diag);
344  }
345 
346  REQUIRE(kmatrix.matrix, "The kernel matrix is not initialized!\n")
347  REQUIRE(block_begin_row>=0 && block_begin_row<kmatrix.num_rows &&
348  block_begin_col>=0 && block_begin_col<kmatrix.num_cols,
349  "Invalid block begin index (%d, %d)!\n",
350  block_begin_row, block_begin_col)
351  REQUIRE(block_begin_row+block_size_row<=kmatrix.num_rows &&
352  block_begin_col+block_size_col<=kmatrix.num_cols,
353  "Invalid block size (%d, %d) at starting index (%d, %d)! "
354  "Please use smaller blocks!", block_size_row, block_size_col,
355  block_begin_row, block_begin_col)
356  REQUIRE(block_size_row>=1 && block_size_col>=1,
357  "Invalid block size (%d, %d)!\n", block_size_row, block_size_col)
358 
359  // check if removal of diagonal is required/valid
360  if (no_diag && block_size_row!=block_size_col)
361  {
362  SG_WARNING("Not removing the main diagonal since block is not square!\n");
363  no_diag=false;
364  }
365 
366  // initialize the vector that accumulates the row/col-wise sum
367  // the first block_size_row entries store the row-wise sum of kernel values
368  // the nextt block_size_col entries store the col-wise sum of kernel values
369  SGVector<float64_t> sum(block_size_row+block_size_col);
370 
371  SGVector<float32_t> rowwise=rowwise_sum<Backend::EIGEN3>(block(kmatrix,
372  block_begin_row, block_begin_col, block_size_row,
373  block_size_col), no_diag);
374 
375  SGVector<float32_t> colwise=colwise_sum<Backend::EIGEN3>(block(kmatrix,
376  block_begin_row, block_begin_col, block_size_row,
377  block_size_col), no_diag);
378 
379  for (index_t i=0; i<rowwise.vlen; ++i)
380  sum[i]=rowwise[i];
381 
382  for (index_t i=0; i<colwise.vlen; ++i)
383  sum[i+rowwise.vlen]=colwise[i];
384 
385  SG_DEBUG("Leaving\n");
386 
387  return sum;
388 }
389 #endif // HAVE_EIGEN3
390 #endif // HAVE_LINALG_LIB
391 
393 {
394  SG_DEBUG("Entering\n")
397 
398  kmatrix=SGMatrix<float32_t>();
399  upper_diagonal=false;
400 
401  SG_DEBUG("Leaving\n")
402 }
403 
405 {
406  cleanup_custom();
408 }
409 
411 {
414 }
415 
417 {
420 }
421 
423 {
426 }
427 
429 {
432 }
433 
435 {
438  else
439  num_lhs=kmatrix.num_rows;
440 }
441 
443 {
446 }
447 
449 {
452 }
453 
455 {
458 }
459 
461 {
464 }
465 
467 {
470  else
471  num_rhs=kmatrix.num_cols;
472 }

SHOGUN Machine Learning Toolbox - Documentation