pktools  2.6.7
Processing Kernel for geospatial data
CostFactorySVM.cc
1 /**********************************************************************
2 CostFactorySVM.cc: select features, typical use: feature selection for classification
3 Copyright (C) 2008-2014 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #include "CostFactorySVM.h"
21 #include "svm.h"
22 
23 #define Malloc(type,n) (type *)malloc((n)*sizeof(type))
24 
25 CostFactorySVM::CostFactorySVM()
26  : CostFactory(2,0), m_svm_type("C_SVC"), m_kernel_type("radial"), m_kernel_degree(3), m_gamma(1.0), m_coef0(0), m_ccost(1000), m_nu(0.5), m_epsilon_loss(100), m_cache(100), m_epsilon_tol(0.001), m_shrinking(false), m_prob_est(true){
27 }
28 
29 CostFactorySVM::~CostFactorySVM(){
30 }
31 
32 CostFactorySVM::CostFactorySVM(std::string svm_type, std::string kernel_type, unsigned short kernel_degree, float gamma, float coef0, float ccost, float nu, float epsilon_loss, int cache, float epsilon_tol, bool shrinking, bool prob_est, unsigned short cv, short verbose)
33  : CostFactory(cv,verbose), m_svm_type(svm_type), m_kernel_type(kernel_type), m_kernel_degree(kernel_degree), m_gamma(gamma), m_coef0(coef0), m_ccost(ccost), m_nu(nu), m_epsilon_loss(epsilon_loss), m_cache(cache), m_epsilon_tol(epsilon_tol), m_shrinking(shrinking), m_prob_est(prob_est){};
34 
35 double CostFactorySVM::getCost(const std::vector<Vector2d<float> > &trainingFeatures){
36  std::map<std::string, svm::SVM_TYPE> svmMap;
37 
38  svmMap["C_SVC"]=svm::C_SVC;
39  svmMap["nu_SVC"]=svm::nu_SVC;
40  svmMap["one_class"]=svm::one_class;
41  svmMap["epsilon_SVR"]=svm::epsilon_SVR;
42  svmMap["nu_SVR"]=svm::nu_SVR;
43 
44  std::map<std::string, svm::KERNEL_TYPE> kernelMap;
45 
46  kernelMap["linear"]=svm::linear;
47  kernelMap["polynomial"]=svm::polynomial;
48  kernelMap["radial"]=svm::radial;
49  kernelMap["sigmoid;"]=svm::sigmoid;
50 
51  unsigned short nclass=trainingFeatures.size();
52  unsigned int ntraining=0;
53  unsigned int ntest=0;
54  for(int iclass=0;iclass<nclass;++iclass){
55  ntraining+=m_nctraining[iclass];
56  ntest+=m_nctest[iclass];
57  }
58  if(ntest)
59  assert(!m_cv);
60  if(!m_cv)
61  assert(ntest);
62  unsigned short nFeatures=trainingFeatures[0][0].size();
63 
64  struct svm_parameter param;
65  param.svm_type = svmMap[m_svm_type];
66  param.kernel_type = kernelMap[m_kernel_type];
67  param.degree = m_kernel_degree;
68  param.gamma = (m_gamma>0)? m_gamma : 1.0/nFeatures;
69  param.coef0 = m_coef0;
70  param.nu = m_nu;
71  param.cache_size = m_cache;
72  param.C = m_ccost;
73  param.eps = m_epsilon_tol;
74  param.p = m_epsilon_loss;
75  param.shrinking = (m_shrinking)? 1 : 0;
76  param.probability = (m_prob_est)? 1 : 0;
77  param.nr_weight = 0;//not used: I use priors and balancing
78  param.weight_label = NULL;
79  param.weight = NULL;
80  param.verbose=(m_verbose>1)? true:false;
81  struct svm_model* svm;
82  struct svm_problem prob;
83  struct svm_node* x_space;
84 
85  prob.l=ntraining;
86  prob.y = Malloc(double,prob.l);
87  prob.x = Malloc(struct svm_node *,prob.l);
88  x_space = Malloc(struct svm_node,(nFeatures+1)*ntraining);
89  unsigned long int spaceIndex=0;
90  int lIndex=0;
91  for(int iclass=0;iclass<nclass;++iclass){
92  // for(int isample=0;isample<trainingFeatures[iclass].size();++isample){
93  for(int isample=0;isample<m_nctraining[iclass];++isample){
94  prob.x[lIndex]=&(x_space[spaceIndex]);
95  for(int ifeature=0;ifeature<nFeatures;++ifeature){
96  x_space[spaceIndex].index=ifeature+1;
97  x_space[spaceIndex].value=trainingFeatures[iclass][isample][ifeature];
98  ++spaceIndex;
99  }
100  x_space[spaceIndex++].index=-1;
101  prob.y[lIndex]=iclass;
102  ++lIndex;
103  }
104  }
105 
106  assert(lIndex==prob.l);
107  if(m_verbose>2)
108  std::cout << "checking parameters" << std::endl;
109  svm_check_parameter(&prob,&param);
110  if(m_verbose>2)
111  std::cout << "parameters ok, training" << std::endl;
112  svm=svm_train(&prob,&param);
113  if(m_verbose>2)
114  std::cout << "SVM is now trained" << std::endl;
115 
116  m_cm.clearResults();
117  if(m_cv>1){
118  double *target = Malloc(double,prob.l);
119  svm_cross_validation(&prob,&param,m_cv,target);
120  assert(param.svm_type != EPSILON_SVR&&param.svm_type != NU_SVR);//only for regression
121  for(int i=0;i<prob.l;i++){
122  std::string refClassName=m_nameVector[prob.y[i]];
123  std::string className=m_nameVector[target[i]];
124  if(m_classValueMap.size())
125  m_cm.incrementResult(type2string<short>(m_classValueMap[refClassName]),type2string<short>(m_classValueMap[className]),1.0);
126  else
127  m_cm.incrementResult(m_cm.getClass(prob.y[i]),m_cm.getClass(target[i]),1.0);
128  }
129  free(target);
130  }
131  else{
132  struct svm_node *x_test;
133  std::vector<double> result(nclass);
134  x_test = Malloc(struct svm_node,(nFeatures+1));
135  for(int iclass=0;iclass<nclass;++iclass){
136  for(int isample=0;isample<m_nctest[iclass];++isample){
137  for(int ifeature=0;ifeature<nFeatures;++ifeature){
138  x_test[ifeature].index=ifeature+1;
139  x_test[ifeature].value=trainingFeatures[iclass][m_nctraining[iclass]+isample][ifeature];
140  }
141  x_test[nFeatures].index=-1;
142  double predict_label=0;
143  assert(svm_check_probability_model(svm));
144  predict_label = svm_predict_probability(svm,x_test,&(result[0]));
145  // predict_label = svm_predict(svm,x_test);
146  std::string refClassName=m_nameVector[iclass];
147  std::string className=m_nameVector[static_cast<short>(predict_label)];
148  if(m_classValueMap.size())
149  m_cm.incrementResult(type2string<short>(m_classValueMap[refClassName]),type2string<short>(m_classValueMap[className]),1.0);
150  else
151  m_cm.incrementResult(refClassName,className,1.0);
152  }
153  }
154  free(x_test);
155  }
156  if(m_verbose>1)
157  std::cout << m_cm << std::endl;
158  assert(m_cm.nReference());
159  // if(m_verbose)
160 
161  // std::cout << m_cm << std::endl;
162  // std::cout << "Kappa: " << m_cm.kappa() << std::endl;
163  // double se95_oa=0;
164  // double doa=0;
165  // doa=m_cm.oa_pct(&se95_oa);
166  // std::cout << "Overall Accuracy: " << doa << " (" << se95_oa << ")" << std::endl;
167 
168  // *NOTE* Because svm_model contains pointers to svm_problem, you can
169  // not free the memory used by svm_problem if you are still using the
170  // svm_model produced by svm_train().
171  // however, we will re-train the svm later on after the feature selection
172  free(prob.y);
173  free(prob.x);
174  free(x_space);
175  svm_free_and_destroy_model(&(svm));
176 
177  return(m_cm.kappa());
178 }
Definition: svm.h:53
Definition: svm.h:12