SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 using namespace shogun;
20 
21 
24 {
25  svm=NULL;
26  lpw=NULL;
27 
28  mkl_eps=0.01;
30  pnorm=1;
31 }
32 
35 {
36  svm=NULL;
37  lpw=NULL;
38 
39  mkl_eps=0.01;
41  pnorm=1;
42 }
43 
44 
46 {
47  SG_UNREF(svm);
48  svm=NULL;
49  delete lpw;
50  lpw=NULL;
51 }
52 
55 {
56  svm=NULL;
57  lpw=NULL;
58  SG_ERROR(
59  " CMKLMulticlass::CMKLMulticlass(const CMKLMulticlass & cm): must "
60  "not be called, glpk structure is currently not copyable");
61 }
62 
64 {
65  SG_ERROR(
66  " CMKLMulticlass CMKLMulticlass::operator=(...): must "
67  "not be called, glpk structure is currently not copyable");
68  return (*this);
69 }
70 
71 
73 {
74  if (!m_labels)
75  {
76  SG_ERROR("CMKLMulticlass::initsvm(): the set labels is NULL\n")
77  }
78 
79  SG_UNREF(svm);
80  svm=new CGMNPSVM;
81  SG_REF(svm);
82 
83  svm->set_C(get_C());
85 
86  if (m_labels->get_num_labels()<=0)
87  {
88  SG_ERROR("CMKLMulticlass::initsvm(): the number of labels is "
89  "nonpositive, do not know how to handle this!\n");
90  }
91 
93 }
94 
96 {
97  if (!m_kernel)
98  {
99  SG_ERROR("CMKLMulticlass::initlpsolver(): the set kernel is NULL\n")
100  }
101 
103  {
104  SG_ERROR("CMKLMulticlass::initlpsolver(): given kernel is not of type"
105  " K_COMBINED %d required by Multiclass Mkl \n",
107  }
108 
109  int numker=dynamic_cast<CCombinedKernel *>(m_kernel)->get_num_subkernels();
110 
111  ASSERT(numker>0)
112  /*
113  if (lpw)
114  {
115  delete lpw;
116  }
117  */
118 
119  //lpw=new MKLMulticlassGLPK;
120  if(pnorm>1)
121  {
124  }
125  else
126  {
128  }
129  lpw->setup(numker);
130 
131 }
132 
133 
135  numberofsilpiterations)
136 {
137  if ( (max_num_mkl_iters>0) && (numberofsilpiterations>=max_num_mkl_iters) )
138  return true;
139 
140  if (weightshistory.size()>1)
141  {
142  std::vector<float64_t> wold,wnew;
143 
144  wold=weightshistory[ weightshistory.size()-2 ];
145  wnew=weightshistory.back();
146  float64_t delta=0;
147 
148  ASSERT (wold.size()==wnew.size())
149 
150 
151  if((pnorm<=1)&&(!normweightssquared.empty()))
152  {
153  //check dual gap part for mkl
154 
156 
157  int32_t maxind=0;
158  float64_t maxval=normweightssquared[maxind];
159  for (size_t i=0;i< wnew.size();++i)
160  {
161  delta+=-0.5*oldnormweightssquared[i]*wold[i];
162  if(normweightssquared[i]>maxval)
163  {
164  maxind=i;
165  maxval=normweightssquared[i];
166  }
167  }
168  delta+=0.5*normweightssquared[maxind];
169  //delta=fabs(delta);
170  SG_SINFO("L1 Norm chosen, MKL part of duality gap %f \n",delta)
171  if( (delta < mkl_eps) && (numberofsilpiterations>=1) )
172  {
173  return true;
174  }
175 
176 
177 
178  }
179  else
180  {
181  delta=0;
182 
183  float64_t deltaold=oldalphaterm,deltanew=curalphaterm;
184  for (size_t i=0;i< wnew.size();++i)
185  {
186  delta+=(wold[i]-wnew[i])*(wold[i]-wnew[i]);
187  deltaold+= -0.5*oldnormweightssquared[i]*wold[i];
188  deltanew+= -0.5*normweightssquared[i]*wnew[i];
189  }
190  if(deltanew>0)
191  {
192  delta=1-deltanew/deltaold;
193  }
194  else
195  {
196  SG_SWARNING("CMKLMulticlass::evaluatefinishcriterion(...): deltanew<=0.Switching back to weight norsm difference as criterion.\n")
197  delta=sqrt(delta);
198  }
199  SG_SINFO("weight delta %f \n",delta)
200 
201  if( (delta < mkl_eps) && (numberofsilpiterations>=1) )
202  {
203  return true;
204  }
205 
206  }
207  }
208 
209  return false;
210 }
211 
212 void CMKLMulticlass::addingweightsstep( const std::vector<float64_t> &
213  curweights)
214 {
215 
216  if (weightshistory.size()>2)
217  {
218  weightshistory.erase(weightshistory.begin());
219  }
220 
221  //float64_t* weights(NULL);
222  //weights=new float64_t[curweights.size()];
223  SGVector<float64_t> weights(curweights.size());
224  std::copy(curweights.begin(),curweights.end(),weights.vector);
225 
227  //delete[] weights;
228  //weights=NULL;
229 
230  initsvm();
231 
233  svm->train();
234 
235  float64_t sumofsignfreealphas=getsumofsignfreealphas();
236  curalphaterm=sumofsignfreealphas;
237 
238  int32_t numkernels=
239  dynamic_cast<CCombinedKernel *>(m_kernel)->get_num_subkernels();
240 
241 
242  normweightssquared.resize(numkernels);
243  for (int32_t ind=0; ind < numkernels; ++ind )
244  {
246  }
247 
248  lpw->addconstraint(normweightssquared,sumofsignfreealphas);
249 }
250 
252 {
253 
254  std::vector<int> trainlabels2(m_labels->get_num_labels());
255  SGVector<int32_t> lab=((CMulticlassLabels*) m_labels)->get_int_labels();
256  std::copy(lab.vector,lab.vector+lab.vlen, trainlabels2.begin());
257 
258  ASSERT (trainlabels2.size()>0)
259  float64_t sum=0;
260 
261  for (int32_t nc=0; nc< ((CMulticlassLabels*) m_labels)->get_num_classes();++nc)
262  {
263  CSVM * sm=svm->get_svm(nc);
264 
265  float64_t bia=sm->get_bias();
266  sum+= 0.5*bia*bia;
267 
268  SG_UNREF(sm);
269  }
270 
271  index_t basealphas_y = 0, basealphas_x = 0;
272  float64_t* basealphas = svm->get_basealphas_ptr(&basealphas_y,
273  &basealphas_x);
274 
275  for (size_t lb=0; lb< trainlabels2.size();++lb)
276  {
277  for (int32_t nc=0; nc< ((CMulticlassLabels*) m_labels)->get_num_classes();++nc)
278  {
279  CSVM * sm=svm->get_svm(nc);
280 
281  if ((int)nc!=trainlabels2[lb])
282  {
283  CSVM * sm2=svm->get_svm(trainlabels2[lb]);
284 
285  float64_t bia1=sm2->get_bias();
286  float64_t bia2=sm->get_bias();
287  SG_UNREF(sm2);
288 
289  sum+= -basealphas[lb*basealphas_y + nc]*(bia1-bia2-1);
290  }
291  SG_UNREF(sm);
292  }
293  }
294 
295  return sum;
296 }
297 
299  const int32_t ind)
300 {
301  CKernel * ker=dynamic_cast<CCombinedKernel *>(m_kernel)->get_kernel(ind);
302 
303  float64_t tmp=0;
304 
305  for (int32_t classindex=0; classindex< ((CMulticlassLabels*) m_labels)->get_num_classes();
306  ++classindex)
307  {
308  CSVM * sm=svm->get_svm(classindex);
309 
310  for (int32_t i=0; i < sm->get_num_support_vectors(); ++i)
311  {
312  float64_t alphai=sm->get_alpha(i);
313  int32_t svindi= sm->get_support_vector(i);
314 
315  for (int32_t k=0; k < sm->get_num_support_vectors(); ++k)
316  {
317  float64_t alphak=sm->get_alpha(k);
318  int32_t svindk=sm->get_support_vector(k);
319 
320  tmp+=alphai*ker->kernel(svindi,svindk)
321  *alphak;
322 
323  }
324  }
325  SG_UNREF(sm);
326  }
327  SG_UNREF(ker);
328  ker=NULL;
329 
330  return tmp;
331 }
332 
333 
335 {
339 
340  int numcl=((CMulticlassLabels*) m_labels)->get_num_classes();
341 
342  if (data)
343  {
344  if (m_labels->get_num_labels() != data->get_num_vectors())
345  {
346  SG_ERROR("%s::train_machine(): Number of training vectors (%d) does"
347  " not match number of labels (%d)\n", get_name(),
349  }
350  m_kernel->init(data, data);
351  }
352 
353  initlpsolver();
354 
355  weightshistory.clear();
356 
357  int32_t numkernels=
358  dynamic_cast<CCombinedKernel *>(m_kernel)->get_num_subkernels();
359 
360  ::std::vector<float64_t> curweights(numkernels,1.0/numkernels);
361  weightshistory.push_back(curweights);
362 
363  addingweightsstep(curweights);
364 
367 
368  int32_t numberofsilpiterations=0;
369  bool final=false;
370  while (!final)
371  {
372 
373  //curweights.clear();
374  lpw->computeweights(curweights);
375  weightshistory.push_back(curweights);
376 
377  addingweightsstep(curweights);
378 
379  //new weights new biasterm
380 
381  final=evaluatefinishcriterion(numberofsilpiterations);
382 
385 
386  ++numberofsilpiterations;
387 
388 
389  } // while(false==final)
390 
391 
392  //set alphas, bias, support vecs
393  ASSERT(numcl>=1)
394  create_multiclass_svm(numcl);
395 
396  for (int32_t i=0; i<numcl; i++)
397  {
398  CSVM* osvm=svm->get_svm(i);
399  CSVM* nsvm=new CSVM(osvm->get_num_support_vectors());
400 
401  for (int32_t k=0; k<osvm->get_num_support_vectors() ; k++)
402  {
403  nsvm->set_alpha(k, osvm->get_alpha(k) );
404  nsvm->set_support_vector(k,osvm->get_support_vector(k) );
405  }
406  nsvm->set_bias(osvm->get_bias() );
407  set_svm(i, nsvm);
408 
409  SG_UNREF(osvm);
410  osvm=NULL;
411  }
412 
413  SG_UNREF(svm);
414  svm=NULL;
415  if (lpw)
416  {
417  delete lpw;
418  }
419  lpw=NULL;
420  return true;
421 }
422 
423 
424 
425 
427 {
428  if ( weightshistory.empty() )
429  {
430  numweights=0;
431  return NULL;
432  }
433 
434  std::vector<float64_t> subkerw=weightshistory.back();
435  numweights=weightshistory.back().size();
436 
437  float64_t* res=new float64_t[numweights];
438  std::copy(weightshistory.back().begin(), weightshistory.back().end(),res);
439  return res;
440 }
441 
443 {
444  mkl_eps=eps;
445 }
446 
448 {
449  max_num_mkl_iters=maxnum;
450 }
451 
453 {
454  pnorm=norm;
455  if(pnorm<1 )
456  SG_ERROR("CMKLMulticlass::set_mkl_norm(float64_t norm) : parameter pnorm<1")
457 }

SHOGUN Machine Learning Toolbox - Documentation