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

SHOGUN Machine Learning Toolbox - Documentation