123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- /**
- * @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 "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_ !!!"<<endl;
- }
- if(strcmp("variance",modestr.c_str())==0){
- mode=VARIANCE_DETECTION_MODE;cerr << "One-class classification via GP predictive _variance_ !!!"<<endl;
- }
- //should be beneficial when the amount of training data is small compared to test data (given a well-conditioned kernel)
- computeInverse = config.gB(section,"compute_inverse",false);
- staticNoise = conf->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 );
- }
|