/** * @file KCGPOneClass.cpp * @brief One-Class Gaussian Process Regression for Classification * @author Erik Rodner + Mi.Ke. * @date 12/03/2010 */ #include #include #include "core/vector/Algorithms.h" #include "vislearning/regression/gpregression/RegGaussianProcess.h" #include "KCGPOneClass.h" using namespace std; using namespace NICE; using namespace OBJREC; KCGPOneClass::KCGPOneClass( const Config *conf, Kernel *kernel, const string & section ) : KernelClassifier ( conf, kernel ) { //overwrite the default optimization options, since we don't want to perform standard loo or marginal likelihood stuff Config config(*conf); string modestr = config.gS(section,"detection_mode"); //enforce not to use the optimization routines (wich would lead to a disaster in the 1-class case) config.sB(section, "optimize_parameters", false ); regressionAlgorithm = new RegGaussianProcess ( &config, kernel, section ); if(strcmp("mean",modestr.c_str())==0){ mode=MEAN_DETECTION_MODE;cerr << "One-class classification via GP predictive _mean_ !!!"<gD(section, "static_noise", 0.0); } KCGPOneClass::KCGPOneClass( const KCGPOneClass & src ) : KernelClassifier ( src ) { regressionAlgorithm = src.regressionAlgorithm->clone(); y = src.y; } KCGPOneClass::~KCGPOneClass() { delete regressionAlgorithm; } void KCGPOneClass::teach ( KernelData *kernelData, const NICE::Vector & y ) { if ( y.size() <= 0 ) { fthrow(Exception, "Number of training vectors is zero!"); } if ( almostZero(kernelData->getKernelMatrix().Max()) ) { fthrow(Exception, "Kernel matrix seems to be not positive definite!"); } //cerr << kernelMatrix << endl; this->y.resize ( y.size() ); this->y = y; this->y = 2*this->y; this->y += -1.0; if ( (this->y.Min() != 1) || (this->y.Max() != 1) ) { fthrow(Exception, "This classifier is suitable only for one-class classification problems, i.e. max(y) = min(y) = 1"); } if ( staticNoise != 0.0 ) kernelData->getKernelMatrix().addIdentity ( staticNoise ); regressionAlgorithm->teach ( kernelData, this->y ); if(mode==VARIANCE_DETECTION_MODE){ if(computeInverse){ kernelData->updateInverseKernelMatrix(); InverseKernelMatrix = kernelData->getInverseKernelMatrix(); }else{ this->kernelData=kernelData; } } } ClassificationResult KCGPOneClass::classifyKernel ( const NICE::Vector & kernelVector, double kernelSelf ) const { FullVector scores ( 2 ); scores[0] = 0.0; if(mode==MEAN_DETECTION_MODE){ double yEstimate = regressionAlgorithm->predictKernel ( kernelVector,kernelSelf ); scores[1] = yEstimate; } if(mode==VARIANCE_DETECTION_MODE){ if(computeInverse){ NICE::Vector kInvkstar = InverseKernelMatrix*kernelVector; double sigmaEstimate = kernelSelf - kernelVector.scalarProduct ( kInvkstar ); scores[1] = 1.0-sigmaEstimate; }else{ NICE::Vector kInvkstar; kInvkstar.resize ( kernelVector.size() ); kernelData->computeInverseKernelMultiply ( kernelVector, kInvkstar); double sigmaEstimate = kernelSelf - kernelVector.scalarProduct ( kInvkstar ); scores[1] = 1.0-sigmaEstimate; } } ClassificationResult r ( scores[1]<0.5 ? 0 : 1, scores ); return r; } KCGPOneClass *KCGPOneClass::clone() const { return new KCGPOneClass ( *this ); }