SHOGUN  6.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
MKLMulticlass.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2009 Alexander Binder
8  * Copyright (C) 2009 Fraunhofer Institute FIRST and Max-Planck-Society
9  *
10  * Update to patch 0.10.0 - thanks to Eric aka Yoo (thereisnoknife@gmail.com)
11  *
12  */
13 
16 #include <shogun/io/SGIO.h>
18 
19 #include <vector>
20 #include <shogun/lib/Signal.h>
21 
22 using namespace shogun;
23 
24 
27 {
28  svm=NULL;
29  lpw=NULL;
30 
31  mkl_eps=0.01;
33  pnorm=1;
34 }
35 
38 {
39  svm=NULL;
40  lpw=NULL;
41 
42  mkl_eps=0.01;
44  pnorm=1;
45 }
46 
47 
49 {
50  SG_UNREF(svm);
51  svm=NULL;
52  delete lpw;
53  lpw=NULL;
54 }
55 
58 {
59  svm=NULL;
60  lpw=NULL;
61  SG_ERROR(
62  " CMKLMulticlass::CMKLMulticlass(const CMKLMulticlass & cm): must "
63  "not be called, glpk structure is currently not copyable");
64 }
65 
67 {
68  SG_ERROR(
69  " CMKLMulticlass CMKLMulticlass::operator=(...): must "
70  "not be called, glpk structure is currently not copyable");
71  return (*this);
72 }
73 
74 
76 {
77  if (!m_labels)
78  {
79  SG_ERROR("CMKLMulticlass::initsvm(): the set labels is NULL\n")
80  }
81 
82  SG_UNREF(svm);
83  svm=new CGMNPSVM;
84  SG_REF(svm);
85 
86  svm->set_C(get_C());
88 
89  if (m_labels->get_num_labels()<=0)
90  {
91  SG_ERROR("CMKLMulticlass::initsvm(): the number of labels is "
92  "nonpositive, do not know how to handle this!\n");
93  }
94 
96 }
97 
99 {
100  if (!m_kernel)
101  {
102  SG_ERROR("CMKLMulticlass::initlpsolver(): the set kernel is NULL\n")
103  }
104 
106  {
107  SG_ERROR("CMKLMulticlass::initlpsolver(): given kernel is not of type"
108  " K_COMBINED %d required by Multiclass Mkl \n",
110  }
111 
112  int numker=dynamic_cast<CCombinedKernel *>(m_kernel)->get_num_subkernels();
113 
114  ASSERT(numker>0)
115  /*
116  if (lpw)
117  {
118  delete lpw;
119  }
120  */
121 
122  //lpw=new MKLMulticlassGLPK;
123  if(pnorm>1)
124  {
127  }
128  else
129  {
131  }
132  lpw->setup(numker);
133 
134 }
135 
136 
138  numberofsilpiterations)
139 {
140  if ( (max_num_mkl_iters>0) && (numberofsilpiterations>=max_num_mkl_iters) )
141  return true;
142 
143  if (weightshistory.size()>1)
144  {
145  std::vector<float64_t> wold,wnew;
146 
147  wold=weightshistory[ weightshistory.size()-2 ];
148  wnew=weightshistory.back();
149  float64_t delta=0;
150 
151  ASSERT (wold.size()==wnew.size())
152 
153 
154  if((pnorm<=1)&&(!normweightssquared.empty()))
155  {
156  //check dual gap part for mkl
157 
159 
160  int32_t maxind=0;
161  float64_t maxval=normweightssquared[maxind];
162  for (size_t i=0;i< wnew.size();++i)
163  {
164  delta+=-0.5*oldnormweightssquared[i]*wold[i];
165  if(normweightssquared[i]>maxval)
166  {
167  maxind=i;
168  maxval=normweightssquared[i];
169  }
170  }
171  delta+=0.5*normweightssquared[maxind];
172  //delta=fabs(delta);
173  SG_SINFO("L1 Norm chosen, MKL part of duality gap %f \n",delta)
174  if( (delta < mkl_eps) && (numberofsilpiterations>=1) )
175  {
176  return true;
177  }
178 
179 
180 
181  }
182  else
183  {
184  delta=0;
185 
186  float64_t deltaold=oldalphaterm,deltanew=curalphaterm;
187  for (size_t i=0;i< wnew.size();++i)
188  {
189  delta+=(wold[i]-wnew[i])*(wold[i]-wnew[i]);
190  deltaold+= -0.5*oldnormweightssquared[i]*wold[i];
191  deltanew+= -0.5*normweightssquared[i]*wnew[i];
192  }
193  if(deltanew>0)
194  {
195  delta=1-deltanew/deltaold;
196  }
197  else
198  {
199  SG_SWARNING("CMKLMulticlass::evaluatefinishcriterion(...): deltanew<=0.Switching back to weight norsm difference as criterion.\n")
200  delta=sqrt(delta);
201  }
202  SG_SINFO("weight delta %f \n",delta)
203 
204  if( (delta < mkl_eps) && (numberofsilpiterations>=1) )
205  {
206  return true;
207  }
208 
209  }
210  }
211 
212  return false;
213 }
214 
215 void CMKLMulticlass::addingweightsstep( const std::vector<float64_t> &
216  curweights)
217 {
218 
219  if (weightshistory.size()>2)
220  {
221  weightshistory.erase(weightshistory.begin());
222  }
223 
224  //float64_t* weights(NULL);
225  //weights=new float64_t[curweights.size()];
226  SGVector<float64_t> weights(curweights.size());
227  std::copy(curweights.begin(),curweights.end(),weights.vector);
228 
230  //delete[] weights;
231  //weights=NULL;
232 
233  initsvm();
234 
236  svm->train();
237 
238  float64_t sumofsignfreealphas=getsumofsignfreealphas();
239  curalphaterm=sumofsignfreealphas;
240 
241  int32_t numkernels=
242  dynamic_cast<CCombinedKernel *>(m_kernel)->get_num_subkernels();
243 
244 
245  normweightssquared.resize(numkernels);
246  for (int32_t ind=0; ind < numkernels; ++ind )
247  {
249  }
250 
251  lpw->addconstraint(normweightssquared,sumofsignfreealphas);
252 }
253 
255 {
256 
257  std::vector<int> trainlabels2(m_labels->get_num_labels());
258  SGVector<int32_t> lab=((CMulticlassLabels*) m_labels)->get_int_labels();
259  std::copy(lab.vector,lab.vector+lab.vlen, trainlabels2.begin());
260 
261  ASSERT (trainlabels2.size()>0)
262  float64_t sum=0;
263 
264  for (int32_t nc=0; nc< ((CMulticlassLabels*) m_labels)->get_num_classes();++nc)
265  {
266  CSVM * sm=svm->get_svm(nc);
267 
268  float64_t bia=sm->get_bias();
269  sum+= 0.5*bia*bia;
270 
271  SG_UNREF(sm);
272  }
273 
274  index_t basealphas_y = 0, basealphas_x = 0;
275  float64_t* basealphas = svm->get_basealphas_ptr(&basealphas_y,
276  &basealphas_x);
277 
278  for (size_t lb=0; lb< trainlabels2.size();++lb)
279  {
280  for (int32_t nc=0; nc< ((CMulticlassLabels*) m_labels)->get_num_classes();++nc)
281  {
282  CSVM * sm=svm->get_svm(nc);
283 
284  if ((int)nc!=trainlabels2[lb])
285  {
286  CSVM * sm2=svm->get_svm(trainlabels2[lb]);
287 
288  float64_t bia1=sm2->get_bias();
289  float64_t bia2=sm->get_bias();
290  SG_UNREF(sm2);
291 
292  sum+= -basealphas[lb*basealphas_y + nc]*(bia1-bia2-1);
293  }
294  SG_UNREF(sm);
295  }
296  }
297 
298  return sum;
299 }
300 
302  const int32_t ind)
303 {
304  CKernel * ker=dynamic_cast<CCombinedKernel *>(m_kernel)->get_kernel(ind);
305 
306  float64_t tmp=0;
307 
308  for (int32_t classindex=0; classindex< ((CMulticlassLabels*) m_labels)->get_num_classes();
309  ++classindex)
310  {
311  CSVM * sm=svm->get_svm(classindex);
312 
313  for (int32_t i=0; i < sm->get_num_support_vectors(); ++i)
314  {
315  float64_t alphai=sm->get_alpha(i);
316  int32_t svindi= sm->get_support_vector(i);
317 
318  for (int32_t k=0; k < sm->get_num_support_vectors(); ++k)
319  {
320  float64_t alphak=sm->get_alpha(k);
321  int32_t svindk=sm->get_support_vector(k);
322 
323  tmp+=alphai*ker->kernel(svindi,svindk)
324  *alphak;
325 
326  }
327  }
328  SG_UNREF(sm);
329  }
330  SG_UNREF(ker);
331  ker=NULL;
332 
333  return tmp;
334 }
335 
336 
338 {
342 
343  int numcl=((CMulticlassLabels*) m_labels)->get_num_classes();
344 
345  if (data)
346  {
347  if (m_labels->get_num_labels() != data->get_num_vectors())
348  {
349  SG_ERROR("%s::train_machine(): Number of training vectors (%d) does"
350  " not match number of labels (%d)\n", get_name(),
352  }
353  m_kernel->init(data, data);
354  }
355 
356  initlpsolver();
357 
358  weightshistory.clear();
359 
360  int32_t numkernels=
361  dynamic_cast<CCombinedKernel *>(m_kernel)->get_num_subkernels();
362 
363  ::std::vector<float64_t> curweights(numkernels,1.0/numkernels);
364  weightshistory.push_back(curweights);
365 
366  addingweightsstep(curweights);
367 
370 
371  int32_t numberofsilpiterations=0;
372  bool final=false;
374 
375  while (!(CSignal::cancel_computations()) && !final)
376  {
377 
378  //curweights.clear();
379  lpw->computeweights(curweights);
380  weightshistory.push_back(curweights);
381 
382  addingweightsstep(curweights);
383 
384  //new weights new biasterm
385 
386  final=evaluatefinishcriterion(numberofsilpiterations);
387 
390 
391  ++numberofsilpiterations;
392 
393 
394  } // while(false==final)
395 
396 
397  //set alphas, bias, support vecs
398  ASSERT(numcl>=1)
399  create_multiclass_svm(numcl);
400 
401  for (int32_t i=0; i<numcl; i++)
402  {
403  CSVM* osvm=svm->get_svm(i);
404  CSVM* nsvm=new CSVM(osvm->get_num_support_vectors());
405 
406  for (int32_t k=0; k<osvm->get_num_support_vectors() ; k++)
407  {
408  nsvm->set_alpha(k, osvm->get_alpha(k) );
409  nsvm->set_support_vector(k,osvm->get_support_vector(k) );
410  }
411  nsvm->set_bias(osvm->get_bias() );
412  set_svm(i, nsvm);
413 
414  SG_UNREF(osvm);
415  osvm=NULL;
416  }
417 
418  SG_UNREF(svm);
419  svm=NULL;
420  if (lpw)
421  {
422  delete lpw;
423  }
424  lpw=NULL;
425  return true;
426 }
427 
428 
429 
430 
432 {
433  if ( weightshistory.empty() )
434  {
435  numweights=0;
436  return NULL;
437  }
438 
439  std::vector<float64_t> subkerw=weightshistory.back();
440  numweights=weightshistory.back().size();
441 
442  float64_t* res=new float64_t[numweights];
443  std::copy(weightshistory.back().begin(), weightshistory.back().end(),res);
444  return res;
445 }
446 
448 {
449  mkl_eps=eps;
450 }
451 
453 {
454  max_num_mkl_iters=maxnum;
455 }
456 
458 {
459  pnorm=norm;
460  if(pnorm<1 )
461  SG_ERROR("CMKLMulticlass::set_mkl_norm(float64_t norm) : parameter pnorm<1")
462 }
void set_epsilon(float64_t eps)
std::vector< float64_t > oldnormweightssquared
virtual bool init(CFeatures *lhs, CFeatures *rhs)
Definition: Kernel.cpp:96
virtual ELabelType get_label_type() const =0
MKLMulticlass is a class for L1-norm Multiclass MKL.
Definition: MKLMulticlass.h:40
int32_t index_t
Definition: common.h:72
The class Labels models labels, i.e. class assignments of objects.
Definition: Labels.h:43
virtual int32_t get_num_labels() const =0
multi-class labels 0,1,...
Definition: LabelTypes.h:20
MKLMulticlassGLPK is a helper class for MKLMulticlass.
#define SG_SWARNING(...)
Definition: SGIO.h:177
virtual int32_t get_num_vectors() const =0
float64_t * get_basealphas_ptr(index_t *y, index_t *x)
Definition: GMNPSVM.cpp:186
CLabels * m_labels
Definition: Machine.h:365
#define SG_ERROR(...)
Definition: SGIO.h:128
float64_t kernel(int32_t idx_a, int32_t idx_b)
void addingweightsstep(const std::vector< float64_t > &curweights)
#define SG_REF(x)
Definition: SGObject.h:52
virtual void set_mkl_norm(float64_t norm)
CMKLMulticlass operator=(const CMKLMulticlass &cm)
virtual bool evaluatefinishcriterion(const int32_t numberofsilpiterations)
Multiclass Labels for multi-class classification.
float64_t getsquarenormofprimalcoefficients(const int32_t ind)
#define ASSERT(x)
Definition: SGIO.h:200
class MultiClassSVM
Definition: MulticlassSVM.h:28
void set_bias(float64_t bias)
virtual void setup(const int32_t numkernels2)
static void clear_cancel()
Definition: Signal.cpp:126
virtual void addconstraint(const ::std::vector< float64_t > &normw2, const float64_t sumofpositivealphas)
double float64_t
Definition: common.h:60
::std::vector< std::vector< float64_t > > weightshistory
bool set_alpha(int32_t idx, float64_t val)
float64_t getsumofsignfreealphas()
void set_C(float64_t C)
float64_t get_alpha(int32_t idx)
float64_t * getsubkernelweights(int32_t &numweights)
The Combined kernel is used to combine a number of kernels into a single CombinedKernel object by lin...
bool set_support_vector(int32_t idx, int32_t val)
int32_t get_support_vector(int32_t idx)
static bool cancel_computations()
Definition: Signal.h:111
virtual void set_subkernel_weights(SGVector< float64_t > weights)
Definition: Kernel.cpp:863
#define SG_UNREF(x)
Definition: SGObject.h:53
MKLMulticlassOptimizationBase * lpw
all of classes and functions are contained in the shogun namespace
Definition: class_list.h:18
T sum(const Container< T > &a, bool no_diag=false)
virtual EKernelType get_kernel_type()=0
Class GMNPSVM implements a one vs. rest MultiClass SVM.
Definition: GMNPSVM.h:26
The class Features is the base class of all feature objects.
Definition: Features.h:68
bool create_multiclass_svm(int32_t num_classes)
#define SG_SINFO(...)
Definition: SGIO.h:172
virtual bool train(CFeatures *data=NULL)
Definition: Machine.cpp:39
std::vector< float64_t > normweightssquared
void set_mkl_epsilon(float64_t eps)
A generic Support Vector Machine Interface.
Definition: SVM.h:49
The Kernel base class.
multiclass one vs rest strategy used to train generic multiclass machines for K-class problems with b...
bool set_svm(int32_t num, CSVM *svm)
virtual bool train_machine(CFeatures *data=NULL)
virtual const char * get_name() const
virtual void set_labels(CLabels *lab)
CSVM * get_svm(int32_t num)
Definition: MulticlassSVM.h:76
virtual void computeweights(std::vector< float64_t > &weights2)
void set_max_num_mkliters(int32_t maxnum)
MKLMulticlassGradient is a helper class for MKLMulticlass.

SHOGUN Machine Learning Toolbox - Documentation