45 #ifndef ROOT_TMVA_MethodSVM
48 #ifndef ROOT_TMVA_Tools
51 #ifndef ROOT_TMVA_Timer
55 #ifndef ROOT_TMVA_SVWorkingSet
59 #ifndef ROOT_TMVA_SVEvent
63 #ifndef ROOT_TMVA_SVKernelFunction
86 TMVA::MethodSVM::MethodSVM( const
TString& jobName, const
TString& methodTitle, DataSetInfo& theData,
88 : MethodBase( jobName, Types::kSVM, methodTitle, theData, theOption, theTargetDir )
98 , fSVKernelFunction(0)
101 , fDoubleSigmaSquared(0)
122 , fSVKernelFunction(0)
125 , fDoubleSigmaSquared(0)
137 if (fInputData !=0) {
delete fInputData; fInputData=0; }
138 if (fSupportVectors !=0 ) {
delete fSupportVectors; fSupportVectors = 0; }
139 if (fWgSet !=0) {
delete fWgSet; fWgSet=0; }
140 if (fSVKernelFunction !=0 ) {
delete fSVKernelFunction; fSVKernelFunction = 0; }
159 SetNormalised(
kTRUE );
164 fInputData =
new std::vector<TMVA::SVEvent*>(0);
165 fSupportVectors =
new std::vector<TMVA::SVEvent*>(0);
174 DeclareOptionRef( fGamma = 1.,
"Gamma",
"RBF kernel parameter: Gamma (size of the Kernel)");
176 DeclareOptionRef( fCost,
"C",
"Cost parameter" );
177 if (DoRegression()) {
182 DeclareOptionRef( fTolerance = 0.01,
"Tol",
"Tolerance parameter" );
183 DeclareOptionRef( fMaxIter = 1000,
"MaxIter",
"Maximum number of training loops" );
193 DeclareOptionRef( fNSubSets = 1,
"NSubSets",
"Number of training subsets" );
194 DeclareOptionRef( fTheKernel =
"Gauss",
"Kernel",
"Uses kernel function");
196 DeclareOptionRef( fDoubleSigmaSquared = 2.,
"Sigma",
"Kernel parameter: sigma");
198 DeclareOptionRef( fOrder = 3,
"Order",
"Polynomial Kernel parameter: polynomial order");
200 DeclareOptionRef( fTheta = 1.,
"Theta",
"Sigmoid Kernel parameter: theta");
201 DeclareOptionRef( fKappa = 1.,
"Kappa",
"Sigmoid Kernel parameter: kappa");
209 if (IgnoreEventsWithNegWeightsInTraining()) {
210 Log() <<
kFATAL <<
"Mechanism to ignore events with negative weights in training not yet available for method: "
211 << GetMethodTypeName()
212 <<
" --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
225 for (
Int_t ievt=0; ievt<
Data()->GetNEvents(); ievt++){
226 if (GetEvent(ievt)->GetWeight() != 0)
227 fInputData->push_back(
new SVEvent(GetEvent(ievt), fCost, DataInfo().IsSignal(GetEvent(ievt))));
232 Log()<<
kINFO <<
"Building SVM Working Set...with "<<fInputData->size()<<
" event instances"<<
Endl;
233 Timer bldwstime( GetName());
234 fWgSet =
new SVWorkingSet( fInputData, fSVKernelFunction,fTolerance, DoRegression() );
239 Log() <<
kINFO <<
"Sorry, no computing time forecast available for SVM, please wait ..." <<
Endl;
241 fWgSet->Train(fMaxIter);
246 fBparm = fWgSet->GetBpar();
247 fSupportVectors = fWgSet->GetSupportVectors();
268 for (std::vector<TMVA::SVEvent*>::iterator veciter=fSupportVectors->begin();
269 veciter!=fSupportVectors->end() ; ++veciter ) {
271 temp[0] = (*veciter)->GetNs();
272 temp[1] = (*veciter)->GetTypeFlag();
273 temp[2] = (*veciter)->GetAlpha();
274 temp[3] = (*veciter)->GetAlpha_p();
275 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++)
276 temp[ivar+4] = (*(*veciter)->GetDataVector())[ivar];
281 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++)
284 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++)
302 std::vector<Float_t>* svector =
new std::vector<Float_t>(GetNvar());
304 if (fMaxVars!=0)
delete fMaxVars;
305 fMaxVars =
new TVectorD( GetNvar() );
306 if (fMinVars!=0)
delete fMinVars;
307 fMinVars =
new TVectorD( GetNvar() );
308 if (fSupportVectors!=0) {
309 for (vector< SVEvent* >::iterator it = fSupportVectors->begin(); it!=fSupportVectors->end(); ++it)
311 delete fSupportVectors;
313 fSupportVectors =
new std::vector<TMVA::SVEvent*>(0);
315 for (
UInt_t ievt = 0; ievt < fNsupv; ievt++) {
319 typeFlag=(int)temp[1];
322 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++) (*svector)[ivar]=temp[ivar+4];
324 fSupportVectors->push_back(
new SVEvent(svector,alpha,alpha_p,typeFlag));
328 void* maxminnode = supportvectornode;
329 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++)
332 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++)
334 if (fSVKernelFunction!=0)
delete fSVKernelFunction;
351 if (fSupportVectors !=0) {
delete fSupportVectors; fSupportVectors = 0;}
352 fSupportVectors =
new std::vector<TMVA::SVEvent*>(0);
360 fSupportVectors->reserve(fNsupv);
366 std::vector<Float_t>* svector =
new std::vector<Float_t>(GetNvar());
368 fMaxVars =
new TVectorD( GetNvar() );
369 fMinVars =
new TVectorD( GetNvar() );
371 for (
UInt_t ievt = 0; ievt < fNsupv; ievt++) {
374 typeFlag = typeTalpha<0?-1:1;
375 alpha = typeTalpha<0?-typeTalpha:typeTalpha;
376 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++) istr >> svector->at(ivar);
378 fSupportVectors->push_back(
new SVEvent(svector,alpha,typeFlag,ns));
381 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++) istr >> (*fMaxVars)[ivar];
383 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++) istr >> (*fMinVars)[ivar];
385 delete fSVKernelFunction;
386 if (fTheKernel ==
"Gauss" ) {
395 Log() <<
kFATAL <<
"Unknown kernel function found in weight file!" <<
Endl;
398 fSVKernelFunction->setCompatibilityParams(k, fOrder, fTheta, fKappa);
420 for (
UInt_t ievt = 0; ievt < fSupportVectors->size() ; ievt++) {
421 myMVA += ( fSupportVectors->at(ievt)->GetAlpha()
422 * fSupportVectors->at(ievt)->GetTypeFlag()
423 * fSVKernelFunction->Evaluate( fSupportVectors->at(ievt), ev ) );
431 NoErrorCalc(err, errUpper);
440 if( fRegressionReturnVal ==
NULL )
441 fRegressionReturnVal =
new std::vector<Float_t>();
442 fRegressionReturnVal->clear();
446 const Event *baseev = GetEvent();
449 for (
UInt_t ievt = 0; ievt < fSupportVectors->size() ; ievt++) {
450 myMVA += ( fSupportVectors->at(ievt)->GetDeltaAlpha()
451 *fSVKernelFunction->Evaluate( fSupportVectors->at(ievt), ev ) );
457 const Event* evT2 = GetTransformationHandler().InverseTransform( evT );
459 fRegressionReturnVal->push_back(evT2->
GetTarget(0));
465 return *fRegressionReturnVal;
473 const int fNsupv = fSupportVectors->size();
474 fout <<
" // not implemented for class: \"" << className <<
"\"" << std::endl;
475 fout <<
" float fBparameter;" << std::endl;
476 fout <<
" int fNOfSuppVec;" << std::endl;
477 fout <<
" static float fAllSuppVectors[][" << fNsupv <<
"];" << std::endl;
478 fout <<
" static float fAlphaTypeCoef[" << fNsupv <<
"];" << std::endl;
480 fout <<
" // Kernel parameter(s) " << std::endl;
481 fout <<
" float fGamma;" << std::endl;
482 fout <<
"};" << std::endl;
483 fout <<
"" << std::endl;
486 fout <<
"inline void " << className <<
"::Initialize() " << std::endl;
487 fout <<
"{" << std::endl;
488 fout <<
" fBparameter = " << fBparm <<
";" << std::endl;
489 fout <<
" fNOfSuppVec = " << fNsupv <<
";" << std::endl;
490 fout <<
" fGamma = " << fGamma <<
";" <<std::endl;
491 fout <<
"}" << std::endl;
495 fout <<
"inline double " << className <<
"::GetMvaValue__(const std::vector<double>& inputValues ) const" << std::endl;
496 fout <<
"{" << std::endl;
497 fout <<
" double mvaval = 0; " << std::endl;
498 fout <<
" double temp = 0; " << std::endl;
500 fout <<
" for (int ievt = 0; ievt < fNOfSuppVec; ievt++ ){" << std::endl;
501 fout <<
" temp = 0;" << std::endl;
502 fout <<
" for ( unsigned int ivar = 0; ivar < GetNvar(); ivar++ ) {" << std::endl;
504 fout <<
" temp += (fAllSuppVectors[ivar][ievt] - inputValues[ivar]) " << std::endl;
505 fout <<
" * (fAllSuppVectors[ivar][ievt] - inputValues[ivar]); " << std::endl;
506 fout <<
" }" << std::endl;
507 fout <<
" mvaval += fAlphaTypeCoef[ievt] * exp( -fGamma * temp ); " << std::endl;
509 fout <<
" }" << std::endl;
510 fout <<
" mvaval -= fBparameter;" << std::endl;
511 fout <<
" return 1./(1. + exp(mvaval));" << std::endl;
512 fout <<
"}" << std::endl;
513 fout <<
"// Clean up" << std::endl;
514 fout <<
"inline void " << className <<
"::Clear() " << std::endl;
515 fout <<
"{" << std::endl;
516 fout <<
" // nothing to clear " << std::endl;
517 fout <<
"}" << std::endl;
518 fout <<
"" << std::endl;
521 fout <<
"float " << className <<
"::fAlphaTypeCoef[] =" << std::endl;
523 for (
Int_t isv = 0; isv < fNsupv; isv++) {
524 fout << fSupportVectors->at(isv)->GetDeltaAlpha() * fSupportVectors->at(isv)->GetTypeFlag();
525 if (isv < fNsupv-1) fout <<
", ";
527 fout <<
" };" << std::endl << std::endl;
529 fout <<
"float " << className <<
"::fAllSuppVectors[][" << fNsupv <<
"] =" << std::endl;
531 for (
UInt_t ivar = 0; ivar < GetNvar(); ivar++) {
534 for (
Int_t isv = 0; isv < fNsupv; isv++){
535 fout << fSupportVectors->at(isv)->GetDataVector()->at(ivar);
536 if (isv < fNsupv-1) fout <<
", ";
539 if (ivar < GetNvar()-1) fout <<
", " << std::endl;
540 else fout << std::endl;
542 fout <<
"};" << std::endl<< std::endl;
556 Log() <<
"The Support Vector Machine (SVM) builds a hyperplance separating" <<
Endl;
557 Log() <<
"signal and background events (vectors) using the minimal subset of " <<
Endl;
558 Log() <<
"all vectors used for training (support vectors). The extension to" <<
Endl;
559 Log() <<
"the non-linear case is performed by mapping input vectors into a " <<
Endl;
560 Log() <<
"higher-dimensional feature space in which linear separation is " <<
Endl;
561 Log() <<
"possible. The use of the kernel functions thereby eliminates the " <<
Endl;
562 Log() <<
"explicit transformation to the feature space. The implemented SVM " <<
Endl;
563 Log() <<
"algorithm performs the classification tasks using linear, polynomial, " <<
Endl;
564 Log() <<
"Gaussian and sigmoidal kernel functions. The Gaussian kernel allows " <<
Endl;
565 Log() <<
"to apply any discriminant shape in the input space." <<
Endl;
569 Log() <<
"SVM is a general purpose non-linear classification method, which " <<
Endl;
570 Log() <<
"does not require data preprocessing like decorrelation or Principal " <<
Endl;
571 Log() <<
"Component Analysis. It generalises quite well and can handle analyses " <<
Endl;
572 Log() <<
"with large numbers of input variables." <<
Endl;
576 Log() <<
"Optimal performance requires primarily a proper choice of the kernel " <<
Endl;
577 Log() <<
"parameters (the width \"Sigma\" in case of Gaussian kernel) and the" <<
Endl;
578 Log() <<
"cost parameter \"C\". The user must optimise them empirically by running" <<
Endl;
579 Log() <<
"SVM several times with different parameter sets. The time needed for " <<
Endl;
580 Log() <<
"each evaluation scales like the square of the number of training " <<
Endl;
581 Log() <<
"events so that a coarse preliminary tuning should be performed on " <<
Endl;
582 Log() <<
"reduced data sets." <<
Endl;
void Train(void)
Train SVM.
ClassImp(TMVA::MethodSVM) TMVA
standard constructor
void DeclareCompatibilityOptions()
options that are used ONLY for the READER to ensure backward compatibility
MsgLogger & Endl(MsgLogger &ml)
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
void MakeClassSpecific(std::ostream &, const TString &) const
write specific classifier response
void SetTarget(UInt_t itgt, Float_t value)
set the target value (dimension itgt) to value
void ProcessOptions()
option post processing (if necessary)
std::vector< std::vector< double > > Data
void DeclareOptions()
declare options available for this method
TVectorT< Double_t > TVectorD
TString GetElapsedTime(Bool_t Scientific=kTRUE)
void AddWeightsXMLTo(void *parent) const
write configuration to xml file
void ReadWeightsFromXML(void *wghtnode)
void ReadWeightsFromStream(std::istream &istr)
void Init(void)
default initialisation
virtual Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets)
SVM can handle classification with 2 classes and regression with one regression-target.
Double_t GetMvaValue(Double_t *err=0, Double_t *errUpper=0)
returns MVA value for given event
MethodSVM(const TString &jobName, const TString &methodTitle, DataSetInfo &theData, const TString &theOption="", TDirectory *theTargetDir=0)
Describe directory structure in memory.
Float_t GetTarget(UInt_t itgt) const
#define REGISTER_METHOD(CLASS)
for example
virtual ~MethodSVM(void)
destructor
virtual void DeclareCompatibilityOptions()
options that are used ONLY for the READER to ensure backward compatibility they are hence without any...
void WriteWeightsToStream(TFile &fout) const
TODO write IT write training sample (TTree) to file.
void GetHelpMessage() const
get help message text
const std::vector< Float_t > & GetRegressionValues()