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

SHOGUN Machine Learning Toolbox - Documentation