SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SVMLight.cpp
Go to the documentation of this file.
1 /***********************************************************************/
2 /* */
3 /* SVMLight.cpp */
4 /* */
5 /* Author: Thorsten Joachims */
6 /* Date: 19.07.99 */
7 /* */
8 /* Copyright (c) 1999 Universitaet Dortmund - All rights reserved */
9 /* */
10 /* This software is available for non-commercial use only. It must */
11 /* not be modified and distributed without prior permission of the */
12 /* author. The author is not responsible for implications from the */
13 /* use of this software. */
14 /* */
15 /* THIS INCLUDES THE FOLLOWING ADDITIONS */
16 /* Generic Kernel Interfacing: Soeren Sonnenburg */
17 /* Parallizations: Soeren Sonnenburg */
18 /* Multiple Kernel Learning: Gunnar Raetsch, Soeren Sonnenburg, */
19 /* Alexander Zien, Marius Kloft, Chen Guohua */
20 /* Linadd Speedup: Gunnar Raetsch, Soeren Sonnenburg */
21 /* */
22 /***********************************************************************/
23 #include <shogun/lib/config.h>
24 
25 #ifdef USE_SVMLIGHT
26 
27 #include <shogun/io/SGIO.h>
28 #include <shogun/lib/Signal.h>
30 #include <shogun/lib/Time.h>
32 
35 
36 #include <shogun/kernel/Kernel.h>
39 
40 #include <unistd.h>
41 
42 #include <shogun/base/Parallel.h>
44 
45 #ifdef HAVE_PTHREAD
46 #include <pthread.h>
47 #endif
48 
49 using namespace shogun;
50 
51 #ifndef DOXYGEN_SHOULD_SKIP_THIS
52 struct S_THREAD_PARAM_REACTIVATE_LINADD
53 {
54  CKernel* kernel;
55  float64_t* lin;
56  float64_t* last_lin;
57  int32_t* active;
58  int32_t* docs;
59  int32_t start;
60  int32_t end;
61 };
62 
63 struct S_THREAD_PARAM
64 {
65  float64_t * lin ;
66  float64_t* W;
67  int32_t start, end;
68  int32_t * active2dnum ;
69  int32_t * docs ;
70  CKernel* kernel ;
71 };
72 
73 struct S_THREAD_PARAM_REACTIVATE_VANILLA
74 {
75  CKernel* kernel;
76  float64_t* lin;
77  float64_t* aicache;
78  float64_t* a;
79  float64_t* a_old;
80  int32_t* changed2dnum;
81  int32_t* inactive2dnum;
82  int32_t* label;
83  int32_t start;
84  int32_t end;
85 };
86 
87 struct S_THREAD_PARAM_KERNEL
88 {
89  float64_t *Kval ;
90  int32_t *KI, *KJ ;
91  int32_t start, end;
92  CSVMLight* svmlight;
93 };
94 
95 #endif // DOXYGEN_SHOULD_SKIP_THIS
96 
98 {
99  S_THREAD_PARAM* params = (S_THREAD_PARAM*) p;
100 
101  int32_t jj=0, j=0 ;
102 
103  for (jj=params->start;(jj<params->end) && (j=params->active2dnum[jj])>=0;jj++)
104  params->lin[j]+=params->kernel->compute_optimized(params->docs[j]);
105 
106  return NULL ;
107 }
108 
110 {
111  S_THREAD_PARAM_KERNEL* params = (S_THREAD_PARAM_KERNEL*) p;
112 
113  int32_t jj=0 ;
114  for (jj=params->start;jj<params->end;jj++)
115  params->Kval[jj]=params->svmlight->compute_kernel(params->KI[jj], params->KJ[jj]) ;
116 
117  return NULL ;
118 }
119 
121 : CSVM()
122 {
123  init();
124  set_kernel(NULL);
125 }
126 
128 : CSVM(C, k, lab)
129 {
130  init();
131 }
132 
134 {
135  //optimizer settings
136  primal=NULL;
137  dual=NULL;
138  init_margin=0.15;
139  init_iter=500;
141  model_b=0;
142  verbosity=1;
144 
145  // svm variables
146  W=NULL;
147  model=SG_MALLOC(MODEL, 1);
148  learn_parm=SG_MALLOC(LEARN_PARM, 1);
149  model->supvec=NULL;
150  model->alpha=NULL;
151  model->index=NULL;
152 
153  // MKL stuff
154  mymaxdiff=1 ;
155  mkl_converged=false;
156 }
157 
159 {
160 
161  SG_FREE(model->supvec);
162  SG_FREE(model->alpha);
163  SG_FREE(model->index);
164  SG_FREE(model);
166 
167  // MKL stuff
168  SG_FREE(W);
169 
170  // optimizer variables
171  SG_FREE(dual);
172  SG_FREE(primal);
173 }
174 
176 {
177  //certain setup params
178  mkl_converged=false;
179  verbosity=1 ;
180  init_margin=0.15;
181  init_iter=500;
184 
185  strcpy (learn_parm->predfile, "");
186  learn_parm->biased_hyperplane= get_bias_enabled() ? 1 : 0;
187  learn_parm->sharedslack=0;
188  learn_parm->remove_inconsistent=0;
189  learn_parm->skip_final_opt_check=0;
190  learn_parm->svm_maxqpsize=get_qpsize();
191  learn_parm->svm_newvarsinqp=learn_parm->svm_maxqpsize-1;
192  learn_parm->maxiter=100000;
193  learn_parm->svm_iter_to_shrink=100;
194  learn_parm->svm_c=C1;
195  learn_parm->transduction_posratio=0.33;
196  learn_parm->svm_costratio=C2/C1;
197  learn_parm->svm_costratio_unlab=1.0;
198  learn_parm->svm_unlabbound=1E-5;
199  learn_parm->epsilon_crit=epsilon; // GU: better decrease it ... ??
200  learn_parm->epsilon_a=1E-15;
201  learn_parm->compute_loo=0;
202  learn_parm->rho=1.0;
203  learn_parm->xa_depth=0;
204 
205  if (!kernel)
206  SG_ERROR( "SVM_light can not proceed without kernel!\n");
207 
208  if (data)
209  {
210  if (m_labels->get_num_labels() != data->get_num_vectors())
211  {
212  SG_ERROR("%s::train_machine(): Number of training vectors (%d) does"
213  " not match number of labels (%d)\n", get_name(),
215  }
216  kernel->init(data, data);
217  }
218 
219  if (!kernel->has_features())
220  SG_ERROR( "SVM_light can not proceed without initialized kernel!\n");
221 
225 
226  // in case of LINADD enabled kernels cleanup!
228  kernel->clear_normal() ;
229 
230  // output some info
231  SG_DEBUG( "threads = %i\n", parallel->get_num_threads()) ;
232  SG_DEBUG( "qpsize = %i\n", learn_parm->svm_maxqpsize) ;
233  SG_DEBUG( "epsilon = %1.1e\n", learn_parm->epsilon_crit) ;
234  SG_DEBUG( "kernel->has_property(KP_LINADD) = %i\n", kernel->has_property(KP_LINADD)) ;
235  SG_DEBUG( "kernel->has_property(KP_KERNCOMBINATION) = %i\n", kernel->has_property(KP_KERNCOMBINATION)) ;
236  SG_DEBUG( "kernel->has_property(KP_BATCHEVALUATION) = %i\n", kernel->has_property(KP_BATCHEVALUATION)) ;
237  SG_DEBUG( "kernel->get_optimization_type() = %s\n", kernel->get_optimization_type()==FASTBUTMEMHUNGRY ? "FASTBUTMEMHUNGRY" : "SLOWBUTMEMEFFICIENT" ) ;
238  SG_DEBUG( "get_solver_type() = %i\n", get_solver_type());
239  SG_DEBUG( "get_linadd_enabled() = %i\n", get_linadd_enabled()) ;
240  SG_DEBUG( "get_batch_computation_enabled() = %i\n", get_batch_computation_enabled()) ;
241  SG_DEBUG( "kernel->get_num_subkernels() = %i\n", kernel->get_num_subkernels()) ;
242 
245 
246  SG_DEBUG( "use_kernel_cache = %i\n", use_kernel_cache) ;
247 
249  {
250  CKernel* kn = ((CCombinedKernel*)kernel)->get_first_kernel();
251 
252  while (kn)
253  {
254  // allocate kernel cache but clean up beforehand
256  SG_UNREF(kn);
257  kn = ((CCombinedKernel*) kernel)->get_next_kernel();
258  }
259  }
260 
262 
263  // train the svm
264  svm_learn();
265 
266  // brain damaged svm light work around
267  create_new_model(model->sv_num-1);
268  set_bias(-model->b);
269  for (int32_t i=0; i<model->sv_num-1; i++)
270  {
271  set_alpha(i, model->alpha[i+1]);
272  set_support_vector(i, model->supvec[i+1]);
273  }
274 
275  // in case of LINADD enabled kernels cleanup!
277  {
278  kernel->clear_normal() ;
280  }
281 
282  if (use_kernel_cache)
284 
285  return true ;
286 }
287 
289 {
290  clock_t start;
291  start = clock();
292  return((int32_t)((float64_t)start*100.0/(float64_t)CLOCKS_PER_SEC));
293 }
294 
295 
297 {
298  int32_t *inconsistent, i;
299  int32_t misclassified,upsupvecnum;
300  float64_t maxdiff, *lin, *c, *a;
301  int32_t iterations;
302  int32_t trainpos=0, trainneg=0 ;
303  ASSERT(m_labels);
304  SGVector<int32_t> lab=((CBinaryLabels*) m_labels)->get_int_labels();
305  int32_t totdoc=lab.vlen;
306  ASSERT(lab.vector && lab.vlen);
307  int32_t* label=SGVector<int32_t>::clone_vector(lab.vector, lab.vlen);
308 
309  int32_t* docs=SG_MALLOC(int32_t, totdoc);
310  SG_FREE(W);
311  W=NULL;
312  count = 0 ;
313 
315  {
317  for (i=0; i<totdoc*kernel->get_num_subkernels(); i++)
318  W[i]=0;
319  }
320 
321  for (i=0; i<totdoc; i++)
322  docs[i]=i;
323 
324  float64_t *xi_fullset; /* buffer for storing xi on full sample in loo */
325  float64_t *a_fullset; /* buffer for storing alpha on full sample in loo */
326  TIMING timing_profile;
327  SHRINK_STATE shrink_state;
328 
329  timing_profile.time_kernel=0;
330  timing_profile.time_opti=0;
331  timing_profile.time_shrink=0;
332  timing_profile.time_update=0;
333  timing_profile.time_model=0;
334  timing_profile.time_check=0;
335  timing_profile.time_select=0;
336 
337  /* make sure -n value is reasonable */
338  if((learn_parm->svm_newvarsinqp < 2)
339  || (learn_parm->svm_newvarsinqp > learn_parm->svm_maxqpsize)) {
340  learn_parm->svm_newvarsinqp=learn_parm->svm_maxqpsize;
341  }
342 
343  init_shrink_state(&shrink_state,totdoc,(int32_t)MAXSHRINK);
344 
345  inconsistent = SG_MALLOC(int32_t, totdoc);
346  c = SG_MALLOC(float64_t, totdoc);
347  a = SG_MALLOC(float64_t, totdoc);
348  a_fullset = SG_MALLOC(float64_t, totdoc);
349  xi_fullset = SG_MALLOC(float64_t, totdoc);
350  lin = SG_MALLOC(float64_t, totdoc);
351  if (m_linear_term.vlen>0)
353  else
354  {
355  learn_parm->eps=SG_MALLOC(float64_t, totdoc); /* equivalent regression epsilon for classification */
356  SGVector<float64_t>::fill_vector(learn_parm->eps, totdoc, -1.0);
357  }
358 
359  learn_parm->svm_cost = SG_MALLOC(float64_t, totdoc);
360 
361  SG_FREE(model->supvec);
362  SG_FREE(model->alpha);
363  SG_FREE(model->index);
364  model->supvec = SG_MALLOC(int32_t, totdoc+2);
365  model->alpha = SG_MALLOC(float64_t, totdoc+2);
366  model->index = SG_MALLOC(int32_t, totdoc+2);
367 
368  model->at_upper_bound=0;
369  model->b=0;
370  model->supvec[0]=0; /* element 0 reserved and empty for now */
371  model->alpha[0]=0;
372  model->totdoc=totdoc;
373 
374  model->kernel=kernel;
375 
376  model->sv_num=1;
377  model->loo_error=-1;
378  model->loo_recall=-1;
379  model->loo_precision=-1;
380  model->xa_error=-1;
381  model->xa_recall=-1;
382  model->xa_precision=-1;
383 
384  for (i=0;i<totdoc;i++) { /* various inits */
385  inconsistent[i]=0;
386  c[i]=0;
387  a[i]=0;
388  lin[i]=0;
389 
390  if(label[i] > 0) {
391  learn_parm->svm_cost[i]=learn_parm->svm_c*learn_parm->svm_costratio*
392  fabs((float64_t)label[i]);
393  label[i]=1;
394  trainpos++;
395  }
396  else if(label[i] < 0) {
397  learn_parm->svm_cost[i]=learn_parm->svm_c*fabs((float64_t)label[i]);
398  label[i]=-1;
399  trainneg++;
400  }
401  else {
402  learn_parm->svm_cost[i]=0;
403  }
404  }
405 
406  /* compute starting state for initial alpha values */
407  SG_DEBUG( "alpha:%d num_sv:%d\n", m_alpha.vector, get_num_support_vectors());
408 
410  if(verbosity>=1) {
411  SG_INFO( "Computing starting state...");
412  }
413 
414  float64_t* alpha = SG_MALLOC(float64_t, totdoc);
415 
416  for (i=0; i<totdoc; i++)
417  alpha[i]=0;
418 
419  for (i=0; i<get_num_support_vectors(); i++)
420  alpha[get_support_vector(i)]=get_alpha(i);
421 
422  int32_t* index = SG_MALLOC(int32_t, totdoc);
423  int32_t* index2dnum = SG_MALLOC(int32_t, totdoc+11);
424  float64_t* aicache = SG_MALLOC(float64_t, totdoc);
425  for (i=0;i<totdoc;i++) { /* create full index and clip alphas */
426  index[i]=1;
427  alpha[i]=fabs(alpha[i]);
428  if(alpha[i]<0) alpha[i]=0;
429  if(alpha[i]>learn_parm->svm_cost[i]) alpha[i]=learn_parm->svm_cost[i];
430  }
431 
432  if (use_kernel_cache)
433  {
434  if (callback &&
435  (!((CCombinedKernel*)kernel)->get_append_subkernel_weights())
436  )
437  {
439  CKernel* kn = k->get_first_kernel();
440 
441  while (kn)
442  {
443  for (i=0;i<totdoc;i++) // fill kernel cache with unbounded SV
444  if((alpha[i]>0) && (alpha[i]<learn_parm->svm_cost[i])
445  && (kn->kernel_cache_space_available()))
446  kn->cache_kernel_row(i);
447 
448  for (i=0;i<totdoc;i++) // fill rest of kernel cache with bounded SV
449  if((alpha[i]==learn_parm->svm_cost[i])
450  && (kn->kernel_cache_space_available()))
451  kn->cache_kernel_row(i);
452 
453  SG_UNREF(kn);
454  kn = k->get_next_kernel();
455  }
456  }
457  else
458  {
459  for (i=0;i<totdoc;i++) /* fill kernel cache with unbounded SV */
460  if((alpha[i]>0) && (alpha[i]<learn_parm->svm_cost[i])
463 
464  for (i=0;i<totdoc;i++) /* fill rest of kernel cache with bounded SV */
465  if((alpha[i]==learn_parm->svm_cost[i])
468  }
469  }
470  compute_index(index,totdoc,index2dnum);
471  update_linear_component(docs,label,index2dnum,alpha,a,index2dnum,totdoc,
472  lin,aicache,NULL);
473  calculate_svm_model(docs,label,lin,alpha,a,c,
474  index2dnum,index2dnum);
475  for (i=0;i<totdoc;i++) { /* copy initial alphas */
476  a[i]=alpha[i];
477  }
478 
479  SG_FREE(index);
480  SG_FREE(index2dnum);
481  SG_FREE(aicache);
482  SG_FREE(alpha);
483 
484  if(verbosity>=1)
485  SG_DONE();
486  }
487  SG_DEBUG( "%d totdoc %d pos %d neg\n", totdoc, trainpos, trainneg);
488  SG_DEBUG( "Optimizing...\n");
489 
490  /* train the svm */
491  iterations=optimize_to_convergence(docs,label,totdoc,
492  &shrink_state,inconsistent,a,lin,
493  c,&timing_profile,
494  &maxdiff,(int32_t)-1,
495  (int32_t)1);
496 
497 
498  if(verbosity>=1) {
499  if(verbosity==1)
500  {
501  SG_DONE();
502  SG_DEBUG("(%ld iterations)", iterations);
503  }
504 
505  misclassified=0;
506  for (i=0;(i<totdoc);i++) { /* get final statistic */
507  if((lin[i]-model->b)*(float64_t)label[i] <= 0.0)
508  misclassified++;
509  }
510 
511  SG_INFO( "Optimization finished (%ld misclassified, maxdiff=%.8f).\n",
512  misclassified,maxdiff);
513 
514  SG_INFO( "obj = %.16f, rho = %.16f\n",get_objective(),model->b);
515  if (maxdiff>epsilon)
516  SG_WARNING( "maximum violation (%f) exceeds svm_epsilon (%f) due to numerical difficulties\n", maxdiff, epsilon);
517 
518  upsupvecnum=0;
519  for (i=1;i<model->sv_num;i++)
520  {
521  if(fabs(model->alpha[i]) >=
522  (learn_parm->svm_cost[model->supvec[i]]-
523  learn_parm->epsilon_a))
524  upsupvecnum++;
525  }
526  SG_INFO( "Number of SV: %ld (including %ld at upper bound)\n",
527  model->sv_num-1,upsupvecnum);
528  }
529 
530  shrink_state_cleanup(&shrink_state);
531  SG_FREE(label);
532  SG_FREE(inconsistent);
533  SG_FREE(c);
534  SG_FREE(a);
535  SG_FREE(a_fullset);
536  SG_FREE(xi_fullset);
537  SG_FREE(lin);
538  SG_FREE(learn_parm->eps);
539  SG_FREE(learn_parm->svm_cost);
540  SG_FREE(docs);
541 }
542 
543 int32_t CSVMLight::optimize_to_convergence(int32_t* docs, int32_t* label, int32_t totdoc,
544  SHRINK_STATE *shrink_state,
545  int32_t *inconsistent,
546  float64_t *a, float64_t *lin, float64_t *c,
547  TIMING *timing_profile, float64_t *maxdiff,
548  int32_t heldout, int32_t retrain)
549  /* docs: Training vectors (x-part) */
550  /* label: Training labels/value (y-part, zero if test example for
551  transduction) */
552  /* totdoc: Number of examples in docs/label */
553  /* laern_parm: Learning paramenters */
554  /* kernel_parm: Kernel paramenters */
555  /* kernel_cache: Initialized/partly filled Cache, if using a kernel.
556  NULL if linear. */
557  /* shrink_state: State of active variables */
558  /* inconsistent: examples thrown out as inconstistent */
559  /* a: alphas */
560  /* lin: linear component of gradient */
561  /* c: right hand side of inequalities (margin) */
562  /* maxdiff: returns maximum violation of KT-conditions */
563  /* heldout: marks held-out example for leave-one-out (or -1) */
564  /* retrain: selects training mode (1=regular / 2=holdout) */
565 {
566 
567  int32_t *chosen,*key,i,j,jj,*last_suboptimal_at,noshrink;
568  int32_t inconsistentnum,choosenum,already_chosen=0,iteration;
569  int32_t misclassified,supvecnum=0,*active2dnum,inactivenum;
570  int32_t *working2dnum,*selexam;
571  int32_t activenum;
572  float64_t criterion, eq;
573  float64_t *a_old;
574  int32_t t0=0,t1=0,t2=0,t3=0,t4=0,t5=0,t6=0; /* timing */
575  float64_t epsilon_crit_org;
576  float64_t bestmaxdiff;
577  float64_t worstmaxdiff;
578  int32_t bestmaxdiffiter,terminate;
579  bool reactivated=false;
580 
581  float64_t *selcrit; /* buffer for sorting */
582  float64_t *aicache; /* buffer to keep one row of hessian */
583  QP qp; /* buffer for one quadratic program */
584 
585  epsilon_crit_org=learn_parm->epsilon_crit; /* save org */
587  learn_parm->epsilon_crit=2.0;
588  /* caching makes no sense for linear kernel */
589  }
590  learn_parm->epsilon_shrink=2;
591  (*maxdiff)=1;
592 
593  SG_DEBUG("totdoc:%d\n",totdoc);
594  chosen = SG_MALLOC(int32_t, totdoc);
595  last_suboptimal_at =SG_MALLOC(int32_t, totdoc);
596  key =SG_MALLOC(int32_t, totdoc+11);
597  selcrit =SG_MALLOC(float64_t, totdoc);
598  selexam =SG_MALLOC(int32_t, totdoc);
599  a_old =SG_MALLOC(float64_t, totdoc);
600  aicache =SG_MALLOC(float64_t, totdoc);
601  working2dnum =SG_MALLOC(int32_t, totdoc+11);
602  active2dnum =SG_MALLOC(int32_t, totdoc+11);
603  qp.opt_ce =SG_MALLOC(float64_t, learn_parm->svm_maxqpsize);
604  qp.opt_ce0 =SG_MALLOC(float64_t, 1);
605  qp.opt_g =SG_MALLOC(float64_t, learn_parm->svm_maxqpsize*learn_parm->svm_maxqpsize);
606  qp.opt_g0 =SG_MALLOC(float64_t, learn_parm->svm_maxqpsize);
607  qp.opt_xinit =SG_MALLOC(float64_t, learn_parm->svm_maxqpsize);
608  qp.opt_low=SG_MALLOC(float64_t, learn_parm->svm_maxqpsize);
609  qp.opt_up=SG_MALLOC(float64_t, learn_parm->svm_maxqpsize);
610 
611  choosenum=0;
612  inconsistentnum=0;
613  if(!retrain) retrain=1;
614  iteration=1;
615  bestmaxdiffiter=1;
616  bestmaxdiff=999999999;
617  worstmaxdiff=1e-10;
618  terminate=0;
619 
620 
621  kernel->set_time(iteration); /* for lru cache */
622 
623  for (i=0;i<totdoc;i++) { /* various inits */
624  chosen[i]=0;
625  a_old[i]=a[i];
626  last_suboptimal_at[i]=1;
627  if(inconsistent[i])
628  inconsistentnum++;
629  }
630  activenum=compute_index(shrink_state->active,totdoc,active2dnum);
631  inactivenum=totdoc-activenum;
632  clear_index(working2dnum);
633 
634  /* repeat this loop until we have convergence */
635  CTime start_time;
636  mkl_converged=false;
637 
638 
639 #ifdef CYGWIN
640  for (;((iteration<100 || (!mkl_converged && callback) ) || (retrain && (!terminate))); iteration++){
641 #else
643  for (;((!CSignal::cancel_computations()) && ((iteration<3 || (!mkl_converged && callback) ) || (retrain && (!terminate)))); iteration++){
644 #endif
645 
646  if(use_kernel_cache)
647  kernel->set_time(iteration); /* for lru cache */
648 
649  if(verbosity>=2) t0=get_runtime();
650  if(verbosity>=3) {
651  SG_DEBUG( "\nSelecting working set... ");
652  }
653 
654  if(learn_parm->svm_newvarsinqp>learn_parm->svm_maxqpsize)
655  learn_parm->svm_newvarsinqp=learn_parm->svm_maxqpsize;
656 
657  i=0;
658  for (jj=0;(j=working2dnum[jj])>=0;jj++) { /* clear working set */
659  if((chosen[j]>=(learn_parm->svm_maxqpsize/
660  CMath::min(learn_parm->svm_maxqpsize,
661  learn_parm->svm_newvarsinqp)))
662  || (inconsistent[j])
663  || (j == heldout)) {
664  chosen[j]=0;
665  choosenum--;
666  }
667  else {
668  chosen[j]++;
669  working2dnum[i++]=j;
670  }
671  }
672  working2dnum[i]=-1;
673 
674  if(retrain == 2) {
675  choosenum=0;
676  for (jj=0;(j=working2dnum[jj])>=0;jj++) { /* fully clear working set */
677  chosen[j]=0;
678  }
679  clear_index(working2dnum);
680  for (i=0;i<totdoc;i++) { /* set inconsistent examples to zero (-i 1) */
681  if((inconsistent[i] || (heldout==i)) && (a[i] != 0.0)) {
682  chosen[i]=99999;
683  choosenum++;
684  a[i]=0;
685  }
686  }
687  if(learn_parm->biased_hyperplane) {
688  eq=0;
689  for (i=0;i<totdoc;i++) { /* make sure we fulfill equality constraint */
690  eq+=a[i]*label[i];
691  }
692  for (i=0;(i<totdoc) && (fabs(eq) > learn_parm->epsilon_a);i++) {
693  if((eq*label[i] > 0) && (a[i] > 0)) {
694  chosen[i]=88888;
695  choosenum++;
696  if((eq*label[i]) > a[i]) {
697  eq-=(a[i]*label[i]);
698  a[i]=0;
699  }
700  else {
701  a[i]-=(eq*label[i]);
702  eq=0;
703  }
704  }
705  }
706  }
707  compute_index(chosen,totdoc,working2dnum);
708  }
709  else
710  { /* select working set according to steepest gradient */
711  if(iteration % 101)
712  {
713  already_chosen=0;
714  if(CMath::min(learn_parm->svm_newvarsinqp, learn_parm->svm_maxqpsize-choosenum)>=4 &&
716  {
717  /* select part of the working set from cache */
718  already_chosen=select_next_qp_subproblem_grad(
719  label,a,lin,c,totdoc,
720  (int32_t)(CMath::min(learn_parm->svm_maxqpsize-choosenum,
721  learn_parm->svm_newvarsinqp)/2),
722  inconsistent,active2dnum,
723  working2dnum,selcrit,selexam,1,
724  key,chosen);
725  choosenum+=already_chosen;
726  }
728  label,a,lin,c,totdoc,
729  CMath::min(learn_parm->svm_maxqpsize-choosenum,
730  learn_parm->svm_newvarsinqp-already_chosen),
731  inconsistent,active2dnum,
732  working2dnum,selcrit,selexam,0,key,
733  chosen);
734  }
735  else { /* once in a while, select a somewhat random working set
736  to get unlocked of infinite loops due to numerical
737  inaccuracies in the core qp-solver */
739  label,a,lin,c,totdoc,
740  CMath::min(learn_parm->svm_maxqpsize-choosenum,
741  learn_parm->svm_newvarsinqp),
742  inconsistent,active2dnum,
743  working2dnum,selcrit,selexam,key,
744  chosen,iteration);
745  }
746  }
747 
748  if(verbosity>=2) {
749  SG_INFO( " %ld vectors chosen\n",choosenum);
750  }
751 
752  if(verbosity>=2) t1=get_runtime();
753 
754  if (use_kernel_cache)
755  {
756  // in case of MKL w/o linadd cache each kernel independently
757  // else if linadd is disabled cache single kernel
758  if ( callback &&
759  (!((CCombinedKernel*) kernel)->get_append_subkernel_weights())
760  )
761  {
763  CKernel* kn = k->get_first_kernel();
764 
765  while (kn)
766  {
767  kn->cache_multiple_kernel_rows(working2dnum, choosenum);
768  SG_UNREF(kn);
769  kn = k->get_next_kernel() ;
770  }
771  }
772  else
773  kernel->cache_multiple_kernel_rows(working2dnum, choosenum);
774  }
775 
776  if(verbosity>=2) t2=get_runtime();
777 
778  if(retrain != 2) {
779  optimize_svm(docs,label,inconsistent,0.0,chosen,active2dnum,
780  totdoc,working2dnum,choosenum,a,lin,c,
781  aicache,&qp,&epsilon_crit_org);
782  }
783 
784  if(verbosity>=2) t3=get_runtime();
785  update_linear_component(docs,label,active2dnum,a,a_old,working2dnum,totdoc,
786  lin,aicache,c);
787 
788  if(verbosity>=2) t4=get_runtime();
789  supvecnum=calculate_svm_model(docs,label,lin,a,a_old,c,working2dnum,active2dnum);
790 
791  if(verbosity>=2) t5=get_runtime();
792 
793  for (jj=0;(i=working2dnum[jj])>=0;jj++) {
794  a_old[i]=a[i];
795  }
796 
797  retrain=check_optimality(label,a,lin,c,totdoc,
798  maxdiff,epsilon_crit_org,&misclassified,
799  inconsistent,active2dnum,last_suboptimal_at,
800  iteration);
801 
802  if(verbosity>=2) {
803  t6=get_runtime();
804  timing_profile->time_select+=t1-t0;
805  timing_profile->time_kernel+=t2-t1;
806  timing_profile->time_opti+=t3-t2;
807  timing_profile->time_update+=t4-t3;
808  timing_profile->time_model+=t5-t4;
809  timing_profile->time_check+=t6-t5;
810  }
811 
812  /* checking whether optimizer got stuck */
813  if((*maxdiff) < bestmaxdiff) {
814  bestmaxdiff=(*maxdiff);
815  bestmaxdiffiter=iteration;
816  }
817  if(iteration > (bestmaxdiffiter+learn_parm->maxiter)) {
818  /* int32_t time no progress? */
819  terminate=1;
820  retrain=0;
821  SG_WARNING( "Relaxing KT-Conditions due to slow progress! Terminating!\n");
822  SG_DEBUG("(iteration :%d, bestmaxdiffiter: %d, lean_param->maxiter: %d)\n", iteration, bestmaxdiffiter, learn_parm->maxiter );
823  }
824 
825  noshrink= (get_shrinking_enabled()) ? 0 : 1;
826 
827  if ((!callback) && (!retrain) && (inactivenum>0) &&
828  ((!learn_parm->skip_final_opt_check) || (kernel->has_property(KP_LINADD) && get_linadd_enabled())))
829  {
830  t1=get_runtime();
831  SG_DEBUG( "reactivating inactive examples\n");
832 
833  reactivate_inactive_examples(label,a,shrink_state,lin,c,totdoc,
834  iteration,inconsistent,
835  docs,aicache,
836  maxdiff);
837  reactivated=true;
838  SG_DEBUG("done reactivating inactive examples (maxdiff:%8f eps_crit:%8f orig_eps:%8f)\n", *maxdiff, learn_parm->epsilon_crit, epsilon_crit_org);
839  /* Update to new active variables. */
840  activenum=compute_index(shrink_state->active,totdoc,active2dnum);
841  inactivenum=totdoc-activenum;
842  /* reset watchdog */
843  bestmaxdiff=(*maxdiff);
844  bestmaxdiffiter=iteration;
845 
846  /* termination criterion */
847  noshrink=1;
848  retrain=0;
849  if((*maxdiff) > learn_parm->epsilon_crit)
850  {
851  SG_INFO( "restarting optimization as we are - due to shrinking - deviating too much (maxdiff(%f) > eps(%f))\n", *maxdiff, learn_parm->epsilon_crit);
852  retrain=1;
853  }
854  timing_profile->time_shrink+=get_runtime()-t1;
855  if (((verbosity>=1) && (!(kernel->has_property(KP_LINADD) && get_linadd_enabled())))
856  || (verbosity>=2)) {
857  SG_DONE();
858  SG_DEBUG("Number of inactive variables = %ld\n", inactivenum);
859  }
860  }
861 
862  if((!retrain) && (learn_parm->epsilon_crit>(*maxdiff)))
863  learn_parm->epsilon_crit=(*maxdiff);
864  if((!retrain) && (learn_parm->epsilon_crit>epsilon_crit_org)) {
865  learn_parm->epsilon_crit/=4.0;
866  retrain=1;
867  noshrink=1;
868  }
869  if(learn_parm->epsilon_crit<epsilon_crit_org)
870  learn_parm->epsilon_crit=epsilon_crit_org;
871 
872  if(verbosity>=2) {
873  SG_INFO( " => (%ld SV (incl. %ld SV at u-bound), max violation=%.5f)\n",
874  supvecnum,model->at_upper_bound,(*maxdiff));
875 
876  }
877  mymaxdiff=*maxdiff ;
878 
879  //don't shrink w/ mkl
880  if (((iteration % 10) == 0) && (!noshrink) && !callback)
881  {
882  activenum=shrink_problem(shrink_state,active2dnum,last_suboptimal_at,iteration,totdoc,
883  CMath::max((int32_t)(activenum/10),
884  CMath::max((int32_t)(totdoc/500),(int32_t) 100)),
885  a,inconsistent, c, lin, label);
886 
887  inactivenum=totdoc-activenum;
888 
889  if (use_kernel_cache && (supvecnum>kernel->get_max_elems_cache())
890  && ((kernel->get_activenum_cache()-activenum)>CMath::max((int32_t)(activenum/10),(int32_t) 500))) {
891 
892  kernel->kernel_cache_shrink(totdoc, CMath::min((int32_t) (kernel->get_activenum_cache()-activenum),
893  (int32_t) (kernel->get_activenum_cache()-supvecnum)),
894  shrink_state->active);
895  }
896  }
897 
898  if (bestmaxdiff>worstmaxdiff)
899  worstmaxdiff=bestmaxdiff;
900 
901  SG_ABS_PROGRESS(bestmaxdiff, -CMath::log10(bestmaxdiff), -CMath::log10(worstmaxdiff), -CMath::log10(epsilon), 6);
902 
903  /* Terminate loop */
904  if (m_max_train_time > 0 && start_time.cur_time_diff() > m_max_train_time) {
905  terminate = 1;
906  retrain = 0;
907  }
908 
909  } /* end of loop */
910 
911  SG_DEBUG( "inactive:%d\n", inactivenum);
912 
913  if (inactivenum && !reactivated && !callback)
914  {
915  SG_DEBUG( "reactivating inactive examples\n");
916  reactivate_inactive_examples(label,a,shrink_state,lin,c,totdoc,
917  iteration,inconsistent,
918  docs,aicache,
919  maxdiff);
920  SG_DEBUG( "done reactivating inactive examples\n");
921  /* Update to new active variables. */
922  activenum=compute_index(shrink_state->active,totdoc,active2dnum);
923  inactivenum=totdoc-activenum;
924  /* reset watchdog */
925  bestmaxdiff=(*maxdiff);
926  bestmaxdiffiter=iteration;
927  }
928 
929  //use this for our purposes!
930  criterion=compute_objective_function(a,lin,c,learn_parm->eps,label,totdoc);
931  CSVM::set_objective(criterion);
932 
933  SG_FREE(chosen);
934  SG_FREE(last_suboptimal_at);
935  SG_FREE(key);
936  SG_FREE(selcrit);
937  SG_FREE(selexam);
938  SG_FREE(a_old);
939  SG_FREE(aicache);
940  SG_FREE(working2dnum);
941  SG_FREE(active2dnum);
942  SG_FREE(qp.opt_ce);
943  SG_FREE(qp.opt_ce0);
944  SG_FREE(qp.opt_g);
945  SG_FREE(qp.opt_g0);
946  SG_FREE(qp.opt_xinit);
947  SG_FREE(qp.opt_low);
948  SG_FREE(qp.opt_up);
949 
950  learn_parm->epsilon_crit=epsilon_crit_org; /* restore org */
951 
952  return(iteration);
953 }
954 
956  float64_t *a, float64_t *lin, float64_t *c, float64_t* eps, int32_t *label,
957  int32_t totdoc)
958  /* Return value of objective function. */
959  /* Works only relative to the active variables! */
960 {
961  /* calculate value of objective function */
962  float64_t criterion=0;
963 
964  for (int32_t i=0;i<totdoc;i++)
965  criterion=criterion+(eps[i]-(float64_t)label[i]*c[i])*a[i]+0.5*a[i]*label[i]*lin[i];
966 
967  return(criterion);
968 }
969 
970 
971 void CSVMLight::clear_index(int32_t *index)
972  /* initializes and empties index */
973 {
974  index[0]=-1;
975 }
976 
977 void CSVMLight::add_to_index(int32_t *index, int32_t elem)
978  /* initializes and empties index */
979 {
980  register int32_t i;
981  for (i=0;index[i] != -1;i++);
982  index[i]=elem;
983  index[i+1]=-1;
984 }
985 
987  int32_t *binfeature, int32_t range, int32_t *index)
988  /* create an inverted index of binfeature */
989 {
990  register int32_t i,ii;
991 
992  ii=0;
993  for (i=0;i<range;i++) {
994  if(binfeature[i]) {
995  index[ii]=i;
996  ii++;
997  }
998  }
999  for (i=0;i<4;i++) {
1000  index[ii+i]=-1;
1001  }
1002  return(ii);
1003 }
1004 
1005 
1007  int32_t* docs, int32_t* label, int32_t *exclude_from_eq_const,
1008  float64_t eq_target, int32_t *chosen, int32_t *active2dnum, int32_t totdoc,
1009  int32_t *working2dnum, int32_t varnum, float64_t *a, float64_t *lin,
1010  float64_t *c, float64_t *aicache, QP *qp, float64_t *epsilon_crit_target)
1011  /* Do optimization on the working set. */
1012 {
1013  int32_t i;
1014  float64_t *a_v;
1015 
1016  //compute_matrices_for_optimization_parallel(docs,label,
1017  // exclude_from_eq_const,eq_target,chosen,
1018  // active2dnum,working2dnum,a,lin,c,
1019  // varnum,totdoc,aicache,qp);
1020 
1022  exclude_from_eq_const,eq_target,chosen,
1023  active2dnum,working2dnum,a,lin,c,
1024  varnum,totdoc,aicache,qp);
1025 
1026  if(verbosity>=3) {
1027  SG_DEBUG( "Running optimizer...");
1028  }
1029  /* call the qp-subsolver */
1030  a_v=optimize_qp(qp,epsilon_crit_target,
1031  learn_parm->svm_maxqpsize,
1032  &(model->b), /* in case the optimizer gives us */
1033  learn_parm->svm_maxqpsize); /* the threshold for free. otherwise */
1034  /* b is calculated in calculate_model. */
1035  if(verbosity>=3) {
1036  SG_DONE();
1037  }
1038 
1039  for (i=0;i<varnum;i++)
1040  a[working2dnum[i]]=a_v[i];
1041 }
1042 
1044  int32_t* docs, int32_t* label, int32_t *exclude_from_eq_const,
1045  float64_t eq_target, int32_t *chosen, int32_t *active2dnum, int32_t *key,
1046  float64_t *a, float64_t *lin, float64_t *c, int32_t varnum, int32_t totdoc,
1047  float64_t *aicache, QP *qp)
1048 {
1049  if (parallel->get_num_threads()<=1)
1050  {
1051  compute_matrices_for_optimization(docs, label, exclude_from_eq_const, eq_target,
1052  chosen, active2dnum, key, a, lin, c,
1053  varnum, totdoc, aicache, qp) ;
1054  }
1055 #ifdef HAVE_PTHREAD
1056  else
1057  {
1058  register int32_t ki,kj,i,j;
1059  register float64_t kernel_temp;
1060 
1061  qp->opt_n=varnum;
1062  qp->opt_ce0[0]=-eq_target; /* compute the constant for equality constraint */
1063  for (j=1;j<model->sv_num;j++) { /* start at 1 */
1064  if((!chosen[model->supvec[j]])
1065  && (!exclude_from_eq_const[(model->supvec[j])])) {
1066  qp->opt_ce0[0]+=model->alpha[j];
1067  }
1068  }
1069  if(learn_parm->biased_hyperplane)
1070  qp->opt_m=1;
1071  else
1072  qp->opt_m=0; /* eq-constraint will be ignored */
1073 
1074  /* init linear part of objective function */
1075  for (i=0;i<varnum;i++) {
1076  qp->opt_g0[i]=lin[key[i]];
1077  }
1078 
1080  int32_t *KI=SG_MALLOC(int32_t, varnum*varnum);
1081  int32_t *KJ=SG_MALLOC(int32_t, varnum*varnum);
1082  int32_t Knum=0 ;
1083  float64_t *Kval = SG_MALLOC(float64_t, varnum*(varnum+1)/2);
1084  for (i=0;i<varnum;i++) {
1085  ki=key[i];
1086  KI[Knum]=docs[ki] ;
1087  KJ[Knum]=docs[ki] ;
1088  Knum++ ;
1089  for (j=i+1;j<varnum;j++)
1090  {
1091  kj=key[j];
1092  KI[Knum]=docs[ki] ;
1093  KJ[Knum]=docs[kj] ;
1094  Knum++ ;
1095  }
1096  }
1097  ASSERT(Knum<=varnum*(varnum+1)/2);
1098 
1099  pthread_t* threads = SG_MALLOC(pthread_t, parallel->get_num_threads()-1);
1100  S_THREAD_PARAM_KERNEL* params = SG_MALLOC(S_THREAD_PARAM_KERNEL, parallel->get_num_threads()-1);
1101  int32_t step= Knum/parallel->get_num_threads();
1102  //SG_DEBUG( "\nkernel-step size: %i\n", step) ;
1103  for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
1104  {
1105  params[t].svmlight = this;
1106  params[t].start = t*step;
1107  params[t].end = (t+1)*step;
1108  params[t].KI=KI ;
1109  params[t].KJ=KJ ;
1110  params[t].Kval=Kval ;
1111  pthread_create(&threads[t], NULL, CSVMLight::compute_kernel_helper, (void*)&params[t]);
1112  }
1113  for (i=params[parallel->get_num_threads()-2].end; i<Knum; i++)
1114  Kval[i]=compute_kernel(KI[i],KJ[i]) ;
1115 
1116  for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
1117  pthread_join(threads[t], NULL);
1118 
1119  SG_FREE(params);
1120  SG_FREE(threads);
1121 
1122  Knum=0 ;
1123  for (i=0;i<varnum;i++) {
1124  ki=key[i];
1125 
1126  /* Compute the matrix for equality constraints */
1127  qp->opt_ce[i]=label[ki];
1128  qp->opt_low[i]=0;
1129  qp->opt_up[i]=learn_parm->svm_cost[ki];
1130 
1131  kernel_temp=Kval[Knum] ;
1132  Knum++ ;
1133  /* compute linear part of objective function */
1134  qp->opt_g0[i]-=(kernel_temp*a[ki]*(float64_t)label[ki]);
1135  /* compute quadratic part of objective function */
1136  qp->opt_g[varnum*i+i]=kernel_temp;
1137 
1138  for (j=i+1;j<varnum;j++) {
1139  kj=key[j];
1140  kernel_temp=Kval[Knum] ;
1141  Knum++ ;
1142  /* compute linear part of objective function */
1143  qp->opt_g0[i]-=(kernel_temp*a[kj]*(float64_t)label[kj]);
1144  qp->opt_g0[j]-=(kernel_temp*a[ki]*(float64_t)label[ki]);
1145  /* compute quadratic part of objective function */
1146  qp->opt_g[varnum*i+j]=(float64_t)label[ki]*(float64_t)label[kj]*kernel_temp;
1147  qp->opt_g[varnum*j+i]=qp->opt_g[varnum*i+j];//(float64_t)label[ki]*(float64_t)label[kj]*kernel_temp;
1148  }
1149 
1150  if(verbosity>=3) {
1151  if(i % 20 == 0) {
1152  SG_DEBUG( "%ld..",i);
1153  }
1154  }
1155  }
1156 
1157  SG_FREE(KI);
1158  SG_FREE(KJ);
1159  SG_FREE(Kval);
1160 
1161  for (i=0;i<varnum;i++) {
1162  /* assure starting at feasible point */
1163  qp->opt_xinit[i]=a[key[i]];
1164  /* set linear part of objective function */
1165  qp->opt_g0[i]=(learn_parm->eps[key[i]]-(float64_t)label[key[i]]*c[key[i]])+qp->opt_g0[i]*(float64_t)label[key[i]];
1166  }
1167 
1168  if(verbosity>=3) {
1169  SG_DONE();
1170  }
1171  }
1172 #endif
1173 }
1174 
1176  int32_t* docs, int32_t* label, int32_t *exclude_from_eq_const,
1177  float64_t eq_target, int32_t *chosen, int32_t *active2dnum, int32_t *key,
1178  float64_t *a, float64_t *lin, float64_t *c, int32_t varnum, int32_t totdoc,
1179  float64_t *aicache, QP *qp)
1180 {
1181  register int32_t ki,kj,i,j;
1182  register float64_t kernel_temp;
1183 
1184  qp->opt_n=varnum;
1185  qp->opt_ce0[0]=-eq_target; /* compute the constant for equality constraint */
1186  for (j=1;j<model->sv_num;j++) { /* start at 1 */
1187  if((!chosen[model->supvec[j]])
1188  && (!exclude_from_eq_const[(model->supvec[j])])) {
1189  qp->opt_ce0[0]+=model->alpha[j];
1190  }
1191  }
1192  if(learn_parm->biased_hyperplane)
1193  qp->opt_m=1;
1194  else
1195  qp->opt_m=0; /* eq-constraint will be ignored */
1196 
1197  /* init linear part of objective function */
1198  for (i=0;i<varnum;i++) {
1199  qp->opt_g0[i]=lin[key[i]];
1200  }
1201 
1202  for (i=0;i<varnum;i++) {
1203  ki=key[i];
1204 
1205  /* Compute the matrix for equality constraints */
1206  qp->opt_ce[i]=label[ki];
1207  qp->opt_low[i]=0;
1208  qp->opt_up[i]=learn_parm->svm_cost[ki];
1209 
1210  kernel_temp=compute_kernel(docs[ki], docs[ki]);
1211  /* compute linear part of objective function */
1212  qp->opt_g0[i]-=(kernel_temp*a[ki]*(float64_t)label[ki]);
1213  /* compute quadratic part of objective function */
1214  qp->opt_g[varnum*i+i]=kernel_temp;
1215 
1216  for (j=i+1;j<varnum;j++) {
1217  kj=key[j];
1218  kernel_temp=compute_kernel(docs[ki], docs[kj]);
1219 
1220  /* compute linear part of objective function */
1221  qp->opt_g0[i]-=(kernel_temp*a[kj]*(float64_t)label[kj]);
1222  qp->opt_g0[j]-=(kernel_temp*a[ki]*(float64_t)label[ki]);
1223  /* compute quadratic part of objective function */
1224  qp->opt_g[varnum*i+j]=(float64_t)label[ki]*(float64_t)label[kj]*kernel_temp;
1225  qp->opt_g[varnum*j+i]=qp->opt_g[varnum*i+j];//(float64_t)label[ki]*(float64_t)label[kj]*kernel_temp;
1226  }
1227 
1228  if(verbosity>=3) {
1229  if(i % 20 == 0) {
1230  SG_DEBUG( "%ld..",i);
1231  }
1232  }
1233  }
1234 
1235  for (i=0;i<varnum;i++) {
1236  /* assure starting at feasible point */
1237  qp->opt_xinit[i]=a[key[i]];
1238  /* set linear part of objective function */
1239  qp->opt_g0[i]=(learn_parm->eps[key[i]]-(float64_t)label[key[i]]*c[key[i]]) + qp->opt_g0[i]*(float64_t)label[key[i]];
1240  }
1241 
1242  if(verbosity>=3) {
1243  SG_DONE();
1244  }
1245 }
1246 
1247 
1249  int32_t* docs, int32_t *label, float64_t *lin, float64_t *a,
1250  float64_t *a_old, float64_t *c, int32_t *working2dnum, int32_t *active2dnum)
1251  /* Compute decision function based on current values */
1252  /* of alpha. */
1253 {
1254  int32_t i,ii,pos,b_calculated=0,first_low,first_high;
1255  float64_t ex_c,b_temp,b_low,b_high;
1256 
1257  if(verbosity>=3) {
1258  SG_DEBUG( "Calculating model...");
1259  }
1260 
1261  if(!learn_parm->biased_hyperplane) {
1262  model->b=0;
1263  b_calculated=1;
1264  }
1265 
1266  for (ii=0;(i=working2dnum[ii])>=0;ii++) {
1267  if((a_old[i]>0) && (a[i]==0)) { /* remove from model */
1268  pos=model->index[i];
1269  model->index[i]=-1;
1270  (model->sv_num)--;
1271  model->supvec[pos]=model->supvec[model->sv_num];
1272  model->alpha[pos]=model->alpha[model->sv_num];
1273  model->index[model->supvec[pos]]=pos;
1274  }
1275  else if((a_old[i]==0) && (a[i]>0)) { /* add to model */
1276  model->supvec[model->sv_num]=docs[i];
1277  model->alpha[model->sv_num]=a[i]*(float64_t)label[i];
1278  model->index[i]=model->sv_num;
1279  (model->sv_num)++;
1280  }
1281  else if(a_old[i]==a[i]) { /* nothing to do */
1282  }
1283  else { /* just update alpha */
1284  model->alpha[model->index[i]]=a[i]*(float64_t)label[i];
1285  }
1286 
1287  ex_c=learn_parm->svm_cost[i]-learn_parm->epsilon_a;
1288  if((a_old[i]>=ex_c) && (a[i]<ex_c)) {
1289  (model->at_upper_bound)--;
1290  }
1291  else if((a_old[i]<ex_c) && (a[i]>=ex_c)) {
1292  (model->at_upper_bound)++;
1293  }
1294 
1295  if((!b_calculated)
1296  && (a[i]>learn_parm->epsilon_a) && (a[i]<ex_c)) { /* calculate b */
1297  model->b=((float64_t)label[i]*learn_parm->eps[i]-c[i]+lin[i]);
1298  b_calculated=1;
1299  }
1300  }
1301 
1302  /* No alpha in the working set not at bounds, so b was not
1303  calculated in the usual way. The following handles this special
1304  case. */
1305  if(learn_parm->biased_hyperplane
1306  && (!b_calculated)
1307  && (model->sv_num-1 == model->at_upper_bound)) {
1308  first_low=1;
1309  first_high=1;
1310  b_low=0;
1311  b_high=0;
1312  for (ii=0;(i=active2dnum[ii])>=0;ii++) {
1313  ex_c=learn_parm->svm_cost[i]-learn_parm->epsilon_a;
1314  if(a[i]<ex_c) {
1315  if(label[i]>0) {
1316  b_temp=-(learn_parm->eps[i]-c[i]+lin[i]);
1317  if((b_temp>b_low) || (first_low)) {
1318  b_low=b_temp;
1319  first_low=0;
1320  }
1321  }
1322  else {
1323  b_temp=-(-learn_parm->eps[i]-c[i]+lin[i]);
1324  if((b_temp<b_high) || (first_high)) {
1325  b_high=b_temp;
1326  first_high=0;
1327  }
1328  }
1329  }
1330  else {
1331  if(label[i]<0) {
1332  b_temp=-(-learn_parm->eps[i]-c[i]+lin[i]);
1333  if((b_temp>b_low) || (first_low)) {
1334  b_low=b_temp;
1335  first_low=0;
1336  }
1337  }
1338  else {
1339  b_temp=-(learn_parm->eps[i]-c[i]+lin[i]);
1340  if((b_temp<b_high) || (first_high)) {
1341  b_high=b_temp;
1342  first_high=0;
1343  }
1344  }
1345  }
1346  }
1347  if(first_high) {
1348  model->b=-b_low;
1349  }
1350  else if(first_low) {
1351  model->b=-b_high;
1352  }
1353  else {
1354  model->b=-(b_high+b_low)/2.0; /* select b as the middle of range */
1355  }
1356  }
1357 
1358  if(verbosity>=3) {
1359  SG_DONE();
1360  }
1361 
1362  return(model->sv_num-1); /* have to substract one, since element 0 is empty*/
1363 }
1364 
1366  int32_t* label, float64_t *a, float64_t *lin, float64_t *c, int32_t totdoc,
1367  float64_t *maxdiff, float64_t epsilon_crit_org, int32_t *misclassified,
1368  int32_t *inconsistent, int32_t *active2dnum, int32_t *last_suboptimal_at,
1369  int32_t iteration)
1370  /* Check KT-conditions */
1371 {
1372  int32_t i,ii,retrain;
1373  float64_t dist,ex_c,target;
1374 
1376  learn_parm->epsilon_shrink=-learn_parm->epsilon_crit+epsilon_crit_org;
1377  else
1378  learn_parm->epsilon_shrink=learn_parm->epsilon_shrink*0.7+(*maxdiff)*0.3;
1379  retrain=0;
1380  (*maxdiff)=0;
1381  (*misclassified)=0;
1382  for (ii=0;(i=active2dnum[ii])>=0;ii++) {
1383  if((!inconsistent[i]) && label[i]) {
1384  dist=(lin[i]-model->b)*(float64_t)label[i];/* 'distance' from
1385  hyperplane*/
1386  target=-(learn_parm->eps[i]-(float64_t)label[i]*c[i]);
1387  ex_c=learn_parm->svm_cost[i]-learn_parm->epsilon_a;
1388  if(dist <= 0) {
1389  (*misclassified)++; /* does not work due to deactivation of var */
1390  }
1391  if((a[i]>learn_parm->epsilon_a) && (dist > target)) {
1392  if((dist-target)>(*maxdiff)) /* largest violation */
1393  (*maxdiff)=dist-target;
1394  }
1395  else if((a[i]<ex_c) && (dist < target)) {
1396  if((target-dist)>(*maxdiff)) /* largest violation */
1397  (*maxdiff)=target-dist;
1398  }
1399  /* Count how int32_t a variable was at lower/upper bound (and optimal).*/
1400  /* Variables, which were at the bound and optimal for a int32_t */
1401  /* time are unlikely to become support vectors. In case our */
1402  /* cache is filled up, those variables are excluded to save */
1403  /* kernel evaluations. (See chapter 'Shrinking').*/
1404  if((a[i]>(learn_parm->epsilon_a))
1405  && (a[i]<ex_c)) {
1406  last_suboptimal_at[i]=iteration; /* not at bound */
1407  }
1408  else if((a[i]<=(learn_parm->epsilon_a))
1409  && (dist < (target+learn_parm->epsilon_shrink))) {
1410  last_suboptimal_at[i]=iteration; /* not likely optimal */
1411  }
1412  else if((a[i]>=ex_c)
1413  && (dist > (target-learn_parm->epsilon_shrink))) {
1414  last_suboptimal_at[i]=iteration; /* not likely optimal */
1415  }
1416  }
1417  }
1418 
1419  /* termination criterion */
1420  if((!retrain) && ((*maxdiff) > learn_parm->epsilon_crit)) {
1421  retrain=1;
1422  }
1423  return(retrain);
1424 }
1425 
1427  int32_t* docs, int32_t* label, int32_t *active2dnum, float64_t *a,
1428  float64_t *a_old, int32_t *working2dnum, int32_t totdoc, float64_t *lin,
1429  float64_t *aicache, float64_t* c)
1430  /* keep track of the linear component */
1431  /* lin of the gradient etc. by updating */
1432  /* based on the change of the variables */
1433  /* in the current working set */
1434 {
1435  register int32_t i=0,ii=0,j=0,jj=0;
1436 
1438  {
1439  if (callback)
1440  {
1441  update_linear_component_mkl_linadd(docs, label, active2dnum, a,
1442  a_old, working2dnum, totdoc, lin, aicache);
1443  }
1444  else
1445  {
1446  kernel->clear_normal();
1447 
1448  int32_t num_working=0;
1449  for (ii=0;(i=working2dnum[ii])>=0;ii++) {
1450  if(a[i] != a_old[i]) {
1451  kernel->add_to_normal(docs[i], (a[i]-a_old[i])*(float64_t)label[i]);
1452  num_working++;
1453  }
1454  }
1455 
1456  if (num_working>0)
1457  {
1458  if (parallel->get_num_threads() < 2)
1459  {
1460  for (jj=0;(j=active2dnum[jj])>=0;jj++) {
1461  lin[j]+=kernel->compute_optimized(docs[j]);
1462  }
1463  }
1464 #ifdef HAVE_PTHREAD
1465  else
1466  {
1467  int32_t num_elem = 0 ;
1468  for (jj=0;(j=active2dnum[jj])>=0;jj++) num_elem++ ;
1469 
1470  pthread_t* threads = SG_MALLOC(pthread_t, parallel->get_num_threads()-1);
1471  S_THREAD_PARAM* params = SG_MALLOC(S_THREAD_PARAM, parallel->get_num_threads()-1);
1472  int32_t start = 0 ;
1473  int32_t step = num_elem/parallel->get_num_threads();
1474  int32_t end = step ;
1475 
1476  for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
1477  {
1478  params[t].kernel = kernel ;
1479  params[t].lin = lin ;
1480  params[t].docs = docs ;
1481  params[t].active2dnum=active2dnum ;
1482  params[t].start = start ;
1483  params[t].end = end ;
1484  start=end ;
1485  end+=step ;
1486  pthread_create(&threads[t], NULL, update_linear_component_linadd_helper, (void*)&params[t]) ;
1487  }
1488 
1489  for (jj=params[parallel->get_num_threads()-2].end;(j=active2dnum[jj])>=0;jj++) {
1490  lin[j]+=kernel->compute_optimized(docs[j]);
1491  }
1492  void* ret;
1493  for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
1494  pthread_join(threads[t], &ret) ;
1495 
1496  SG_FREE(params);
1497  SG_FREE(threads);
1498  }
1499 #endif
1500  }
1501  }
1502  }
1503  else
1504  {
1505  if (callback)
1506  {
1507  update_linear_component_mkl(docs, label, active2dnum,
1508  a, a_old, working2dnum, totdoc, lin, aicache);
1509  }
1510  else {
1511  for (jj=0;(i=working2dnum[jj])>=0;jj++) {
1512  if(a[i] != a_old[i]) {
1513  kernel->get_kernel_row(i,active2dnum,aicache);
1514  for (ii=0;(j=active2dnum[ii])>=0;ii++)
1515  lin[j]+=(a[i]-a_old[i])*aicache[j]*(float64_t)label[i];
1516  }
1517  }
1518  }
1519  }
1520 }
1521 
1522 
1524  int32_t* docs, int32_t* label, int32_t *active2dnum, float64_t *a,
1525  float64_t *a_old, int32_t *working2dnum, int32_t totdoc, float64_t *lin,
1526  float64_t *aicache)
1527 {
1528  //int inner_iters=0;
1529  int32_t num = kernel->get_num_vec_rhs();
1530  int32_t num_weights = -1;
1531  int32_t num_kernels = kernel->get_num_subkernels() ;
1532  const float64_t* old_beta = kernel->get_subkernel_weights(num_weights);
1533  ASSERT(num_weights==num_kernels);
1534 
1535  if ((kernel->get_kernel_type()==K_COMBINED) &&
1536  (!((CCombinedKernel*)kernel)->get_append_subkernel_weights()))// for combined kernel
1537  {
1539  CKernel* kn = k->get_first_kernel() ;
1540  int32_t n = 0, i, j ;
1541 
1542  while (kn!=NULL)
1543  {
1544  for (i=0;i<num;i++)
1545  {
1546  if(a[i] != a_old[i])
1547  {
1548  kn->get_kernel_row(i,NULL,aicache, true);
1549  for (j=0;j<num;j++)
1550  W[j*num_kernels+n]+=(a[i]-a_old[i])*aicache[j]*(float64_t)label[i];
1551  }
1552  }
1553 
1554  SG_UNREF(kn);
1555  kn = k->get_next_kernel();
1556  n++ ;
1557  }
1558  }
1559  else // hope the kernel is fast ...
1560  {
1561  float64_t* w_backup = SG_MALLOC(float64_t, num_kernels);
1562  float64_t* w1 = SG_MALLOC(float64_t, num_kernels);
1563 
1564  // backup and set to zero
1565  for (int32_t i=0; i<num_kernels; i++)
1566  {
1567  w_backup[i] = old_beta[i] ;
1568  w1[i]=0.0 ;
1569  }
1570  for (int32_t n=0; n<num_kernels; n++)
1571  {
1572  w1[n]=1.0 ;
1574 
1575  for (int32_t i=0;i<num;i++)
1576  {
1577  if(a[i] != a_old[i])
1578  {
1579  for (int32_t j=0;j<num;j++)
1580  W[j*num_kernels+n]+=(a[i]-a_old[i])*compute_kernel(i,j)*(float64_t)label[i];
1581  }
1582  }
1583  w1[n]=0.0 ;
1584  }
1585 
1586  // restore old weights
1587  kernel->set_subkernel_weights(SGVector<float64_t>(w_backup,num_weights));
1588 
1589  SG_FREE(w_backup);
1590  SG_FREE(w1);
1591  }
1592 
1593  call_mkl_callback(a, label, lin);
1594 }
1595 
1596 
1598  int32_t* docs, int32_t* label, int32_t *active2dnum, float64_t *a,
1599  float64_t *a_old, int32_t *working2dnum, int32_t totdoc, float64_t *lin,
1600  float64_t *aicache)
1601 {
1602  //int inner_iters=0;
1603 
1604  // kernel with LP_LINADD property is assumed to have
1605  // compute_by_subkernel functions
1606  int32_t num = kernel->get_num_vec_rhs();
1607  int32_t num_weights = -1;
1608  int32_t num_kernels = kernel->get_num_subkernels() ;
1609  const float64_t* old_beta = kernel->get_subkernel_weights(num_weights);
1610  ASSERT(num_weights==num_kernels);
1611 
1612  float64_t* w_backup = SG_MALLOC(float64_t, num_kernels);
1613  float64_t* w1 = SG_MALLOC(float64_t, num_kernels);
1614 
1615  // backup and set to one
1616  for (int32_t i=0; i<num_kernels; i++)
1617  {
1618  w_backup[i] = old_beta[i] ;
1619  w1[i]=1.0 ;
1620  }
1621  // set the kernel weights
1623 
1624  // create normal update (with changed alphas only)
1625  kernel->clear_normal();
1626  for (int32_t ii=0, i=0;(i=working2dnum[ii])>=0;ii++) {
1627  if(a[i] != a_old[i]) {
1628  kernel->add_to_normal(docs[i], (a[i]-a_old[i])*(float64_t)label[i]);
1629  }
1630  }
1631 
1632  if (parallel->get_num_threads() < 2)
1633  {
1634  // determine contributions of different kernels
1635  for (int32_t i=0; i<num; i++)
1636  kernel->compute_by_subkernel(i,&W[i*num_kernels]);
1637  }
1638 #ifdef HAVE_PTHREAD
1639  else
1640  {
1641  pthread_t* threads = SG_MALLOC(pthread_t, parallel->get_num_threads()-1);
1642  S_THREAD_PARAM* params = SG_MALLOC(S_THREAD_PARAM, parallel->get_num_threads()-1);
1643  int32_t step= num/parallel->get_num_threads();
1644 
1645  for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
1646  {
1647  params[t].kernel = kernel;
1648  params[t].W = W;
1649  params[t].start = t*step;
1650  params[t].end = (t+1)*step;
1651  pthread_create(&threads[t], NULL, CSVMLight::update_linear_component_mkl_linadd_helper, (void*)&params[t]);
1652  }
1653 
1654  for (int32_t i=params[parallel->get_num_threads()-2].end; i<num; i++)
1655  kernel->compute_by_subkernel(i,&W[i*num_kernels]);
1656 
1657  for (int32_t t=0; t<parallel->get_num_threads()-1; t++)
1658  pthread_join(threads[t], NULL);
1659 
1660  SG_FREE(params);
1661  SG_FREE(threads);
1662  }
1663 #endif
1664 
1665  // restore old weights
1666  kernel->set_subkernel_weights(SGVector<float64_t>(w_backup,num_weights));
1667 
1668  call_mkl_callback(a, label, lin);
1669 }
1670 
1672 {
1673  S_THREAD_PARAM* params = (S_THREAD_PARAM*) p;
1674 
1675  int32_t num_kernels=params->kernel->get_num_subkernels();
1676 
1677  // determine contributions of different kernels
1678  for (int32_t i=params->start; i<params->end; i++)
1679  params->kernel->compute_by_subkernel(i,&(params->W[i*num_kernels]));
1680 
1681  return NULL ;
1682 }
1683 
1684 void CSVMLight::call_mkl_callback(float64_t* a, int32_t* label, float64_t* lin)
1685 {
1686  int32_t num = kernel->get_num_vec_rhs();
1687  int32_t num_kernels = kernel->get_num_subkernels() ;
1688 
1689  float64_t suma=0;
1690  float64_t* sumw=SG_MALLOC(float64_t, num_kernels);
1691 #ifdef HAVE_LAPACK
1692  int nk = (int) num_kernels; /* calling external lib */
1693  double* alphay = SG_MALLOC(double, num);
1694 
1695  for (int32_t i=0; i<num; i++)
1696  {
1697  alphay[i]=a[i]*label[i];
1698  suma+=a[i];
1699  }
1700 
1701  for (int32_t i=0; i<num_kernels; i++)
1702  sumw[i]=0;
1703 
1704  cblas_dgemv(CblasColMajor, CblasNoTrans, num_kernels, (int) num, 0.5, (double*) W,
1705  num_kernels, alphay, 1, 1.0, (double*) sumw, 1);
1706 
1707  SG_FREE(alphay);
1708 #else
1709  for (int32_t i=0; i<num; i++)
1710  suma += a[i];
1711 
1712  for (int32_t d=0; d<num_kernels; d++)
1713  {
1714  sumw[d]=0;
1715  for (int32_t i=0; i<num; i++)
1716  sumw[d] += a[i]*(0.5*label[i]*W[i*num_kernels+d]);
1717  }
1718 #endif
1719 
1720  if (callback)
1721  mkl_converged=callback(mkl, sumw, suma);
1722 
1723 
1724  const float64_t* new_beta = kernel->get_subkernel_weights(num_kernels);
1725 
1726  // update lin
1727 #ifdef HAVE_LAPACK
1728  cblas_dgemv(CblasColMajor, CblasTrans, nk, (int) num, 1.0, (double*) W,
1729  nk, (double*) new_beta, 1, 0.0, (double*) lin, 1);
1730 #else
1731  for (int32_t i=0; i<num; i++)
1732  lin[i]=0 ;
1733  for (int32_t d=0; d<num_kernels; d++)
1734  if (new_beta[d]!=0)
1735  for (int32_t i=0; i<num; i++)
1736  lin[i] += new_beta[d]*W[i*num_kernels+d] ;
1737 #endif
1738 
1739  SG_FREE(sumw);
1740 }
1741 
1742 
1743 /*************************** Working set selection ***************************/
1744 
1746  int32_t* label, float64_t *a, float64_t *lin, float64_t *c, int32_t totdoc,
1747  int32_t qp_size, int32_t *inconsistent, int32_t *active2dnum,
1748  int32_t *working2dnum, float64_t *selcrit, int32_t *select,
1749  int32_t cache_only, int32_t *key, int32_t *chosen)
1750  /* Use the feasible direction approach to select the next
1751  qp-subproblem (see chapter 'Selecting a good working set'). If
1752  'cache_only' is true, then the variables are selected only among
1753  those for which the kernel evaluations are cached. */
1754 {
1755  int32_t choosenum,i,j,k,activedoc,inum,valid;
1756  float64_t s;
1757 
1758  for (inum=0;working2dnum[inum]>=0;inum++); /* find end of index */
1759  choosenum=0;
1760  activedoc=0;
1761  for (i=0;(j=active2dnum[i])>=0;i++) {
1762  s=-label[j];
1763  if(cache_only)
1764  {
1765  if (use_kernel_cache)
1766  valid=(kernel->kernel_cache_check(j));
1767  else
1768  valid = 1 ;
1769  }
1770  else
1771  valid=1;
1772  if(valid
1773  && (!((a[j]<=(0+learn_parm->epsilon_a)) && (s<0)))
1774  && (!((a[j]>=(learn_parm->svm_cost[j]-learn_parm->epsilon_a))
1775  && (s>0)))
1776  && (!chosen[j])
1777  && (label[j])
1778  && (!inconsistent[j]))
1779  {
1780  selcrit[activedoc]=(float64_t)label[j]*(learn_parm->eps[j]-(float64_t)label[j]*c[j]+(float64_t)label[j]*lin[j]);
1781  key[activedoc]=j;
1782  activedoc++;
1783  }
1784  }
1785  select_top_n(selcrit,activedoc,select,(int32_t)(qp_size/2));
1786  for (k=0;(choosenum<(qp_size/2)) && (k<(qp_size/2)) && (k<activedoc);k++) {
1787  i=key[select[k]];
1788  chosen[i]=1;
1789  working2dnum[inum+choosenum]=i;
1790  choosenum+=1;
1791  if (use_kernel_cache)
1793  /* make sure it does not get kicked */
1794  /* out of cache */
1795  }
1796 
1797  activedoc=0;
1798  for (i=0;(j=active2dnum[i])>=0;i++) {
1799  s=label[j];
1800  if(cache_only)
1801  {
1802  if (use_kernel_cache)
1803  valid=(kernel->kernel_cache_check(j));
1804  else
1805  valid = 1 ;
1806  }
1807  else
1808  valid=1;
1809  if(valid
1810  && (!((a[j]<=(0+learn_parm->epsilon_a)) && (s<0)))
1811  && (!((a[j]>=(learn_parm->svm_cost[j]-learn_parm->epsilon_a))
1812  && (s>0)))
1813  && (!chosen[j])
1814  && (label[j])
1815  && (!inconsistent[j]))
1816  {
1817  selcrit[activedoc]=-(float64_t)label[j]*(learn_parm->eps[j]-(float64_t)label[j]*c[j]+(float64_t)label[j]*lin[j]);
1818  /* selcrit[activedoc]=-(float64_t)(label[j]*(-1.0+(float64_t)label[j]*lin[j])); */
1819  key[activedoc]=j;
1820  activedoc++;
1821  }
1822  }
1823  select_top_n(selcrit,activedoc,select,(int32_t)(qp_size/2));
1824  for (k=0;(choosenum<qp_size) && (k<(qp_size/2)) && (k<activedoc);k++) {
1825  i=key[select[k]];
1826  chosen[i]=1;
1827  working2dnum[inum+choosenum]=i;
1828  choosenum+=1;
1829  if (use_kernel_cache)
1830  kernel->kernel_cache_touch(i); /* make sure it does not get kicked */
1831  /* out of cache */
1832  }
1833  working2dnum[inum+choosenum]=-1; /* complete index */
1834  return(choosenum);
1835 }
1836 
1838  int32_t* label, float64_t *a, float64_t *lin, float64_t *c, int32_t totdoc,
1839  int32_t qp_size, int32_t *inconsistent, int32_t *active2dnum,
1840  int32_t *working2dnum, float64_t *selcrit, int32_t *select, int32_t *key,
1841  int32_t *chosen, int32_t iteration)
1842 /* Use the feasible direction approach to select the next
1843  qp-subproblem (see section 'Selecting a good working set'). Chooses
1844  a feasible direction at (pseudo) random to help jump over numerical
1845  problem. */
1846 {
1847  int32_t choosenum,i,j,k,activedoc,inum;
1848  float64_t s;
1849 
1850  for (inum=0;working2dnum[inum]>=0;inum++); /* find end of index */
1851  choosenum=0;
1852  activedoc=0;
1853  for (i=0;(j=active2dnum[i])>=0;i++) {
1854  s=-label[j];
1855  if((!((a[j]<=(0+learn_parm->epsilon_a)) && (s<0)))
1856  && (!((a[j]>=(learn_parm->svm_cost[j]-learn_parm->epsilon_a))
1857  && (s>0)))
1858  && (!inconsistent[j])
1859  && (label[j])
1860  && (!chosen[j])) {
1861  selcrit[activedoc]=(j+iteration) % totdoc;
1862  key[activedoc]=j;
1863  activedoc++;
1864  }
1865  }
1866  select_top_n(selcrit,activedoc,select,(int32_t)(qp_size/2));
1867  for (k=0;(choosenum<(qp_size/2)) && (k<(qp_size/2)) && (k<activedoc);k++) {
1868  i=key[select[k]];
1869  chosen[i]=1;
1870  working2dnum[inum+choosenum]=i;
1871  choosenum+=1;
1872  if (use_kernel_cache)
1873  kernel->kernel_cache_touch(i); /* make sure it does not get kicked */
1874  /* out of cache */
1875  }
1876 
1877  activedoc=0;
1878  for (i=0;(j=active2dnum[i])>=0;i++) {
1879  s=label[j];
1880  if((!((a[j]<=(0+learn_parm->epsilon_a)) && (s<0)))
1881  && (!((a[j]>=(learn_parm->svm_cost[j]-learn_parm->epsilon_a))
1882  && (s>0)))
1883  && (!inconsistent[j])
1884  && (label[j])
1885  && (!chosen[j])) {
1886  selcrit[activedoc]=(j+iteration) % totdoc;
1887  key[activedoc]=j;
1888  activedoc++;
1889  }
1890  }
1891  select_top_n(selcrit,activedoc,select,(int32_t)(qp_size/2));
1892  for (k=0;(choosenum<qp_size) && (k<(qp_size/2)) && (k<activedoc);k++) {
1893  i=key[select[k]];
1894  chosen[i]=1;
1895  working2dnum[inum+choosenum]=i;
1896  choosenum+=1;
1897  if (use_kernel_cache)
1898  kernel->kernel_cache_touch(i); /* make sure it does not get kicked */
1899  /* out of cache */
1900  }
1901  working2dnum[inum+choosenum]=-1; /* complete index */
1902  return(choosenum);
1903 }
1904 
1905 
1906 
1908  float64_t *selcrit, int32_t range, int32_t* select, int32_t n)
1909 {
1910  register int32_t i,j;
1911 
1912  for (i=0;(i<n) && (i<range);i++) { /* Initialize with the first n elements */
1913  for (j=i;j>=0;j--) {
1914  if((j>0) && (selcrit[select[j-1]]<selcrit[i])){
1915  select[j]=select[j-1];
1916  }
1917  else {
1918  select[j]=i;
1919  j=-1;
1920  }
1921  }
1922  }
1923  if(n>0) {
1924  for (i=n;i<range;i++) {
1925  if(selcrit[i]>selcrit[select[n-1]]) {
1926  for (j=n-1;j>=0;j--) {
1927  if((j>0) && (selcrit[select[j-1]]<selcrit[i])) {
1928  select[j]=select[j-1];
1929  }
1930  else {
1931  select[j]=i;
1932  j=-1;
1933  }
1934  }
1935  }
1936  }
1937  }
1938 }
1939 
1940 
1941 /******************************** Shrinking *********************************/
1942 
1944  SHRINK_STATE *shrink_state, int32_t totdoc, int32_t maxhistory)
1945 {
1946  int32_t i;
1947 
1948  shrink_state->deactnum=0;
1949  shrink_state->active = SG_MALLOC(int32_t, totdoc);
1950  shrink_state->inactive_since = SG_MALLOC(int32_t, totdoc);
1951  shrink_state->a_history = SG_MALLOC(float64_t*, maxhistory);
1952  shrink_state->maxhistory=maxhistory;
1953  shrink_state->last_lin = SG_MALLOC(float64_t, totdoc);
1954  shrink_state->last_a = SG_MALLOC(float64_t, totdoc);
1955 
1956  for (i=0;i<totdoc;i++) {
1957  shrink_state->active[i]=1;
1958  shrink_state->inactive_since[i]=0;
1959  shrink_state->last_a[i]=0;
1960  shrink_state->last_lin[i]=0;
1961  }
1962 }
1963 
1964 void CSVMLight::shrink_state_cleanup(SHRINK_STATE *shrink_state)
1965 {
1966  SG_FREE(shrink_state->active);
1967  SG_FREE(shrink_state->inactive_since);
1968  if(shrink_state->deactnum > 0)
1969  SG_FREE((shrink_state->a_history[shrink_state->deactnum-1]));
1970  SG_FREE((shrink_state->a_history));
1971  SG_FREE((shrink_state->last_a));
1972  SG_FREE((shrink_state->last_lin));
1973 }
1974 
1976  SHRINK_STATE *shrink_state, int32_t *active2dnum,
1977  int32_t *last_suboptimal_at, int32_t iteration, int32_t totdoc,
1978  int32_t minshrink, float64_t *a, int32_t *inconsistent, float64_t* c,
1979  float64_t* lin, int* label)
1980  /* Shrink some variables away. Do the shrinking only if at least
1981  minshrink variables can be removed. */
1982 {
1983  int32_t i,ii,change,activenum,lastiter;
1984  float64_t *a_old=NULL;
1985 
1986  activenum=0;
1987  change=0;
1988  for (ii=0;active2dnum[ii]>=0;ii++) {
1989  i=active2dnum[ii];
1990  activenum++;
1991  lastiter=last_suboptimal_at[i];
1992 
1993  if(((iteration-lastiter) > learn_parm->svm_iter_to_shrink)
1994  || (inconsistent[i])) {
1995  change++;
1996  }
1997  }
1998  if((change>=minshrink) /* shrink only if sufficiently many candidates */
1999  && (shrink_state->deactnum<shrink_state->maxhistory)) { /* and enough memory */
2000  /* Shrink problem by removing those variables which are */
2001  /* optimal at a bound for a minimum number of iterations */
2002  if(verbosity>=2) {
2003  SG_INFO( " Shrinking...");
2004  }
2005 
2006  if (!(kernel->has_property(KP_LINADD) && get_linadd_enabled())) { /* non-linear case save alphas */
2007 
2008  a_old=SG_MALLOC(float64_t, totdoc);
2009  shrink_state->a_history[shrink_state->deactnum]=a_old;
2010  for (i=0;i<totdoc;i++) {
2011  a_old[i]=a[i];
2012  }
2013  }
2014  for (ii=0;active2dnum[ii]>=0;ii++) {
2015  i=active2dnum[ii];
2016  lastiter=last_suboptimal_at[i];
2017  if(((iteration-lastiter) > learn_parm->svm_iter_to_shrink)
2018  || (inconsistent[i])) {
2019  shrink_state->active[i]=0;
2020  shrink_state->inactive_since[i]=shrink_state->deactnum;
2021  }
2022  }
2023  activenum=compute_index(shrink_state->active,totdoc,active2dnum);
2024  shrink_state->deactnum++;
2026  shrink_state->deactnum=0;
2027 
2028  if(verbosity>=2) {
2029  SG_DONE();
2030  SG_DEBUG("Number of inactive variables = %ld\n", totdoc-activenum);
2031  }
2032  }
2033  return(activenum);
2034 }
2035 
2037 {
2038  S_THREAD_PARAM_REACTIVATE_LINADD* params = (S_THREAD_PARAM_REACTIVATE_LINADD*) p;
2039 
2040  CKernel* k = params->kernel;
2041  float64_t* lin = params->lin;
2042  float64_t* last_lin = params->last_lin;
2043  int32_t* active = params->active;
2044  int32_t* docs = params->docs;
2045  int32_t start = params->start;
2046  int32_t end = params->end;
2047 
2048  for (int32_t i=start;i<end;i++)
2049  {
2050  if (!active[i])
2051  lin[i] = last_lin[i]+k->compute_optimized(docs[i]);
2052 
2053  last_lin[i]=lin[i];
2054  }
2055 
2056  return NULL;
2057 }
2058 
2060 {
2061  S_THREAD_PARAM_REACTIVATE_VANILLA* params = (S_THREAD_PARAM_REACTIVATE_VANILLA*) p;
2062  ASSERT(params);
2063  ASSERT(params->kernel);
2064  ASSERT(params->lin);
2065  ASSERT(params->aicache);
2066  ASSERT(params->a);
2067  ASSERT(params->a_old);
2068  ASSERT(params->changed2dnum);
2069  ASSERT(params->inactive2dnum);
2070  ASSERT(params->label);
2071 
2072  CKernel* k = params->kernel;
2073  float64_t* lin = params->lin;
2074  float64_t* aicache = params->aicache;
2075  float64_t* a= params->a;
2076  float64_t* a_old = params->a_old;
2077  int32_t* changed2dnum = params->changed2dnum;
2078  int32_t* inactive2dnum = params->inactive2dnum;
2079  int32_t* label = params->label;
2080  int32_t start = params->start;
2081  int32_t end = params->end;
2082 
2083  for (int32_t ii=start;ii<end;ii++)
2084  {
2085  int32_t i=changed2dnum[ii];
2086  int32_t j=0;
2087  ASSERT(i>=0);
2088 
2089  k->get_kernel_row(i,inactive2dnum,aicache);
2090  for (int32_t jj=0;(j=inactive2dnum[jj])>=0;jj++)
2091  lin[j]+=(a[i]-a_old[i])*aicache[j]*(float64_t)label[i];
2092  }
2093  return NULL;
2094 }
2095 
2097  int32_t* label, float64_t *a, SHRINK_STATE *shrink_state, float64_t *lin,
2098  float64_t *c, int32_t totdoc, int32_t iteration, int32_t *inconsistent,
2099  int32_t* docs, float64_t *aicache, float64_t *maxdiff)
2100  /* Make all variables active again which had been removed by
2101  shrinking. */
2102  /* Computes lin for those variables from scratch. */
2103 {
2104  register int32_t i,j,ii,jj,t,*changed2dnum,*inactive2dnum;
2105  int32_t *changed,*inactive;
2106  register float64_t *a_old,dist;
2107  float64_t ex_c,target;
2108 
2109  if (kernel->has_property(KP_LINADD) && get_linadd_enabled()) { /* special linear case */
2110  a_old=shrink_state->last_a;
2111 
2113  {
2114  SG_DEBUG( " clear normal - linadd\n");
2115  kernel->clear_normal();
2116 
2117  int32_t num_modified=0;
2118  for (i=0;i<totdoc;i++) {
2119  if(a[i] != a_old[i]) {
2120  kernel->add_to_normal(docs[i], ((a[i]-a_old[i])*(float64_t)label[i]));
2121  a_old[i]=a[i];
2122  num_modified++;
2123  }
2124  }
2125 
2126  if (num_modified>0)
2127  {
2128  int32_t num_threads=parallel->get_num_threads();
2129  ASSERT(num_threads>0);
2130  if (num_threads < 2)
2131  {
2132  S_THREAD_PARAM_REACTIVATE_LINADD params;
2133  params.kernel=kernel;
2134  params.lin=lin;
2135  params.last_lin=shrink_state->last_lin;
2136  params.docs=docs;
2137  params.active=shrink_state->active;
2138  params.start=0;
2139  params.end=totdoc;
2141  }
2142 #ifdef HAVE_PTHREAD
2143  else
2144  {
2145  pthread_t* threads = SG_MALLOC(pthread_t, num_threads-1);
2146  S_THREAD_PARAM_REACTIVATE_LINADD* params = SG_MALLOC(S_THREAD_PARAM_REACTIVATE_LINADD, num_threads);
2147  int32_t step= totdoc/num_threads;
2148 
2149  for (t=0; t<num_threads-1; t++)
2150  {
2151  params[t].kernel=kernel;
2152  params[t].lin=lin;
2153  params[t].last_lin=shrink_state->last_lin;
2154  params[t].docs=docs;
2155  params[t].active=shrink_state->active;
2156  params[t].start = t*step;
2157  params[t].end = (t+1)*step;
2158  pthread_create(&threads[t], NULL, CSVMLight::reactivate_inactive_examples_linadd_helper, (void*)&params[t]);
2159  }
2160 
2161  params[t].kernel=kernel;
2162  params[t].lin=lin;
2163  params[t].last_lin=shrink_state->last_lin;
2164  params[t].docs=docs;
2165  params[t].active=shrink_state->active;
2166  params[t].start = t*step;
2167  params[t].end = totdoc;
2168  reactivate_inactive_examples_linadd_helper((void*) &params[t]);
2169 
2170  for (t=0; t<num_threads-1; t++)
2171  pthread_join(threads[t], NULL);
2172 
2173  SG_FREE(threads);
2174  SG_FREE(params);
2175  }
2176 #endif
2177 
2178  }
2179  }
2180  else
2181  {
2182  float64_t *alphas = SG_MALLOC(float64_t, totdoc);
2183  int32_t *idx = SG_MALLOC(int32_t, totdoc);
2184  int32_t num_suppvec=0 ;
2185 
2186  for (i=0; i<totdoc; i++)
2187  {
2188  if(a[i] != a_old[i])
2189  {
2190  alphas[num_suppvec] = (a[i]-a_old[i])*(float64_t)label[i];
2191  idx[num_suppvec] = i ;
2192  a_old[i] = a[i] ;
2193  num_suppvec++ ;
2194  }
2195  }
2196 
2197  if (num_suppvec>0)
2198  {
2199  int32_t num_inactive=0;
2200  int32_t* inactive_idx=SG_MALLOC(int32_t, totdoc); // infact we only need a subset
2201 
2202  j=0;
2203  for (i=0;i<totdoc;i++)
2204  {
2205  if(!shrink_state->active[i])
2206  {
2207  inactive_idx[j++] = i;
2208  num_inactive++;
2209  }
2210  }
2211 
2212  if (num_inactive>0)
2213  {
2214  float64_t* dest = SG_MALLOC(float64_t, num_inactive);
2215  memset(dest, 0, sizeof(float64_t)*num_inactive);
2216 
2217  kernel->compute_batch(num_inactive, inactive_idx, dest, num_suppvec, idx, alphas);
2218 
2219  j=0;
2220  for (i=0;i<totdoc;i++) {
2221  if(!shrink_state->active[i]) {
2222  lin[i] = shrink_state->last_lin[i] + dest[j++] ;
2223  }
2224  shrink_state->last_lin[i]=lin[i];
2225  }
2226 
2227  SG_FREE(dest);
2228  }
2229  else
2230  {
2231  for (i=0;i<totdoc;i++)
2232  shrink_state->last_lin[i]=lin[i];
2233  }
2234  SG_FREE(inactive_idx);
2235  }
2236  SG_FREE(alphas);
2237  SG_FREE(idx);
2238  }
2239 
2241  }
2242  else
2243  {
2244  changed=SG_MALLOC(int32_t, totdoc);
2245  changed2dnum=SG_MALLOC(int32_t, totdoc+11);
2246  inactive=SG_MALLOC(int32_t, totdoc);
2247  inactive2dnum=SG_MALLOC(int32_t, totdoc+11);
2248  for (t=shrink_state->deactnum-1;(t>=0) && shrink_state->a_history[t];t--)
2249  {
2250  if(verbosity>=2) {
2251  SG_INFO( "%ld..",t);
2252  }
2253  a_old=shrink_state->a_history[t];
2254  for (i=0;i<totdoc;i++) {
2255  inactive[i]=((!shrink_state->active[i])
2256  && (shrink_state->inactive_since[i] == t));
2257  changed[i]= (a[i] != a_old[i]);
2258  }
2259  compute_index(inactive,totdoc,inactive2dnum);
2260  compute_index(changed,totdoc,changed2dnum);
2261 
2262 
2263  //TODO: PUT THIS BACK IN!!!!!!!! int32_t num_threads=parallel->get_num_threads();
2264  int32_t num_threads=1;
2265  ASSERT(num_threads>0);
2266 
2267  if (num_threads < 2)
2268  {
2269  for (ii=0;(i=changed2dnum[ii])>=0;ii++) {
2270  kernel->get_kernel_row(i,inactive2dnum,aicache);
2271  for (jj=0;(j=inactive2dnum[jj])>=0;jj++)
2272  lin[j]+=(a[i]-a_old[i])*aicache[j]*(float64_t)label[i];
2273  }
2274  }
2275 #ifdef HAVE_PTHREAD
2276  else
2277  {
2278  //find number of the changed ones
2279  int32_t num_changed=0;
2280  for (ii=0;changed2dnum[ii]>=0;ii++)
2281  num_changed++;
2282 
2283  if (num_changed>0)
2284  {
2285  pthread_t* threads= SG_MALLOC(pthread_t, num_threads-1);
2286  S_THREAD_PARAM_REACTIVATE_VANILLA* params = SG_MALLOC(S_THREAD_PARAM_REACTIVATE_VANILLA, num_threads);
2287  int32_t step= num_changed/num_threads;
2288 
2289  // alloc num_threads many tmp buffers
2290  float64_t* tmp_lin=SG_MALLOC(float64_t, totdoc*num_threads);
2291  memset(tmp_lin, 0, sizeof(float64_t)*((size_t) totdoc)*num_threads);
2292  float64_t* tmp_aicache=SG_MALLOC(float64_t, totdoc*num_threads);
2293  memset(tmp_aicache, 0, sizeof(float64_t)*((size_t) totdoc)*num_threads);
2294 
2295  int32_t thr;
2296  for (thr=0; thr<num_threads-1; thr++)
2297  {
2298  params[thr].kernel=kernel;
2299  params[thr].lin=&tmp_lin[thr*totdoc];
2300  params[thr].aicache=&tmp_aicache[thr*totdoc];
2301  params[thr].a=a;
2302  params[thr].a_old=a_old;
2303  params[thr].changed2dnum=changed2dnum;
2304  params[thr].inactive2dnum=inactive2dnum;
2305  params[thr].label=label;
2306  params[thr].start = thr*step;
2307  params[thr].end = (thr+1)*step;
2308  pthread_create(&threads[thr], NULL, CSVMLight::reactivate_inactive_examples_vanilla_helper, (void*)&params[thr]);
2309  }
2310 
2311  params[thr].kernel=kernel;
2312  params[thr].lin=&tmp_lin[thr*totdoc];
2313  params[thr].aicache=&tmp_aicache[thr*totdoc];
2314  params[thr].a=a;
2315  params[thr].a_old=a_old;
2316  params[thr].changed2dnum=changed2dnum;
2317  params[thr].inactive2dnum=inactive2dnum;
2318  params[thr].label=label;
2319  params[thr].start = thr*step;
2320  params[thr].end = num_changed;
2321  reactivate_inactive_examples_vanilla_helper((void*) &params[thr]);
2322 
2323  for (jj=0;(j=inactive2dnum[jj])>=0;jj++)
2324  lin[j]+=tmp_lin[totdoc*thr+j];
2325 
2326  for (thr=0; thr<num_threads-1; thr++)
2327  {
2328  pthread_join(threads[thr], NULL);
2329 
2330  //add up results
2331  for (jj=0;(j=inactive2dnum[jj])>=0;jj++)
2332  lin[j]+=tmp_lin[totdoc*thr+j];
2333  }
2334 
2335  SG_FREE(tmp_lin);
2336  SG_FREE(tmp_aicache);
2337  SG_FREE(threads);
2338  SG_FREE(params);
2339  }
2340  }
2341 #endif
2342  }
2343  SG_FREE(changed);
2344  SG_FREE(changed2dnum);
2345  SG_FREE(inactive);
2346  SG_FREE(inactive2dnum);
2347  }
2348 
2349  (*maxdiff)=0;
2350  for (i=0;i<totdoc;i++) {
2351  shrink_state->inactive_since[i]=shrink_state->deactnum-1;
2352  if(!inconsistent[i]) {
2353  dist=(lin[i]-model->b)*(float64_t)label[i];
2354  target=-(learn_parm->eps[i]-(float64_t)label[i]*c[i]);
2355  ex_c=learn_parm->svm_cost[i]-learn_parm->epsilon_a;
2356  if((a[i]>learn_parm->epsilon_a) && (dist > target)) {
2357  if((dist-target)>(*maxdiff)) /* largest violation */
2358  (*maxdiff)=dist-target;
2359  }
2360  else if((a[i]<ex_c) && (dist < target)) {
2361  if((target-dist)>(*maxdiff)) /* largest violation */
2362  (*maxdiff)=target-dist;
2363  }
2364  if((a[i]>(0+learn_parm->epsilon_a))
2365  && (a[i]<ex_c)) {
2366  shrink_state->active[i]=1; /* not at bound */
2367  }
2368  else if((a[i]<=(0+learn_parm->epsilon_a)) && (dist < (target+learn_parm->epsilon_shrink))) {
2369  shrink_state->active[i]=1;
2370  }
2371  else if((a[i]>=ex_c)
2372  && (dist > (target-learn_parm->epsilon_shrink))) {
2373  shrink_state->active[i]=1;
2374  }
2375  else if(learn_parm->sharedslack) { /* make all active when sharedslack */
2376  shrink_state->active[i]=1;
2377  }
2378  }
2379  }
2380 
2381  if (!(kernel->has_property(KP_LINADD) && get_linadd_enabled())) { /* update history for non-linear */
2382  for (i=0;i<totdoc;i++) {
2383  (shrink_state->a_history[shrink_state->deactnum-1])[i]=a[i];
2384  }
2385  for (t=shrink_state->deactnum-2;(t>=0) && shrink_state->a_history[t];t--) {
2386  SG_FREE(shrink_state->a_history[t]);
2387  shrink_state->a_history[t]=0;
2388  }
2389  }
2390 }
2391 
2392 
2393 
2394 /* start the optimizer and return the optimal values */
2396  QP *qp, float64_t *epsilon_crit, int32_t nx, float64_t *threshold,
2397  int32_t& svm_maxqpsize)
2398 {
2399  register int32_t i, j, result;
2400  float64_t margin, obj_before, obj_after;
2401  float64_t sigdig, dist, epsilon_loqo;
2402  int32_t iter;
2403 
2404  if(!primal) { /* allocate memory at first call */
2405  primal=SG_MALLOC(float64_t, nx*3);
2406  dual=SG_MALLOC(float64_t, nx*2+1);
2407  }
2408 
2409  obj_before=0; /* calculate objective before optimization */
2410  for(i=0;i<qp->opt_n;i++) {
2411  obj_before+=(qp->opt_g0[i]*qp->opt_xinit[i]);
2412  obj_before+=(0.5*qp->opt_xinit[i]*qp->opt_xinit[i]*qp->opt_g[i*qp->opt_n+i]);
2413  for(j=0;j<i;j++) {
2414  obj_before+=(qp->opt_xinit[j]*qp->opt_xinit[i]*qp->opt_g[j*qp->opt_n+i]);
2415  }
2416  }
2417 
2418  result=STILL_RUNNING;
2419  qp->opt_ce0[0]*=(-1.0);
2420  /* Run pr_loqo. If a run fails, try again with parameters which lead */
2421  /* to a slower, but more robust setting. */
2422  for(margin=init_margin,iter=init_iter;
2423  (margin<=0.9999999) && (result!=OPTIMAL_SOLUTION);) {
2424 
2426  sigdig=-log10(opt_precision);
2427 
2428  result=pr_loqo((int32_t)qp->opt_n,(int32_t)qp->opt_m,
2429  (float64_t *)qp->opt_g0,(float64_t *)qp->opt_g,
2430  (float64_t *)qp->opt_ce,(float64_t *)qp->opt_ce0,
2431  (float64_t *)qp->opt_low,(float64_t *)qp->opt_up,
2433  (int32_t)(verbosity-2),
2434  (float64_t)sigdig,(int32_t)iter,
2435  (float64_t)margin,(float64_t)(qp->opt_up[0])/4.0,(int32_t)0);
2436 
2437  if(CMath::is_nan(dual[0])) { /* check for choldc problem */
2438  if(verbosity>=2) {
2439  SG_SDEBUG("Restarting PR_LOQO with more conservative parameters.\n");
2440  }
2441  if(init_margin<0.80) { /* become more conservative in general */
2442  init_margin=(4.0*margin+1.0)/5.0;
2443  }
2444  margin=(margin+1.0)/2.0;
2445  (opt_precision)*=10.0; /* reduce precision */
2446  if(verbosity>=2) {
2447  SG_SDEBUG("Reducing precision of PR_LOQO.\n");
2448  }
2449  }
2450  else if(result!=OPTIMAL_SOLUTION) {
2451  iter+=2000;
2452  init_iter+=10;
2453  (opt_precision)*=10.0; /* reduce precision */
2454  if(verbosity>=2) {
2455  SG_SDEBUG("Reducing precision of PR_LOQO due to (%ld).\n",result);
2456  }
2457  }
2458  }
2459 
2460  if(qp->opt_m) /* Thanks to Alex Smola for this hint */
2461  model_b=dual[0];
2462  else
2463  model_b=0;
2464 
2465  /* Check the precision of the alphas. If results of current optimization */
2466  /* violate KT-Conditions, relax the epsilon on the bounds on alphas. */
2467  epsilon_loqo=1E-10;
2468  for(i=0;i<qp->opt_n;i++) {
2469  dist=-model_b*qp->opt_ce[i];
2470  dist+=(qp->opt_g0[i]+1.0);
2471  for(j=0;j<i;j++) {
2472  dist+=(primal[j]*qp->opt_g[j*qp->opt_n+i]);
2473  }
2474  for(j=i;j<qp->opt_n;j++) {
2475  dist+=(primal[j]*qp->opt_g[i*qp->opt_n+j]);
2476  }
2477  /* SG_SDEBUG("LOQO: a[%d]=%f, dist=%f, b=%f\n",i,primal[i],dist,dual[0]); */
2478  if((primal[i]<(qp->opt_up[i]-epsilon_loqo)) && (dist < (1.0-(*epsilon_crit)))) {
2479  epsilon_loqo=(qp->opt_up[i]-primal[i])*2.0;
2480  }
2481  else if((primal[i]>(0+epsilon_loqo)) && (dist > (1.0+(*epsilon_crit)))) {
2482  epsilon_loqo=primal[i]*2.0;
2483  }
2484  }
2485 
2486  for(i=0;i<qp->opt_n;i++) { /* clip alphas to bounds */
2487  if(primal[i]<=(0+epsilon_loqo)) {
2488  primal[i]=0;
2489  }
2490  else if(primal[i]>=(qp->opt_up[i]-epsilon_loqo)) {
2491  primal[i]=qp->opt_up[i];
2492  }
2493  }
2494 
2495  obj_after=0; /* calculate objective after optimization */
2496  for(i=0;i<qp->opt_n;i++) {
2497  obj_after+=(qp->opt_g0[i]*primal[i]);
2498  obj_after+=(0.5*primal[i]*primal[i]*qp->opt_g[i*qp->opt_n+i]);
2499  for(j=0;j<i;j++) {
2500  obj_after+=(primal[j]*primal[i]*qp->opt_g[j*qp->opt_n+i]);
2501  }
2502  }
2503 
2504  /* if optimizer returned NAN values, reset and retry with smaller */
2505  /* working set. */
2506  if(CMath::is_nan(obj_after) || CMath::is_nan(model_b)) {
2507  for(i=0;i<qp->opt_n;i++) {
2508  primal[i]=qp->opt_xinit[i];
2509  }
2510  model_b=0;
2511  if(svm_maxqpsize>2) {
2512  svm_maxqpsize--; /* decrease size of qp-subproblems */
2513  }
2514  }
2515 
2516  if(obj_after >= obj_before) { /* check whether there was progress */
2517  (opt_precision)/=100.0;
2519  if(verbosity>=2) {
2520  SG_SDEBUG("Increasing Precision of PR_LOQO.\n");
2521  }
2522  }
2523 
2524  // TODO: add parameter for this (e.g. for MTL experiments)
2525  if(precision_violations > 5000) {
2526  (*epsilon_crit)*=10.0;
2528  SG_SINFO("Relaxing epsilon on KT-Conditions.\n");
2529  }
2530 
2531  (*threshold)=model_b;
2532 
2533  if(result!=OPTIMAL_SOLUTION) {
2534  SG_SERROR("PR_LOQO did not converge.\n");
2535  return(qp->opt_xinit);
2536  }
2537  else {
2538  return(primal);
2539  }
2540 }
2541 
2542 
2543 #endif //USE_SVMLIGHT

SHOGUN Machine Learning Toolbox - Documentation