KCMinimumEnclosingBall.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /**
  2. * @file KCGPOneClass.cpp
  3. * @brief One-Class Gaussian Process Regression for Classification
  4. * @author Erik Rodner + Mi.Ke.
  5. * @date 12/03/2010
  6. */
  7. #include <iostream>
  8. #include <typeinfo>
  9. #include "KCMinimumEnclosingBall.h"
  10. using namespace std;
  11. using namespace NICE;
  12. using namespace OBJREC;
  13. KCMinimumEnclosingBall::KCMinimumEnclosingBall( const Config *conf, Kernel *kernel, const string & section )
  14. : KernelClassifier ( conf, kernel )
  15. {
  16. //specify parameters, if any
  17. nu = conf->gD(section,"outlier_fraction");
  18. fprintf(stderr,"\nUsing (upper bound) outlier fraction of nu=%f (upper bound is so far guaranteed only for stationary kernels)\n",nu);
  19. if(nu<0 || nu>1){
  20. fprintf(stderr,"ERROR: Outlier fraction 'nu' (outlier_fraction) specifies must be in [0,1] !!!\n\n");
  21. exit(-1);
  22. }
  23. }
  24. KCMinimumEnclosingBall::KCMinimumEnclosingBall( const KCMinimumEnclosingBall & src ) : KernelClassifier ( src )
  25. {
  26. this->alpha=src.alpha;
  27. this->radius=src.radius;
  28. this->aKa=src.aKa;
  29. this->nu=src.nu;
  30. this->trainingSize=src.trainingSize;
  31. this->TwoK=src.TwoK;
  32. this->Eye=src.Eye;
  33. this->Ones=src.Ones;
  34. this->ones=src.ones;
  35. this->b=src.b;
  36. this->minusDiagK=src.minusDiagK;
  37. this->minusOne=src.minusOne;
  38. this->zeros=src.zeros;
  39. }
  40. KCMinimumEnclosingBall::~KCMinimumEnclosingBall()
  41. {
  42. }
  43. void KCMinimumEnclosingBall::teach ( KernelData *kernelData, const NICE::Vector & y )
  44. {
  45. NICE::Matrix kernelMatrix = kernelData->getKernelMatrix();
  46. trainingSize=kernelMatrix.rows();
  47. int n=trainingSize;
  48. if(nu==0.0){ //no outlier, i.e. hard minimum enclosing ball algorithm
  49. TwoK.resize(n,n);
  50. Eye.resize(n,n);
  51. minusDiagK.resize(n);
  52. Ones.resize(n,1);
  53. minusOne.resize(1);
  54. zeros.resize(n);
  55. alpha.resize(n);
  56. for(int i=0;i<n;i++){
  57. for(int j=0;j<n;j++){
  58. Eye[i][j]= ( i==j ? 1 : 0 );
  59. TwoK[i][j]=2*kernelMatrix(i,j);
  60. }
  61. minusDiagK[i]=-kernelMatrix(i,i);
  62. Ones[i][0]=1;
  63. zeros[i]=0;
  64. }
  65. minusOne[0]=-1;
  66. }else{ //soft MEB problem (more complicated since we must introduce further inequalities)
  67. TwoK.resize(n,n);
  68. Eye.resize(n,2*n); // instead of Id, we also insert -Id (to the right of Id)
  69. minusDiagK.resize(n);
  70. Ones.resize(n,1);
  71. minusOne.resize(1);
  72. zeros.resize(2*n); // instead of zeros we also insert 1/(v*n)
  73. alpha.resize(n);
  74. for(int i=0;i<n;i++){
  75. for(int j=0;j<n;j++){
  76. Eye[i][j]= ( i==j ? 1 : 0 );
  77. Eye[i][n+j]= ( i==j ? -1 : 0 );
  78. TwoK[i][j]=2*kernelMatrix(i,j);
  79. }
  80. minusDiagK[i]=-kernelMatrix(i,i);
  81. Ones[i][0]=1;
  82. zeros[i]=0;
  83. zeros[n+i]=1.0/(nu*double(n));
  84. }
  85. minusOne[0]=-1;
  86. }
  87. QuadProgPP::solve_quadprog(TwoK, minusDiagK, Ones, minusOne, Eye, zeros, alpha);
  88. radius=0.0;
  89. aKa=0.0;
  90. double rad2=-1e+100,tmp;
  91. for(int i=0;i<n;i++){
  92. tmp=0.0;
  93. for(int j=0;j<n;j++){
  94. aKa+=0.5*alpha[i]*TwoK[i][j]*alpha[j];
  95. tmp+=-TwoK[i][j]*alpha[j];
  96. }
  97. if( (alpha[i]>1e-10) && (alpha[i]<1/(n*nu)+1e-10) ){
  98. tmp+=0.5*TwoK[i][i];
  99. rad2=(rad2>tmp ? rad2 : tmp);
  100. }
  101. //fprintf(stderr,"alpha_%d=%f\t 1/vl=%f\t 0>alpha<1/vl? %d => R_%d=aKa+%f\n",i,alpha[i],1.0/(nu*n),((alpha[i]>1e-10)&&alpha[i]<1/(n*nu)+1e-10),i,tmp);
  102. }
  103. radius=aKa+rad2;
  104. //fprintf(stderr,"\nfinal radius R=aKa+%f\n",rad2);
  105. }
  106. ClassificationResult KCMinimumEnclosingBall::classifyKernel ( const NICE::Vector & kernelVector, double kernelSelf ) const
  107. {
  108. FullVector scores ( 2 );
  109. scores[0] = 0.0;
  110. double rest = 0.0;
  111. for(int i=0;i<trainingSize;i++){
  112. rest+=-2*kernelVector[i]*alpha[i];
  113. }
  114. rest=rest+kernelSelf;
  115. double inlierness = radius - (aKa + rest);
  116. scores[1] = inlierness;
  117. ClassificationResult r ( inlierness<0 ? 0 : 1, scores );
  118. return r;
  119. }
  120. KCMinimumEnclosingBall *KCMinimumEnclosingBall::clone() const
  121. {
  122. return new KCMinimumEnclosingBall ( *this );
  123. }