SHOGUN  6.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
QuadraticTimeMMD.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) The Shogun Machine Learning Toolbox
3  * Written (w) 2012 - 2013 Heiko Strathmann
4  * Written (w) 2014 - 2017 Soumyajit De
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * The views and conclusions contained in the software and documentation are those
28  * of the authors and should not be interpreted as representing official policies,
29  * either expressed or implied, of the Shogun Development Team.
30  */
31 
32 #include <shogun/io/SGIO.h>
33 #include <shogun/lib/SGVector.h>
34 #include <shogun/kernel/Kernel.h>
48 
49 using namespace shogun;
50 using namespace internal;
51 using namespace mmd;
52 using std::unique_ptr;
53 
55 {
57 
58  void init_statistic_job();
59  void init_permutation_job();
60  void init_variance_h1_job();
61  void init_kernel();
62  SGMatrix<float32_t> get_kernel_matrix();
63 
64  SGVector<float64_t> sample_null_spectrum();
65  SGVector<float64_t> sample_null_permutation();
66  SGVector<float64_t> gamma_fit_null();
67 
69  unique_ptr<CMultiKernelQuadraticTimeMMD> multi_kernel;
70 
78  bool precompute;
79 
91 
93 
94  ComputeMMD statistic_job;
95  VarianceH0 variance_h0_job;
96  VarianceH1 variance_h1_job;
97  PermutationMMD permutation_job;
98 
99  static constexpr bool DEFAULT_PRECOMPUTE = true;
100  static constexpr index_t DEFAULT_NUM_EIGENVALUES = 10;
101 };
102 
104 {
105  is_kernel_initialized=false;
108 }
109 
111 {
112  REQUIRE(owner.get_num_samples_p()>0,
113  "Number of samples from P (was %s) has to be > 0!\n", owner.get_num_samples_p());
114  REQUIRE(owner.get_num_samples_q()>0,
115  "Number of samples from Q (was %s) has to be > 0!\n", owner.get_num_samples_q());
116 
117  statistic_job.m_n_x=owner.get_num_samples_p();
118  statistic_job.m_n_y=owner.get_num_samples_q();
119  statistic_job.m_stype=owner.get_statistic_type();
120 }
121 
123 {
124  REQUIRE(owner.get_num_samples_p()>0,
125  "Number of samples from P (was %s) has to be > 0!\n", owner.get_num_samples_p());
126  REQUIRE(owner.get_num_samples_q()>0,
127  "Number of samples from Q (was %s) has to be > 0!\n", owner.get_num_samples_q());
128 
129  variance_h1_job.m_n_x=owner.get_num_samples_p();
130  variance_h1_job.m_n_y=owner.get_num_samples_q();
131 }
132 
134 {
135  REQUIRE(owner.get_num_samples_p()>0,
136  "Number of samples from P (was %s) has to be > 0!\n", owner.get_num_samples_p());
137  REQUIRE(owner.get_num_samples_q()>0,
138  "Number of samples from Q (was %s) has to be > 0!\n", owner.get_num_samples_q());
139  REQUIRE(owner.get_num_null_samples()>0,
140  "Number of null samples (was %d) has to be > 0!\n", owner.get_num_null_samples());
141 
142  permutation_job.m_n_x=owner.get_num_samples_p();
143  permutation_job.m_n_y=owner.get_num_samples_q();
144  permutation_job.m_stype=owner.get_statistic_type();
145  permutation_job.m_num_null_samples=owner.get_num_null_samples();
146 }
147 
149 {
150  ASSERT(owner.get_kernel());
151  if (!is_kernel_initialized)
152  {
153  ASSERT(owner.get_kernel()->get_kernel_type()!=K_CUSTOM);
154  auto samples_p_and_q=owner.get_p_and_q();
155 
156  auto kernel=owner.get_kernel();
157  kernel->init(samples_p_and_q, samples_p_and_q);
158  is_kernel_initialized=true;
159  SG_SINFO("Kernel is initialized with joint features of %d total samples!\n", samples_p_and_q->get_num_vectors());
160  }
161 }
162 
164 {
165  ASSERT(precompute);
166  ASSERT(owner.get_kernel());
167  ASSERT(is_kernel_initialized);
168 
169  if (owner.get_kernel()->get_kernel_type()!=K_CUSTOM)
170  {
171  auto kernel=owner.get_kernel();
172  owner.get_kernel_mgr().precompute_kernel_at(0);
173  kernel->remove_lhs_and_rhs();
174  }
175 
176  ASSERT(owner.get_kernel()->get_kernel_type()==K_CUSTOM);
177  auto precomputed_kernel=static_cast<CCustomKernel*>(owner.get_kernel());
178  return precomputed_kernel->get_float32_kernel_matrix();
179 }
180 
181 CQuadraticTimeMMD::CQuadraticTimeMMD() : CMMD()
182 {
183  init();
184 }
185 
186 CQuadraticTimeMMD::CQuadraticTimeMMD(CFeatures* samples_from_p, CFeatures* samples_from_q) : CMMD(samples_from_p, samples_from_q)
187 {
188  init();
189 }
190 
191 void CQuadraticTimeMMD::init()
192 {
193  self=unique_ptr<Self>(new Self(*this));
194  self->multi_kernel=unique_ptr<CMultiKernelQuadraticTimeMMD>(new CMultiKernelQuadraticTimeMMD(this));
195 }
196 
198 {
199  CMMD::cleanup();
200 }
201 
202 void CQuadraticTimeMMD::set_p(CFeatures* samples_from_p)
203 {
204  if (samples_from_p!=get_p())
205  {
206  CTwoDistributionTest::set_p(samples_from_p);
207  get_kernel_mgr().restore_kernel_at(0);
208  self->is_kernel_initialized=false;
209  self->multi_kernel->invalidate_precomputed_distance();
210 
211  if (get_kernel() && get_kernel()->get_kernel_type()==K_CUSTOM)
212  {
213  SG_WARNING("Existing kernel is already precomputed. Features provided will be\
214  ignored unless the kernel is updated with a non-precomputed one!\n");
215  self->is_kernel_initialized=true;
216  }
217  }
218  else
219  {
220  SG_INFO("Provided features are the same as the existing one. Ignoring!\n");
221  }
222 }
223 
224 void CQuadraticTimeMMD::set_q(CFeatures* samples_from_q)
225 {
226  if (samples_from_q!=get_q())
227  {
228  CTwoDistributionTest::set_q(samples_from_q);
229  get_kernel_mgr().restore_kernel_at(0);
230  self->is_kernel_initialized=false;
231  self->multi_kernel->invalidate_precomputed_distance();
232 
233  if (get_kernel() && get_kernel()->get_kernel_type()==K_CUSTOM)
234  {
235  SG_WARNING("Existing kernel is already precomputed. Features provided will be\
236  ignored unless the kernel is updated with a non-precomputed one!\n");
237  self->is_kernel_initialized=true;
238  }
239  }
240  else
241  {
242  SG_INFO("Provided features are the same as the existing one. Ignoring!\n");
243  }
244 }
245 
247 {
248  CFeatures* samples_p_and_q=nullptr;
249  REQUIRE(get_p(), "Samples from P are not set!\n");
250  REQUIRE(get_q(), "Samples from Q are not set!\n");
251 
252  DataManager& data_mgr=get_data_mgr();
253  data_mgr.start();
254  auto samples=data_mgr.next();
255  if (!samples.empty())
256  {
257  CFeatures *samples_p=samples[0][0];
258  CFeatures *samples_q=samples[1][0];
259  samples_p_and_q=samples_p->create_merged_copy(samples_q);
260  samples.clear();
261  }
262  else
263  {
264  SG_SERROR("Could not fetch samples!\n");
265  }
266  data_mgr.end();
267  return samples_p_and_q;
268 }
269 
271 {
272  if (kernel!=get_kernel())
273  {
274  // removing any pre-computed kernel is done in the base already
276  self->is_kernel_initialized=false;
277 
278  if (kernel->get_kernel_type()==K_CUSTOM)
279  {
280  SG_INFO("Setting a precomputed kernel. Features provided will be ignored!\n");
281  self->is_kernel_initialized=true;
282  }
283  }
284  else
285  {
286  SG_INFO("Provided kernel is the same as the existing one. Ignoring!\n");
287  }
288 }
289 
291 {
293  self->is_kernel_initialized=false;
294 
295  ASSERT(get_kernel());
296  if (get_kernel()->get_kernel_type()==K_CUSTOM)
297  {
298  SG_WARNING("Selected kernel is already precomputed. Features provided will be\
299  ignored unless the kernel is updated with a non-precomputed one!\n");
300  self->is_kernel_initialized=true;
301  }
302 }
303 
305 {
306  const index_t Nx=get_num_samples_p();
307  const index_t Ny=get_num_samples_q();
308  return Nx*Ny*statistic/(Nx+Ny);
309 }
310 
311 
313 {
314  SG_DEBUG("Entering\n");
315  REQUIRE(get_kernel(), "Kernel is not set!\n");
316 
317  self->init_statistic_job();
318  self->init_kernel();
319 
320  float64_t statistic=0;
321  if (self->precompute)
322  {
323  SGMatrix<float32_t> kernel_matrix=self->get_kernel_matrix();
324  statistic=self->statistic_job(kernel_matrix);
325  }
326  else
327  {
328  auto kernel=get_kernel();
329  if (kernel->get_kernel_type()==K_CUSTOM)
330  SG_INFO("Precompute is turned off, but provided kernel is already precomputed!\n");
331  auto kernel_functor=internal::Kernel(kernel);
332  statistic=self->statistic_job(kernel_functor);
333  }
334 
335  statistic=normalize_statistic(statistic);
336 
337  SG_DEBUG("Leaving\n");
338  return statistic;
339 }
340 
342 {
343  SG_SDEBUG("Entering\n");
344  REQUIRE(owner.get_kernel(), "Kernel is not set!\n");
345 
347  init_kernel();
348 
349  SGVector<float32_t> result;
350  if (precompute)
351  {
352  SGMatrix<float32_t> kernel_matrix=get_kernel_matrix();
353  result=permutation_job(kernel_matrix);
354  }
355  else
356  {
357  auto kernel=owner.get_kernel();
358  if (kernel->get_kernel_type()==K_CUSTOM)
359  SG_SINFO("Precompute is turned off, but provided kernel is already precomputed!\n");
360  auto kernel_functor=internal::Kernel(kernel);
361  result=permutation_job(kernel_functor);
362  }
363 
364  SGVector<float64_t> null_samples(result.vlen);
365  for (auto i=0; i<result.vlen; ++i)
366  null_samples[i]=owner.normalize_statistic(result[i]);
367 
368  SG_SDEBUG("Leaving\n");
369  return null_samples;
370 }
371 
373 {
374  SG_SDEBUG("Entering\n");
375  REQUIRE(owner.get_kernel(), "Kernel is not set!\n");
376  REQUIRE(precompute, "MMD2_SPECTRUM is not possible without precomputing the kernel matrix!\n");
377 
378  index_t m=owner.get_num_samples_p();
379  index_t n=owner.get_num_samples_q();
380 
381  REQUIRE(num_eigenvalues>0 && num_eigenvalues<m+n-1,
382  "Number of Eigenvalues (%d) must be in between [1, %d]\n", num_eigenvalues, m+n-1);
383 
384  init_kernel();
385 
386  /* imaginary matrix K=[K KL; KL' L] (MATLAB notation)
387  * K is matrix for XX, L is matrix for YY, KL is XY, LK is YX
388  * works since X and Y are concatenated here */
389  SGMatrix<float32_t> kernel_matrix=get_kernel_matrix();
390  SGMatrix<float32_t> K(kernel_matrix.num_rows, kernel_matrix.num_cols);
391  std::copy(kernel_matrix.data(), kernel_matrix.data()+kernel_matrix.size(), K.data());
392 
393  /* center matrix K=H*K*H */
394  K.center();
395 
396  /* compute eigenvalues and select num_eigenvalues largest ones */
397  Eigen::Map<Eigen::MatrixXf> c_kernel_matrix(K.matrix, K.num_rows, K.num_cols);
398  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eigen_solver(c_kernel_matrix);
399  REQUIRE(eigen_solver.info()==Eigen::Success, "Eigendecomposition failed!\n");
400  index_t max_num_eigenvalues=eigen_solver.eigenvalues().rows();
401 
402  SGVector<float64_t> null_samples(owner.get_num_null_samples());
403 
404  /* finally, sample from null distribution */
405  for (auto i=0; i<null_samples.vlen; ++i)
406  {
407  float64_t null_sample=0;
408  for (index_t j=0; j<num_eigenvalues; ++j)
409  {
410  float64_t z_j=CMath::randn_double();
411  float64_t multiple=CMath::sq(z_j);
412 
413  /* take largest EV, scale by 1/(m+n) on the fly and take abs value*/
414  float64_t eigenvalue_estimate=eigen_solver.eigenvalues()[max_num_eigenvalues-1-j];
415  eigenvalue_estimate/=(m+n);
416 
417  if (owner.get_statistic_type()==ST_UNBIASED_FULL)
418  multiple-=1;
419 
420  null_sample+=eigenvalue_estimate*multiple;
421  }
422  null_samples[i]=null_sample;
423  }
424 
425  SG_SDEBUG("Leaving\n");
426  return null_samples;
427 }
428 
430 {
431  SG_SDEBUG("Entering\n");
432 
433  REQUIRE(owner.get_kernel(), "Kernel is not set!\n");
434  REQUIRE(precompute, "MMD2_GAMMA is not possible without precomputing the kernel matrix!\n");
435  REQUIRE(owner.get_statistic_type()==ST_BIASED_FULL, "Provided statistic has to be BIASED!\n");
436 
437  index_t m=owner.get_num_samples_p();
438  index_t n=owner.get_num_samples_q();
439  REQUIRE(m==n, "Number of samples from p (%d) and q (%d) must be equal.\n", n, m)
440 
441  SGVector<float64_t> result(2);
442  std::fill(result.vector, result.vector+result.vlen, 0);
443 
444  init_kernel();
445 
446  /* imaginary matrix K=[K KL; KL' L] (MATLAB notation)
447  * K is matrix for XX, L is matrix for YY, KL is XY, LK is YX
448  * works since X and Y are concatenated here */
449  SGMatrix<float32_t> kernel_matrix=get_kernel_matrix();
450 
451  /* compute mean under H0 of MMD, which is
452  * meanMMD =2/m * ( 1 - 1/m*sum(diag(KL)) );
453  * in MATLAB.
454  * Remove diagonals on the fly */
455  float64_t mean_mmd=0;
456  for (index_t i=0; i<m; ++i)
457  {
458  /* virtual KL matrix is in upper right corner of SHOGUN K matrix
459  * so this sums the diagonal of the matrix between X and Y*/
460  mean_mmd+=kernel_matrix(i, m+i);
461  }
462  mean_mmd=2.0/m*(1.0-1.0/m*mean_mmd);
463 
464  /* compute variance under H0 of MMD, which is
465  * varMMD=2/m/(m-1) * 1/m/(m-1) * sum(sum( (K+L - KL - KL').^2 ));
466  * in MATLAB, so sum up all elements */
467 
468  // TODO parallelise or use linalg and precomputed kernel matrix
469  float64_t var_mmd=0;
470  for (index_t i=0; i<m; ++i)
471  {
472  for (index_t j=0; j<m; ++j)
473  {
474  /* dont add diagonal of all pairs of imaginary kernel matrices */
475  if (i==j || m+i==j || m+j==i)
476  continue;
477 
478  float64_t to_add=kernel_matrix(i, j);
479  to_add+=kernel_matrix(m+i, m+j);
480  to_add-=kernel_matrix(i, m+j);
481  to_add-=kernel_matrix(m+i, j);
482  var_mmd+=CMath::pow(to_add, 2);
483  }
484  }
485 
486  var_mmd*=2.0/m/(m-1)*1.0/m/(m-1);
487 
488  /* parameters for gamma distribution */
489  float64_t a=CMath::pow(mean_mmd, 2)/var_mmd;
490  float64_t b=var_mmd*m/mean_mmd;
491 
492  result[0]=a;
493  result[1]=b;
494 
495  SG_SDEBUG("Leaving\n");
496  return result;
497 }
498 
499 float64_t CQuadraticTimeMMD::compute_variance_h0()
500 {
501  REQUIRE(get_kernel(), "Kernel is not set!\n");
502  REQUIRE(self->precompute,
503  "Computing variance estimate is not possible without precomputing the kernel matrix!\n");
504 
505  self->init_kernel();
506  SGMatrix<float32_t> kernel_matrix=self->get_kernel_matrix();
507  return self->variance_h0_job(kernel_matrix);
508 }
509 
510 float64_t CQuadraticTimeMMD::compute_variance_h1()
511 {
512  REQUIRE(get_kernel(), "Kernel is not set!\n");
513  self->init_kernel();
514  self->init_variance_h1_job();
515  float64_t variance_estimate=0;
516  if (self->precompute)
517  {
518  SGMatrix<float32_t> kernel_matrix=self->get_kernel_matrix();
519  variance_estimate=self->variance_h1_job(kernel_matrix);
520  }
521  else
522  {
523  auto kernel=get_kernel();
524  if (kernel->get_kernel_type()==K_CUSTOM)
525  SG_INFO("Precompute is turned off, but provided kernel is already precomputed!\n");
526  auto kernel_functor=internal::Kernel(kernel);
527  variance_estimate=self->variance_h1_job(kernel_functor);
528  }
529  return variance_estimate;
530 }
531 
532 float64_t CQuadraticTimeMMD::compute_p_value(float64_t statistic)
533 {
534  REQUIRE(get_kernel(), "Kernel is not set!\n");
535  float64_t result=0;
536  switch (get_null_approximation_method())
537  {
538  case NAM_MMD2_GAMMA:
539  {
540  SGVector<float64_t> params=self->gamma_fit_null();
541  result=CStatistics::gamma_cdf(statistic, params[0], params[1]);
542  break;
543  }
544  default:
545  result=CHypothesisTest::compute_p_value(statistic);
546  break;
547  }
548  return result;
549 }
550 
551 float64_t CQuadraticTimeMMD::compute_threshold(float64_t alpha)
552 {
553  REQUIRE(get_kernel(), "Kernel is not set!\n");
554  float64_t result=0;
555  switch (get_null_approximation_method())
556  {
557  case NAM_MMD2_GAMMA:
558  {
559  SGVector<float64_t> params=self->gamma_fit_null();
560  result=CStatistics::gamma_inverse_cdf(alpha, params[0], params[1]);
561  break;
562  }
563  default:
564  result=CHypothesisTest::compute_threshold(alpha);
565  break;
566  }
567  return result;
568 }
569 
570 SGVector<float64_t> CQuadraticTimeMMD::sample_null()
571 {
572  REQUIRE(get_kernel(), "Kernel is not set!\n");
573  SGVector<float64_t> null_samples;
574  switch (get_null_approximation_method())
575  {
576  case NAM_MMD2_SPECTRUM:
577  null_samples=self->sample_null_spectrum();
578  break;
579  case NAM_PERMUTATION:
580  null_samples=self->sample_null_permutation();
581  break;
582  default: break;
583  }
584  return null_samples;
585 }
586 
587 CMultiKernelQuadraticTimeMMD* CQuadraticTimeMMD::multikernel()
588 {
589  return self->multi_kernel.get();
590 }
591 
592 void CQuadraticTimeMMD::spectrum_set_num_eigenvalues(index_t num_eigenvalues)
593 {
594  self->num_eigenvalues=num_eigenvalues;
595 }
596 
597 index_t CQuadraticTimeMMD::spectrum_get_num_eigenvalues() const
598 {
599  return self->num_eigenvalues;
600 }
601 
602 void CQuadraticTimeMMD::precompute_kernel_matrix(bool precompute)
603 {
604  if (self->precompute && !precompute)
605  {
606  if (get_kernel())
607  {
608  get_kernel_mgr().restore_kernel_at(0);
609  self->is_kernel_initialized=false;
610  if (get_kernel()->get_kernel_type()==K_CUSTOM)
611  {
612  SG_WARNING("The existing kernel itself is a precomputed kernel!\n");
613  precompute=true;
614  self->is_kernel_initialized=true;
615  }
616  }
617  }
618  self->precompute=precompute;
619 }
620 
621 void CQuadraticTimeMMD::save_permutation_inds(bool save_inds)
622 {
623  self->permutation_job.m_save_inds=save_inds;
624 }
625 
626 SGMatrix<index_t> CQuadraticTimeMMD::get_permutation_inds() const
627 {
628  return self->permutation_job.m_all_inds;
629 }
630 
631 const char* CQuadraticTimeMMD::get_name() const
632 {
633  return "QuadraticTimeMMD";
634 }
#define SG_INFO(...)
Definition: SGIO.h:117
int32_t index_t
Definition: common.h:72
T * data() const
Definition: SGMatrix.h:237
The Custom Kernel allows for custom user provided kernel matrices.
Definition: CustomKernel.h:36
virtual float64_t compute_statistic()
SGMatrix< float32_t > get_float32_kernel_matrix()
Definition: CustomKernel.h:548
virtual void select_kernel()
Definition: MMD.cpp:114
#define REQUIRE(x,...)
Definition: SGIO.h:205
index_t num_cols
Definition: SGMatrix.h:465
static constexpr index_t DEFAULT_NUM_EIGENVALUES
virtual void set_p(CFeatures *samples_from_p)
virtual float64_t normalize_statistic(float64_t statistic) const
index_t num_rows
Definition: SGMatrix.h:463
SGVector< float64_t > sample_null_spectrum()
virtual void set_q(CFeatures *samples_from_q)
virtual CFeatures * create_merged_copy(CList *others)
Definition: Features.h:235
unique_ptr< CMultiKernelQuadraticTimeMMD > multi_kernel
This class implements the quadratic time Maximum Mean Statistic as described in [1]. The MMD is the distance of two probability distributions and in a RKHS which we denote by .
index_t vlen
Definition: SGVector.h:545
virtual void set_p(CFeatures *samples_from_p)
#define ASSERT(x)
Definition: SGIO.h:200
SGVector< float64_t > gamma_fit_null()
double float64_t
Definition: common.h:60
const index_t get_num_samples_q() const
friend class CMultiKernelQuadraticTimeMMD
T get(const Tag< T > &_tag) const
Definition: SGObject.h:376
internal::DataManager & get_data_mgr()
Class that performs quadratic time MMD test optimized for multiple shift-invariant kernels...
internal::KernelManager & get_kernel_mgr()
const index_t get_num_samples_p() const
void cleanup()
Definition: MMD.cpp:124
#define SG_DEBUG(...)
Definition: SGIO.h:106
all of classes and functions are contained in the shogun namespace
Definition: class_list.h:18
#define SG_SDEBUG(...)
Definition: SGIO.h:167
virtual EKernelType get_kernel_type()=0
uint64_t size() const
Definition: SGMatrix.h:243
The class Features is the base class of all feature objects.
Definition: Features.h:68
#define SG_SERROR(...)
Definition: SGIO.h:178
#define SG_SINFO(...)
Definition: SGIO.h:172
Class DataManager for fetching/streaming test data block-wise. It can handle data coming from multipl...
Definition: DataManager.h:63
CKernel * get_kernel() const
Abstract base class that provides an interface for performing kernel two-sample test using Maximum Me...
Definition: MMD.h:120
The Kernel base class.
SGMatrix< float32_t > get_kernel_matrix()
virtual void set_kernel(CKernel *kernel)
SGVector< float64_t > sample_null_permutation()
#define SG_WARNING(...)
Definition: SGIO.h:127
virtual void set_kernel(CKernel *kernel)
static constexpr bool DEFAULT_PRECOMPUTE
virtual void set_q(CFeatures *samples_from_q)

SHOGUN Machine Learning Toolbox - Documentation