123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /**
- * @file KCGPOneClass.cpp
- * @brief One-Class Gaussian Process Regression for Classification
- * @author Erik Rodner + Mi.Ke.
- * @date 12/03/2010
- */
- #include <iostream>
- #include <typeinfo>
- #include "KCMinimumEnclosingBall.h"
- using namespace std;
- using namespace NICE;
- using namespace OBJREC;
- KCMinimumEnclosingBall::KCMinimumEnclosingBall( const Config *conf, Kernel *kernel, const string & section )
- : KernelClassifier ( conf, kernel )
- {
- //specify parameters, if any
- nu = conf->gD(section,"outlier_fraction");
- fprintf(stderr,"\nUsing (upper bound) outlier fraction of nu=%f (upper bound is so far guaranteed only for stationary kernels)\n",nu);
- if(nu<0 || nu>1){
- fprintf(stderr,"ERROR: Outlier fraction 'nu' (outlier_fraction) specifies must be in [0,1] !!!\n\n");
- exit(-1);
- }
- }
- KCMinimumEnclosingBall::KCMinimumEnclosingBall( const KCMinimumEnclosingBall & src ) : KernelClassifier ( src )
- {
- this->alpha=src.alpha;
- this->radius=src.radius;
- this->aKa=src.aKa;
- this->nu=src.nu;
- this->trainingSize=src.trainingSize;
- this->TwoK=src.TwoK;
- this->Eye=src.Eye;
- this->Ones=src.Ones;
- this->ones=src.ones;
- this->b=src.b;
- this->minusDiagK=src.minusDiagK;
- this->minusOne=src.minusOne;
- this->zeros=src.zeros;
- }
- KCMinimumEnclosingBall::~KCMinimumEnclosingBall()
- {
- }
- void KCMinimumEnclosingBall::teach ( KernelData *kernelData, const NICE::Vector & y )
- {
- NICE::Matrix kernelMatrix = kernelData->getKernelMatrix();
- trainingSize=kernelMatrix.rows();
- int n=trainingSize;
- if(nu==0.0){ //no outlier, i.e. hard minimum enclosing ball algorithm
- TwoK.resize(n,n);
- Eye.resize(n,n);
- minusDiagK.resize(n);
- Ones.resize(n,1);
- minusOne.resize(1);
- zeros.resize(n);
- alpha.resize(n);
- for(int i=0;i<n;i++){
- for(int j=0;j<n;j++){
- Eye[i][j]= ( i==j ? 1 : 0 );
- TwoK[i][j]=2*kernelMatrix(i,j);
- }
- minusDiagK[i]=-kernelMatrix(i,i);
- Ones[i][0]=1;
- zeros[i]=0;
- }
- minusOne[0]=-1;
- }else{ //soft MEB problem (more complicated since we must introduce further inequalities)
- TwoK.resize(n,n);
- Eye.resize(n,2*n); // instead of Id, we also insert -Id (to the right of Id)
- minusDiagK.resize(n);
- Ones.resize(n,1);
- minusOne.resize(1);
- zeros.resize(2*n); // instead of zeros we also insert 1/(v*n)
- alpha.resize(n);
- for(int i=0;i<n;i++){
- for(int j=0;j<n;j++){
- Eye[i][j]= ( i==j ? 1 : 0 );
- Eye[i][n+j]= ( i==j ? -1 : 0 );
- TwoK[i][j]=2*kernelMatrix(i,j);
- }
- minusDiagK[i]=-kernelMatrix(i,i);
- Ones[i][0]=1;
- zeros[i]=0;
- zeros[n+i]=1.0/(nu*double(n));
- }
- minusOne[0]=-1;
- }
- QuadProgPP::solve_quadprog(TwoK, minusDiagK, Ones, minusOne, Eye, zeros, alpha);
- radius=0.0;
- aKa=0.0;
- double rad2=-1e+100,tmp;
- for(int i=0;i<n;i++){
- tmp=0.0;
- for(int j=0;j<n;j++){
- aKa+=0.5*alpha[i]*TwoK[i][j]*alpha[j];
- tmp+=-TwoK[i][j]*alpha[j];
- }
- if( (alpha[i]>1e-10) && (alpha[i]<1/(n*nu)+1e-10) ){
- tmp+=0.5*TwoK[i][i];
- rad2=(rad2>tmp ? rad2 : tmp);
- }
- //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);
- }
- radius=aKa+rad2;
- //fprintf(stderr,"\nfinal radius R=aKa+%f\n",rad2);
- }
-
- ClassificationResult KCMinimumEnclosingBall::classifyKernel ( const NICE::Vector & kernelVector, double kernelSelf ) const
- {
- FullVector scores ( 2 );
- scores[0] = 0.0;
- double rest = 0.0;
- for(int i=0;i<trainingSize;i++){
- rest+=-2*kernelVector[i]*alpha[i];
- }
- rest=rest+kernelSelf;
- double inlierness = radius - (aKa + rest);
- scores[1] = inlierness;
- ClassificationResult r ( inlierness<0 ? 0 : 1, scores );
- return r;
- }
- KCMinimumEnclosingBall *KCMinimumEnclosingBall::clone() const
- {
- return new KCMinimumEnclosingBall ( *this );
- }
|