MKLMultiClass.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "classifier/mkl/MKLMultiClass.h"
00012 #include "lib/io.h"
00013
00014 using namespace shogun;
00015
00016
00017 CMKLMultiClass::CMKLMultiClass()
00018 : CMultiClassSVM(ONE_VS_REST)
00019 {
00020 svm=NULL;
00021 lpw=NULL;
00022
00023 mkl_eps=0.01;
00024 max_num_mkl_iters=999;
00025 }
00026
00027 CMKLMultiClass::CMKLMultiClass(float64_t C, CKernel* k, CLabels* lab)
00028 : CMultiClassSVM(ONE_VS_REST, C, k, lab)
00029 {
00030 svm=NULL;
00031 lpw=NULL;
00032
00033 mkl_eps=0.01;
00034 max_num_mkl_iters=999;
00035
00036 }
00037
00038
00039 CMKLMultiClass::~CMKLMultiClass()
00040 {
00041 SG_UNREF(svm);
00042 svm=NULL;
00043 delete lpw;
00044 lpw=NULL;
00045 }
00046
00047 CMKLMultiClass::CMKLMultiClass( const CMKLMultiClass & cm)
00048 : CMultiClassSVM(ONE_VS_REST)
00049 {
00050 svm=NULL;
00051 lpw=NULL;
00052 SG_ERROR(
00053 " CMKLMultiClass::CMKLMultiClass(const CMKLMultiClass & cm): must "
00054 "not be called, glpk structure is currently not copyable");
00055 }
00056
00057 CMKLMultiClass CMKLMultiClass::operator=( const CMKLMultiClass & cm)
00058 {
00059 SG_ERROR(
00060 " CMKLMultiClass CMKLMultiClass::operator=(...): must "
00061 "not be called, glpk structure is currently not copyable");
00062 return (*this);
00063 }
00064
00065
00066 void CMKLMultiClass::initsvm()
00067 {
00068 if (!labels)
00069 {
00070 SG_ERROR("CMKLMultiClass::initsvm(): the set labels is NULL\n");
00071 }
00072
00073 SG_UNREF(svm);
00074 svm=new CGMNPSVM;
00075 SG_REF(svm);
00076
00077 svm->set_C(get_C1(),get_C2());
00078 svm->set_epsilon(epsilon);
00079
00080 int32_t numlabels;
00081 float64_t * lb=labels->get_labels ( numlabels);
00082
00083 if (numlabels<=0)
00084 {
00085 SG_ERROR("CMKLMultiClass::initsvm(): the number of labels is "
00086 "nonpositive, do not know how to handle this!\n");
00087 }
00088
00089 CLabels* newlab=new CLabels(lb, labels->get_num_labels() );
00090 delete[] lb;
00091 lb=NULL;
00092
00093 svm->set_labels(newlab);
00094
00095 newlab=NULL;
00096 }
00097
00098 void CMKLMultiClass::initlpsolver()
00099 {
00100 if (!kernel)
00101 {
00102 SG_ERROR("CMKLMultiClass::initlpsolver(): the set kernel is NULL\n");
00103 }
00104
00105 if (kernel->get_kernel_type()!=K_COMBINED)
00106 {
00107 SG_ERROR("CMKLMultiClass::initlpsolver(): given kernel is not of type"
00108 " K_COMBINED %d required by Multiclass Mkl \n",
00109 kernel->get_kernel_type());
00110 }
00111
00112 int numker=dynamic_cast<CCombinedKernel *>(kernel)->get_num_subkernels();
00113
00114 ASSERT(numker>0);
00115
00116
00117
00118
00119
00120
00121 lpw=new MKLMultiClassGLPK;
00122 lpw->setup(numker);
00123 }
00124
00125
00126 bool CMKLMultiClass::evaluatefinishcriterion(const int32_t
00127 numberofsilpiterations)
00128 {
00129 if ( (max_num_mkl_iters>0) && (numberofsilpiterations>=max_num_mkl_iters) )
00130 {
00131 return(true);
00132 }
00133
00134 if (weightshistory.size()>1)
00135 {
00136 std::vector<float64_t> wold,wnew;
00137
00138 wold=weightshistory[ weightshistory.size()-2 ];
00139 wnew=weightshistory.back();
00140 float64_t delta=0;
00141
00142 ASSERT (wold.size()==wnew.size());
00143
00144 for (size_t i=0;i< wnew.size();++i)
00145 {
00146 delta+=(wold[i]-wnew[i])*(wold[i]-wnew[i]);
00147 }
00148 delta=sqrt(delta);
00149
00150 if( (delta < mkl_eps) && (numberofsilpiterations>=1) )
00151 {
00152 return(true);
00153 }
00154 }
00155
00156 return(false);
00157 }
00158
00159 void CMKLMultiClass::addingweightsstep( const std::vector<float64_t> &
00160 curweights)
00161 {
00162
00163 if (weightshistory.size()>2)
00164 {
00165 weightshistory.erase(weightshistory.begin());
00166 }
00167
00168 float64_t* weights(NULL);
00169 weights=new float64_t[curweights.size()];
00170 std::copy(curweights.begin(),curweights.end(),weights);
00171
00172 kernel->set_subkernel_weights( weights, curweights.size());
00173 delete[] weights;
00174 weights=NULL;
00175
00176 initsvm();
00177
00178 svm->set_kernel(kernel);
00179 svm->train();
00180
00181 float64_t sumofsignfreealphas=getsumofsignfreealphas();
00182 int32_t numkernels=
00183 dynamic_cast<CCombinedKernel *>(kernel)->get_num_subkernels();
00184
00185
00186 std::vector<float64_t> normw2(numkernels);
00187 for (int32_t ind=0; ind < numkernels; ++ind )
00188 {
00189 normw2[ind]=getsquarenormofprimalcoefficients( ind );
00190 }
00191
00192 lpw->addconstraint(normw2,sumofsignfreealphas);
00193 }
00194
00195 float64_t CMKLMultiClass::getsumofsignfreealphas()
00196 {
00197
00198 std::vector<int> trainlabels2(labels->get_num_labels());
00199 int32_t tmpint;
00200 int32_t * lab=labels->get_int_labels ( tmpint);
00201 std::copy(lab,lab+labels->get_num_labels(), trainlabels2.begin());
00202 delete[] lab;
00203 lab=NULL;
00204
00205
00206 ASSERT (trainlabels2.size()>0);
00207 float64_t sum=0;
00208
00209 for (int32_t nc=0; nc< labels->get_num_classes();++nc)
00210 {
00211 CSVM * sm=svm->get_svm(nc);
00212
00213 float64_t bia=sm->get_bias();
00214 sum+= bia*bia;
00215
00216 SG_UNREF(sm);
00217 }
00218
00219 ::std::vector< ::std::vector<float64_t> > basealphas;
00220 svm->getbasealphas( basealphas);
00221
00222 for (size_t lb=0; lb< trainlabels2.size();++lb)
00223 {
00224 for (int32_t nc=0; nc< labels->get_num_classes();++nc)
00225 {
00226 CSVM * sm=svm->get_svm(nc);
00227
00228 if ((int)nc!=trainlabels2[lb])
00229 {
00230 CSVM * sm2=svm->get_svm(trainlabels2[lb]);
00231
00232 float64_t bia1=sm2->get_bias();
00233 float64_t bia2=sm->get_bias();
00234 SG_UNREF(sm2);
00235
00236 sum+= -basealphas[nc][lb]*(bia1-bia2-1);
00237 }
00238 SG_UNREF(sm);
00239 }
00240 }
00241
00242 return(sum);
00243 }
00244
00245 float64_t CMKLMultiClass::getsquarenormofprimalcoefficients(
00246 const int32_t ind)
00247 {
00248 CKernel * ker=dynamic_cast<CCombinedKernel *>(kernel)->get_kernel(ind);
00249
00250 float64_t tmp=0;
00251
00252 for (int32_t classindex=0; classindex< labels->get_num_classes();
00253 ++classindex)
00254 {
00255 CSVM * sm=svm->get_svm(classindex);
00256
00257 for (int32_t i=0; i < sm->get_num_support_vectors(); ++i)
00258 {
00259 float64_t alphai=sm->get_alpha(i);
00260 int32_t svindi= sm->get_support_vector(i);
00261
00262 for (int32_t k=0; k < sm->get_num_support_vectors(); ++k)
00263 {
00264 float64_t alphak=sm->get_alpha(k);
00265 int32_t svindk=sm->get_support_vector(k);
00266
00267 tmp+=alphai*ker->kernel(svindi,svindk)
00268 *alphak;
00269
00270 }
00271 }
00272 SG_UNREF(sm);
00273 }
00274 SG_UNREF(ker);
00275 ker=NULL;
00276
00277 return(tmp);
00278 }
00279
00280
00281 bool CMKLMultiClass::train(CFeatures* data)
00282 {
00283 int numcl=labels->get_num_classes();
00284 ASSERT(kernel);
00285 ASSERT(labels && labels->get_num_labels());
00286
00287 if (data)
00288 {
00289 if (labels->get_num_labels() != data->get_num_vectors())
00290 SG_ERROR("Number of training vectors does not match number of "
00291 "labels\n");
00292 kernel->init(data, data);
00293 }
00294
00295 initlpsolver();
00296
00297 weightshistory.clear();
00298
00299 int32_t numkernels=
00300 dynamic_cast<CCombinedKernel *>(kernel)->get_num_subkernels();
00301
00302 ::std::vector<float64_t> curweights(numkernels,1.0/numkernels);
00303 weightshistory.push_back(curweights);
00304
00305 addingweightsstep(curweights);
00306
00307 int32_t numberofsilpiterations=0;
00308 bool final=false;
00309 while (!final)
00310 {
00311
00312 curweights.clear();
00313 lpw->computeweights(curweights);
00314 weightshistory.push_back(curweights);
00315
00316
00317 final=evaluatefinishcriterion(numberofsilpiterations);
00318 ++numberofsilpiterations;
00319
00320 addingweightsstep(curweights);
00321
00322 }
00323
00324
00325
00326 ASSERT(numcl>=1);
00327 create_multiclass_svm(numcl);
00328
00329 for (int32_t i=0; i<numcl; i++)
00330 {
00331 CSVM* osvm=svm->get_svm(i);
00332 CSVM* nsvm=new CSVM(osvm->get_num_support_vectors());
00333
00334 for (int32_t k=0; k<osvm->get_num_support_vectors() ; k++)
00335 {
00336 nsvm->set_alpha(k, osvm->get_alpha(k) );
00337 nsvm->set_support_vector(k,osvm->get_support_vector(k) );
00338 }
00339 nsvm->set_bias(osvm->get_bias() );
00340 set_svm(i, nsvm);
00341
00342 SG_UNREF(osvm);
00343 osvm=NULL;
00344 }
00345
00346 SG_UNREF(svm);
00347 svm=NULL;
00348 if (lpw)
00349 {
00350 delete lpw;
00351 }
00352 lpw=NULL;
00353 return(true);
00354 }
00355
00356
00357
00358
00359 float64_t* CMKLMultiClass::getsubkernelweights(int32_t & numweights)
00360 {
00361 if ( weightshistory.empty() )
00362 {
00363 numweights=0;
00364 return NULL;
00365 }
00366
00367 std::vector<float64_t> subkerw=weightshistory.back();
00368 numweights=weightshistory.back().size();
00369
00370 float64_t* res=new float64_t[numweights];
00371 std::copy(weightshistory.back().begin(), weightshistory.back().end(),res);
00372 return res;
00373 }
00374
00375 void CMKLMultiClass::set_mkl_epsilon(float64_t eps )
00376 {
00377 mkl_eps=eps;
00378 }
00379
00380 void CMKLMultiClass::set_max_num_mkliters(int32_t maxnum)
00381 {
00382 max_num_mkl_iters=maxnum;
00383 }