KSquare Utilities
svm.cpp
Go to the documentation of this file.
1 #include "FirstIncludes.h"
2 
3 #include <math.h>
4 #include <stdio.h>
5 #include <ctype.h>
6 #include <float.h>
7 #include <string.h>
8 #include <string>
9 #include <stdarg.h>
10 #include <vector>
11 #include <assert.h>
12 #include <iostream>
13 
14 
15 #include "MemoryDebug.h"
16 using namespace std;
17 
18 
19 #include "GlobalGoalKeeper.h"
20 #include "KKBaseTypes.h"
21 #include "KKException.h"
22 #include "KKStrParser.h"
23 #include "OSservices.h"
24 using namespace KKB;
25 
26 
27 #include "KKMLLTypes.h"
28 using namespace KKMLL;
29 
30 #pragma warning(disable : 4996)
31 
32 
33 
34 
35 #include "svm.h"
36 
37 
38 // Forward defining several functions.
39 namespace SVM233
40 {
41 
43 {
44  margin = NULL;
45  featureWeight = NULL;
46  SVIndex = NULL;
47  nonSVIndex = NULL;
48  label = NULL;
49  nSV = NULL;
50  SV = NULL;
51  sv_coef = NULL;
52  rho = NULL;
53  kValueTable = NULL;
54  nr_class = -1;
55  l = -1;
56  numNonSV = -1;
57  weight = -1;
58  dim = -1;
59  valid = true;
60  weOwnXspace = false;
61 }
62 
63 
65 {
66  Dispose ();
67 }
68 
69 
71 {
72  kkint32 memoryConsumedEstimated = sizeof (SvmModel233)
73  + param.MemoryConsumedEstimated ()
74  + (kkint32)exampleNames.size () * 40;
75 
76  if (SV) memoryConsumedEstimated += sizeof (svm_node*) * l;
77  if (sv_coef) memoryConsumedEstimated += (nr_class - 1) * sizeof (double*) + l * (nr_class - 1) * sizeof (double);
78  if (rho) memoryConsumedEstimated += l * sizeof (double);
79  if (label) memoryConsumedEstimated += nr_class * sizeof (kkint32);
80  if (nSV) memoryConsumedEstimated += nr_class * sizeof (kkint32);
81  if (featureWeight) memoryConsumedEstimated += dim * sizeof (double);
82  if (kValueTable) memoryConsumedEstimated += sizeof (double) * l;
83  if ((xSpace != NULL) && weOwnXspace)
84  memoryConsumedEstimated += sizeof (svm_node) * l;
85 
86  return memoryConsumedEstimated;
87 }
88 
89 
90 
91 
92 void SvmModel233::Dispose ()
93 {
94  if (weOwnXspace)
95  {
96  delete xSpace;
97  xSpace = NULL;
98  }
99 
100  if (sv_coef)
101  {
102  for (kkint32 i = 0; i < (nr_class - 1); i++)
103  {
104  free (sv_coef[i]);
105  sv_coef[i] = NULL;
106  }
107  }
108 
109  free (SV); SV = NULL;
110  free (sv_coef); sv_coef = NULL;
111  free (rho); rho = NULL;
112  free (label); label = NULL;
113  free (nSV); nSV = NULL;
114 
115  //luo add
116  if (dim > 0 )
117  {
118  delete[] (featureWeight);
119  featureWeight = NULL;
120  }
121 
122  free (SVIndex); SVIndex = NULL;
123  free (nonSVIndex); nonSVIndex = NULL;
124  delete[] margin; margin = NULL;
125 
126  if (kValueTable)
127  {
128  delete[] kValueTable; kValueTable = NULL;
129  }
130 }
131 
132 
133 
135 {
136  if (svIDX < (kkint32)exampleNames.size ())
137  return exampleNames[svIDX];
138  else
139  return "SV" + StrFormatInt (svIDX, "ZZZ#");
140 }
141 
142 
143 
144 void SvmModel233::WriteXML (const KKStr& varName,
145  ostream& o
146  ) const
147 {
148  XmlTag startTag ("SvmModel233", XmlTag::TagTypes::tagStart);
149  if (!varName.Empty ())
150  startTag.AddAtribute ("VarName", varName);
151  startTag.WriteXML (o);
152  o << endl;
153 
154  kkint32 numberOfBinaryClassifiers = nr_class * (nr_class - 1) / 2;
155 
156  kkint32 origPrecision = (kkint32)o.precision ();
157  o.precision (14);
158 
160 
161  XmlElementInt32::WriteXML (nr_class, "nr_class", o);
162 
163  kkint32 totalNumSVs = l;
164 
165  XmlElementInt32::WriteXML (totalNumSVs, "totalNumSVs", o);
166 
167  XmlElementArrayDouble::WriteXML (numberOfBinaryClassifiers, rho, "rho", o);
168 
169  if (margin)
170  {
171  kkint32 oldPrecision = (kkint32)o.precision ();
172  o.precision (9);
173  XmlElementArrayDouble::WriteXML (numberOfBinaryClassifiers, margin, "margin", o);
174  o.precision (oldPrecision);
175  }
176 
177  if (label)
178  XmlElementArrayInt32::WriteXML (nr_class, label, "label", o);
179 
180  if (nSV)
181  XmlElementArrayInt32::WriteXML (nr_class, nSV, "nSV", o);
182 
183  {
184  // Determine total number of elements
185  kkint32 totalNumOfElements = 0;
186  for (kkint32 i = 0; i < totalNumSVs; i++)
187  {
188  const svm_node *p = SV[i];
189  while (p->index != -1)
190  {
191  totalNumOfElements++;
192  p++;
193  }
194 
195  totalNumOfElements++; // Add one for terminating node
196  }
197 
198  XmlElementInt32::WriteXML (totalNumOfElements, "totalNumOfElements", o);
199  }
200 
201  // The Support Vector Information will be written in the Contents portion of SvmModel233
202  for (kkint32 i = 0; i < totalNumSVs; i++)
203  {
204  if ((kkint32)exampleNames.size () > i)
205  o << "SuportVectorNamed" << "\t" << exampleNames[i];
206  else
207  o << "SuportVector";
208 
209  o.precision (16);
210  for (kkint32 j = 0; j < nr_class - 1; j++)
211  o << "\t" << sv_coef[j][i];
212 
213  const svm_node *p = SV[i];
214  while (p->index != -1)
215  {
216  o << "\t" << p->index << ":" << p->value;
217  p++;
218  }
219 
220  o << endl;
221  }
222 
223  o.precision (origPrecision);
224 
225  XmlTag endTag ("SvmModel233", XmlTag::TagTypes::tagEnd);
226  endTag.WriteXML (o);
227  o << endl;
228 } /* WriteXML */
229 
230 
231 
232 
233 
235  XmlTagConstPtr tag,
236  VolConstBool& cancelFlag,
237  RunLog& log
238  )
239 {
240  exampleNames.clear ();
241  kkint32 numberOfBinaryClassifiers = 0;
242  kkint32 numElementsLoaded = 0;
243  kkint32 totalNumSVs = 0;
244  kkint32 totalNumOfElements = 0;
245  kkint32 numSVsLoaded = 0;
246  delete rho; rho = NULL;
247  delete margin; margin = NULL;
248  delete nSV; nSV = NULL;
249  delete label; label = NULL;
250  delete SV; SV = NULL;
251 
252  bool errorsFound = false;
253  valid = true;
254 
255  XmlTokenPtr t = NULL;
256  while ((!errorsFound) && (!cancelFlag))
257  {
258  if (t != NULL)
259  {
260  if (typeid (*t) == typeid (XmlContent))
261  {
262  XmlContentPtr cp = dynamic_cast<XmlContentPtr> (t);
263  delete cp; cp = NULL; t = NULL;
264  }
265  else
266  {
267  delete t;
268  }
269  }
270 
271  t = s.GetNextToken (cancelFlag, log);
272  if (cancelFlag)
273  {
274  delete t;
275  t = NULL;
276  }
277  if (!t) break;
278 
280  {
281  XmlElementPtr e = dynamic_cast<XmlElementPtr> (t);
282  const KKStr& varName = e->VarName ();
283  const KKStr& sectionName = e->SectionName ();
284 
285  if (varName.EqualIgnoreCase ("Param") && (typeid (*e) == typeid (XmlElementKKStr)))
286  {
287  param.ParseTabDelStr (*(dynamic_cast<XmlElementKKStrPtr> (e)->Value ()));
288  }
289 
290  else if (varName.EqualIgnoreCase ("nr_class"))
291  {
292  nr_class = e->ToInt32 ();
293  numberOfBinaryClassifiers = nr_class * (nr_class - 1) / 2;
294  }
295 
296  else if (varName.EqualIgnoreCase ("totalNumSVs"))
297  {
298  totalNumSVs = e->ToInt32 ();
299  l = totalNumSVs;
300  }
301 
302  else if (varName.EqualIgnoreCase ("rho") && (typeid (*e) == typeid (XmlElementArrayDouble)))
303  {
304  delete rho; rho = NULL;
305  XmlElementArrayDoublePtr rhoArray = dynamic_cast<XmlElementArrayDoublePtr> (e);
306  if (rhoArray->Count () != numberOfBinaryClassifiers)
307  {
308  log.Level (-1) << endl
309  << "SvmModel233::ReadXML ***ERROR*** 'rho' array incorrect length: expected: "
310  << numberOfBinaryClassifiers << " found: " << rhoArray->Count () << " elements"
311  << endl <<endl;
312  errorsFound = true;
313  }
314  else
315  {
316  rho = rhoArray->TakeOwnership ();
317  }
318  }
319 
320  else if (varName.EqualIgnoreCase ("margin") && (typeid (*e) == typeid (XmlElementArrayDouble)))
321  {
322  delete margin; margin = NULL;
323  XmlElementArrayDoublePtr marginArray = dynamic_cast<XmlElementArrayDoublePtr> (e);
324  if (marginArray->Count () != numberOfBinaryClassifiers)
325  {
326  log.Level (-1) << endl
327  << "SvmModel233::ReadXML ***ERROR*** 'margin' array incorrect length: expected: "
328  << numberOfBinaryClassifiers << " found: " << marginArray->Count () << " elements"
329  << endl <<endl;
330  errorsFound = true;
331  }
332  else
333  {
334  margin = marginArray->TakeOwnership ();
335  }
336  }
337 
338  else if (varName.EqualIgnoreCase ("label") && (typeid (*e) == typeid (XmlElementArrayInt32)))
339  {
340  delete label; label = NULL;
341  XmlElementArrayInt32Ptr labelArray = dynamic_cast<XmlElementArrayInt32Ptr> (e);
342  if (labelArray->Count () != nr_class)
343  {
344  log.Level (-1) << endl
345  << "SvmModel233::ReadXML ***ERROR*** 'label' array incorrect length: expected: "
346  << nr_class << " found: " << labelArray->Count () << " elements"
347  << endl <<endl;
348  errorsFound = true;
349  }
350  else
351  {
352  label = labelArray->TakeOwnership ();
353  }
354  }
355 
356  else if (varName.EqualIgnoreCase ("nSV") && (typeid (*e) == typeid (XmlElementArrayInt32)))
357  {
358  delete nSV; nSV = NULL;
359  XmlElementArrayInt32Ptr nSVArray = dynamic_cast<XmlElementArrayInt32Ptr> (e);
360  if (nSVArray->Count () != nr_class)
361  {
362  log.Level (-1) << endl
363  << "SvmModel233::ReadXML ***ERROR*** 'nSV' array incorrect length: expected: "
364  << nr_class << " found: " << nSVArray->Count () << " elements"
365  << endl <<endl;
366  errorsFound = true;
367  }
368  else
369  {
370  nSV = nSVArray->TakeOwnership ();
371  }
372  }
373 
374  else if (varName.EqualIgnoreCase ("totalNumOfElements"))
375  {
376  totalNumOfElements = e->ToInt32 ();
377  if (totalNumOfElements < 1)
378  {
379  log.Level (-1) << endl
380  << "SvmModel233::ReadXML ***ERROR*** Invalid totalNumOfElements: " << totalNumOfElements << endl
381  << endl;
382  errorsFound = true;
383  }
384  else
385  {
386  kkint32 m = nr_class - 1;
387  // kint32 l = model->l;
388 
389  delete sv_coef;
390  sv_coef = new double*[l];
391  for (kkint32 i = 0; i < m; i++)
392  sv_coef[i] = new double[l];
393 
394  SV = new svm_node*[l];
395  xSpace = new svm_node[totalNumOfElements];
396  weOwnXspace = true;
397  }
398  }
399  }
400  else if (typeid (*t) == typeid (XmlContent))
401  {
402  XmlContentPtr content = dynamic_cast<XmlContentPtr> (t);
403  KKStrParser p (*(content->Content ()));
404  p.TrimWhiteSpace (" ");
405 
406  KKStr lineName = p.GetNextToken ("\t");
407  if (!lineName.EqualIgnoreCase ("SuportVectorNamed") && !lineName.EqualIgnoreCase ("SuportVector"))
408  {
409  log.Level (-1) << endl
410  << "SvmModel233::ReadXML ***ERROR*** Invalid Content: " << lineName << endl
411  << endl;
412  errorsFound = true;
413  }
414 
415  else if (numSVsLoaded >= totalNumSVs)
416  {
417  log.Level (-1) << "SvmModel233::ReadXML ***ERROR*** Exceeding expected number of Support Vectors." << endl;
418  }
419 
420  if (!SV)
421  {
422  log.Level (-1) << endl << "SvmModel233::ReadXML ***ERROR*** 'SV' was no defined LineNum:" << lineName << endl << endl;
423  errorsFound = true;
424  }
425 
426  if (!errorsFound)
427  {
428  if (lineName.EqualIgnoreCase ("SuportVectorNamed"))
429  {
430  exampleNames.push_back (p.GetNextToken ("\t"));
431  }
432 
433  for (kkint32 j = 0; j < nr_class - 1; j++)
434  sv_coef[j][numSVsLoaded] = p.GetNextTokenDouble ("\t");
435 
436  SV[numSVsLoaded] = &(xSpace[numElementsLoaded]);
437 
438  while ((p.MoreTokens ()) && (numElementsLoaded < (totalNumOfElements - 1)))
439  {
440  xSpace[numElementsLoaded].index = p.GetNextTokenInt (":");
441  xSpace[numElementsLoaded].value = p.GetNextTokenDouble ("\t");
442  numElementsLoaded++;
443  }
444 
445  if (numElementsLoaded >= totalNumOfElements)
446  {
447  log.Level (-1) << endl
448  << "SvmModel233::ReadXML ***ERROR*** 'numElementsLoaded' is greater than what was defined by 'totalNumOfElements'." << endl
449  << endl;
450  errorsFound = true;
451  }
452  else
453  {
454  xSpace[numElementsLoaded].index = -1;
455  xSpace[numElementsLoaded].value = 0.0;
456  numElementsLoaded++;
457  numSVsLoaded++;
458  }
459  }
460  }
461  else
462  {
463  log.Level (-1) << endl
464  << "SvmModel233::ReadXML ***ERROR*** Unexpected Token[" << t->SectionName () << " " << t->VarName () << "]" << endl
465  << endl;
466  errorsFound = true;
467  }
468 
469  delete t;
470  t = NULL;
471  }
472 
473  if (!errorsFound)
474  {
475  if (numSVsLoaded != totalNumSVs)
476  {
477  log.Level (-1) << endl
478  << "SvmModel233::ReadXML ***ERROR*** numSVsLoaded[" << numSVsLoaded << "] does not match totalNumSVs[" << totalNumSVs << "]." << endl
479  << endl;
480  errorsFound= true;
481  }
482 
483  else
484  {
485  delete kValueTable;
486  kValueTable = new double[l];
487  }
488  }
489 
490  valid = (!errorsFound) && (!cancelFlag);
491 } /* ReadXML */
492 
493 
494 
495 XmlFactoryMacro(SvmModel233)
496 
497 
498 
499 
500 
501 
502  // Generalized SMO+SVMlight algorithm
503  // Solves:
504  //
505  // min 0.5(\alpha^T Q \alpha) + b^T \alpha
506  //
507  // y^T \alpha = \delta
508  // y_i = +1 or -1
509  // 0 <= alpha_i <= Cp for y_i = 1
510  // 0 <= alpha_i <= Cn for y_i = -1
511  //
512  // Given:
513  //
514  // Q, b, y, Cp, Cn, and an initial feasible point \alpha
515  // l is the size of vectors and matrices
516  // eps is the stopping criterion
517  //
518  // solution will be put in \alpha, objective value will be put in obj
519  //
520 
521  typedef float Qfloat;
522  typedef signed char schar;
523 
524  class Cache;
525  class Kernel;
526  class Solver;
527  class Solver_NU;
528  class SVC_Q;
529  class ONE_CLASS_Q;
530  class SVR_Q;
531 
532  class Solver
533  {
534  public:
535  Solver() {};
536  virtual ~Solver() {};
537 
538  struct SolutionInfo {
539  double obj;
540  double rho;
543  double r; // for Solver_NU
544  };
545 
546  void Solve(kkint32 l,
547  const Kernel& Q,
548  const double* b_,
549  const schar* y_,
550  double* alpha_,
551  double Cp,
552  double Cn,
553  double eps,
554  SolutionInfo* si,
555  kkint32 shrinking
556  );
557 
558  void Solve (kkint32 l,
559  const Kernel& Q,
560  const double* b_,
561  const schar* y_,
562  double* alpha_,
563  double* C_,
564  double eps,
565  SolutionInfo* si,
566  kkint32 shrinking
567  );
568 
569  protected:
572  double* G; // gradient of objective function
574  char* alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE
575  double* alpha;
576  const Kernel* Q;
577  double eps;
578  double* C;
579  double* b;
581  double* G_bar; // gradient, if we treat free variables as 0
583  bool unshrinked; // XXX
584 
585  double get_C(kkint32 i)
586  {
587  return C[i];
588  }
590  {
591  if (alpha[i] >= get_C (i))
593 
594  else if(alpha[i] <= 0)
596 
597  else
598  alpha_status[i] = FREE;
599  }
600 
601  bool is_upper_bound(kkint32 i) { return alpha_status[i] == UPPER_BOUND; }
602  bool is_lower_bound(kkint32 i) { return alpha_status[i] == LOWER_BOUND; }
603  bool is_free(kkint32 i) { return alpha_status[i] == FREE; }
604  void swap_index(kkint32 i, kkint32 j);
605  void reconstruct_gradient();
606  virtual kkint32 select_working_set(kkint32 &i, kkint32 &j);
607  virtual double calculate_rho();
608  virtual void do_shrinking();
609  };
610 
611 
612  static void solve_c_svc (const svm_problem* prob,
613  const svm_parameter* param,
614  double* alpha,
615  Solver::SolutionInfo* si,
616  double Cp,
617  double Cn
618  );
619 
620  static void solve_c_svc (const svm_problem* prob,
621  const svm_parameter* param,
622  double* alpha,
623  Solver::SolutionInfo* si,
624  double* C_
625  );
626 
627 
628 
629  static void solve_nu_svc (const svm_problem* prob,
630  const svm_parameter* param,
631  double* alpha,
632  Solver::SolutionInfo* si
633  );
634 
635 
636  static void solve_one_class (const svm_problem* prob,
637  const svm_parameter* param,
638  double* alpha,
639  Solver::SolutionInfo* si
640  );
641 
642  static void solve_epsilon_svr (const svm_problem* prob,
643  const svm_parameter* param,
644  double* alpha,
645  Solver::SolutionInfo* si
646  );
647 
648  static void solve_nu_svr (const svm_problem* prob,
649  const svm_parameter* param,
650  double* alpha,
651  Solver::SolutionInfo* si
652  );
653 
655  {
656  double *alpha;
657  double rho;
658  };
659 
660 
662  const svm_parameter* param
663  );
664 
666  const svm_parameter* param,
667  double Cp,
668  double Cn,
670  );
671 
672 
673 #ifdef WIN32
674 
675 #ifndef min
676  template <class T> inline T min(T x,T y) { return (x<y)?x:y; }
677 #endif
678 
679 #ifndef max
680  template <class T> inline T max(T x,T y) { return (x>y)?x:y; }
681 #endif
682 
683 #endif
684 
685 
686 
687 template <class T> inline void Swap(T& x, T& y) { T t=x; x=y; y=t; }
688 
689 
690 template <class S, class T> inline void clone(T*& dst, S* src, kkint32 n)
691 {
692  dst = new T[n];
693  KKStr::MemCpy((void *)dst, (void *)src, sizeof(T)*n);
694 }
695 
696 
697 
698 #define INF HUGE_VAL
699 #define Malloc(type,n) (type *)malloc((n)*sizeof(type))
700 
701 #if 0
702  void info(const char *fmt,...)
703  {
704  va_list ap;
705  va_start(ap,fmt);
706  vprintf(fmt,ap);
707  va_end(ap);
708  }
709 
710  void info_flush()
711  {
712  fflush(stdout);
713  }
714 #else
715  void info(const char *fmt,...) {}
716  void info_flush() {}
717 #endif
718 
719 } /* SVM233 */
720 
721 
722 using namespace SVM233;
723 
724 
725 
726 
727 
728 
729 
731  coef0 (0.0),
732  degree (3),
733  gamma (0.0),
734  kernel_type (RBF),
735  svm_type (C_SVC),
736 
737  /* these are for training only */
738  C (1),
739  cache_size (40.0),
740  eps (1e-3),
741  nr_weight (0),
742  nu (0.5),
743  p (0.1),
744  probability (0),
745  shrinking (1),
746  weight (NULL),
747  weight_label (NULL),
748 
749  A (1.0f),
750  boosting (0),
751  cBoost (1.0),
752  confidence (0),
753  dim (0),
754  dimSelect (-1),
755  featureWeight (NULL),
756  hist (0),
757  nr_class (0),
758  numSVM (1),
759  sample (100),
760  sampleSV (0),
761  threshold (0.0f)
762 {
763 }
764 
765 
766 
767 
769  :
770  coef0 (_param.coef0),
771  degree (_param.degree),
772  gamma (_param.gamma),
773  kernel_type (_param.kernel_type),
774  svm_type (_param.svm_type),
775 
776  /* these are for training only */
777  C (_param.C),
778  cache_size (_param.cache_size),
779  eps (_param.eps),
780  nr_weight (_param.nr_weight),
781  nu (_param.nu),
782  p (_param.p),
783  probability (_param.probability),
784  shrinking (_param.shrinking),
785  weight (NULL),
786  weight_label (NULL),
787 
788  A (_param.A),
789  boosting (_param.boosting),
790  cBoost ( _param.cBoost),
791  confidence (_param.confidence),
792  dim (_param.dim),
793  dimSelect (_param.dimSelect),
794  featureWeight (NULL),
795  hist (_param.hist),
796  nr_class (_param.nr_class),
797  numSVM (_param.numSVM),
798  sample (_param.sample),
799  sampleSV (_param.sampleSV),
800  threshold (_param.threshold)
801  {
802  if (_param.weight_label)
803  {
805  for (kkint32 x = 0; x < nr_weight; x++)
806  weight_label[x] = _param.weight_label[x];
807  }
808 
809  if (_param.weight)
810  {
811  weight = new double[nr_weight];
812  for (kkint32 x = 0; x < nr_weight; x++)
813  weight[x] = _param.weight[x];
814  }
815 
816  if (_param.featureWeight)
817  {
818  featureWeight = new double[dim];
819  for (kkint32 x = 0; x < dim; x++)
820  featureWeight[x] = _param.featureWeight[x];
821  }
822 }
823 
824 
825 
826 
827 
829 {
830  coef0 = right.coef0;
831  degree = right.degree;
832  gamma = right.gamma;
833  kernel_type = right.kernel_type;
834  svm_type = right.svm_type;
835 
836  cache_size = right.cache_size;
837  eps = right.eps;
838  C = right.C;
839  nr_weight = right.nr_weight;
840  weight_label = NULL;
841  weight = NULL;
842  nu = right.nu;
843  p = right.p;
844  shrinking = right.shrinking;
845  probability = right.probability;
846  numSVM = right.numSVM;
847  sampleSV = right.sampleSV;
848  hist = right.hist;
849  boosting = right.boosting;
850  cBoost = right.cBoost;
851  dimSelect = right.dimSelect;
852  dim = right.dim;
853  featureWeight = NULL;
854  confidence = right.confidence;
855  A = right.A;
856  nr_class = right.nr_class;
857  threshold = right.threshold;
858  sample = right.sample;
859 
860  if (right.weight_label)
861  {
863  for (kkint32 x = 0; x < nr_weight; x++)
864  weight_label[x] = right.weight_label[x];
865  }
866 
867  if (right.weight)
868  {
869  weight = new double[nr_weight];
870  for (kkint32 x = 0; x < nr_weight; x++)
871  weight[x] = right.weight[x];
872  }
873 
874  if (right.featureWeight)
875  {
876  featureWeight = new double[dim];
877  for (kkint32 x = 0; x < dim; x++)
878  featureWeight[x] = right.featureWeight[x];
879  }
880 
881  return *this;
882 } /* svm_parameter::operator= */
883 
884 
885 
887 {
888  kkint32 memoryConsumedEstimated = sizeof (svm_parameter);
889  if (weight)
890  memoryConsumedEstimated += ((sizeof (double) + sizeof(kkint32)) * nr_weight);
891 
892  if (featureWeight)
893  memoryConsumedEstimated += (sizeof (double) * dim);
894 
895  return memoryConsumedEstimated;
896 }
897 
898 
899 
901  KKStr value,
902  double valueNum,
903  bool& parmUsed
904  )
905 {
906  parmUsed = true;
907 
908  cmd.Upper ();
909 
910  if (cmd == "-A")
911  numSVM = (kkint32)valueNum;
912 
913  else if (cmd == "-C")
914  C = valueNum;
915 
916  else if (cmd == "-D")
917  degree = valueNum;
918 
919  else if (cmd == "-E")
920  eps = valueNum;
921 
922  else if ((cmd == "-G") || (cmd == "-GAMMA"))
923  gamma = valueNum;
924 
925  else if (cmd == "-H")
926  shrinking = (kkint32)valueNum;
927 
928  else if (cmd == "-I")
929  threshold = (float)valueNum;
930 
931  else if (cmd == "-J")
932  hist = (kkint32)valueNum;
933 
934  else if (cmd == "-K")
935  boosting = (kkint32)valueNum;
936 
937  else if (cmd == "-L")
938  cBoost = (float)valueNum;
939 
940  else if (cmd == "-M")
941  cache_size = valueNum;
942 
943  else if (cmd == "-N")
944  nu = valueNum;
945 
946  else if (cmd == "-O")
947  dimSelect = (kkint32)valueNum;
948 
949  else if (cmd == "-P")
950  p = valueNum;
951 
952  else if (cmd == "-Q")
953  confidence = valueNum;
954 
955  else if (cmd == "-R")
956  coef0 = valueNum;
957 
958  else if (cmd == "-S")
959  svm_type = (kkint32)valueNum;
960 
961  else if (cmd == "-T")
962  kernel_type = (kkint32)valueNum;
963 
964  else if (cmd == "-U")
965  A = (float)valueNum;
966 
967  else if (cmd == "-W")
968  {
969  ++nr_weight;
970  weight_label = KKB::kkReallocateArray (weight_label, nr_weight - 1, nr_weight);
971  weight = KKB::kkReallocateArray (weight, nr_weight - 1, nr_weight);
973  weight [nr_weight - 1] = valueNum;
974  }
975 
976  else
977  parmUsed = false;
978 
979 } /* ProcessSvmParameter */
980 
981 
982 
984  coef0 (0.0),
985  degree (3),
986  gamma (0.0),
987  kernel_type (0),
988  svm_type (C_SVC),
989 
990  /* these are for training only */
991  C (1),
992  cache_size (40.0),
993  eps (1e-3),
994  nr_weight (0),
995  nu (0.5),
996  p (0.1),
997  probability (0),
998  shrinking (1),
999  weight (NULL),
1000  weight_label (NULL),
1001 
1002  //luo add
1003  A (1.0),
1004  boosting (0),
1005  cBoost (1.0),
1006  confidence (0),
1007  dim (0),
1008  dimSelect (-1),
1009  featureWeight (NULL),
1010  hist (0),
1011  nr_class (0),
1012  numSVM (1),
1013  sample (100),
1014  sampleSV (0),
1015  threshold (0.0f)
1016 
1017 {
1018  KKStr leftOverStr;
1019 
1020  KKStr field (_paramStr.ExtractToken (" \t\n\r"));
1021  KKStr value;
1022 
1023  double valueNum;
1024 
1025  while (!field.Empty ())
1026  {
1027  if (field[0] != '-')
1028  {
1029  leftOverStr << " " << field;
1030  }
1031  else
1032  {
1033  _paramStr.TrimLeft (" \t\n\r");
1034  value == "";
1035  if (_paramStr.Len () > 0)
1036  {
1037  if (_paramStr[0] != '-')
1038  value = _paramStr.ExtractToken (" \t\n\r");
1039  }
1040 
1041  valueNum = atof (value.Str ());
1042 
1043  bool parmUsed = false;
1044 
1045  if (field.Len () > 2)
1046  {
1047  leftOverStr << " " << field << " " << value;
1048  }
1049  else
1050  {
1051  ProcessSvmParameter (field, value, valueNum, parmUsed);
1052  if (!parmUsed)
1053  {
1054  leftOverStr << " " << field << " " << value;
1055  }
1056  }
1057  }
1058 
1059  field = _paramStr.ExtractToken (" \t\n\r");
1060  }
1061 
1062  _paramStr = leftOverStr;
1063 
1064 } /* svm_parameter (KKStr paramStr) */
1065 
1066 
1067 
1068 
1070 {
1071  KKStr cmdStr (200); // Initialized char* allocation to 200
1072 
1073  cmdStr << "-a " << numSVM << " "
1074  //<< "-b " << sample << " "
1075  << "-c " << C << " "
1076  << "-d " << degree << " "
1077  << "-e " << eps << " "
1078  << "-g " << gamma << " "
1079  << "-h " << shrinking << " "
1080  << "-i " << threshold << " "
1081  << "-j " << hist << " "
1082  << "-k " << boosting << " "
1083  << "-l " << cBoost << " "
1084  << "-m " << cache_size << " "
1085  << "-n " << nu << " ";
1086 
1087  if (dimSelect >= 0)
1088  cmdStr << "-o " << dimSelect << " ";
1089 
1090  cmdStr << "-p " << p << " "
1091  << "-q " << confidence << " "
1092  << "-r " << coef0 << " "
1093  << "-s " << svm_type << " "
1094  << "-t " << kernel_type << " "
1095  << "-u " << A << " ";
1096 
1097  return cmdStr;
1098 } /* ToCmdLineStr */
1099 
1100 
1101 
1102 
1103 
1105 {
1106  kkint32 x;
1107 
1108  KKStr result (300);
1109 
1110  result << "svm_type" << "\t" << svm_type << "\t"
1111  << "kernel_type" << "\t" << kernel_type << "\t"
1112  << "degree" << "\t" << degree << "\t"
1113  << "gamma" << "\t" << gamma << "\t"
1114  << "coef0" << "\t" << coef0 << "\t"
1115  << "cache_size" << "\t" << cache_size << "\t"
1116  << "eps" << "\t" << eps << "\t"
1117  << "C" << "\t" << C << "\t";
1118 
1119  result << "nr_weight" << "\t" << nr_weight << "\t";
1120  if (nr_weight > 0)
1121  {
1122  for (x = 0; x < nr_weight; x++)
1123  {
1124  if (x > 0) result << ",";
1125  result << weight_label[x];
1126  }
1127  result << "\t";
1128 
1129  for (x = 0; x < nr_weight; x++)
1130  {
1131  if (x > 0) result << ",";
1132  result << weight[x];
1133  }
1134  result << "\t";
1135  }
1136 
1137  result << "nu" << "\t" << nu << "\t"
1138  << "p" << "\t" << p << "\t"
1139  << "shrinking" << "\t" << shrinking << "\t"
1140  << "probability" << "\t" << probability << "\t"
1141  << "numSVM" << "\t" << numSVM << "\t"
1142  << "sampleSV" << "\t" << sampleSV << "\t"
1143  << "hist" << "\t" << hist << "\t"
1144  << "boosting" << "\t" << boosting << "\t"
1145  << "cBoost" << "\t" << cBoost << "\t"
1146  << "dimSelect" << "\t" << dimSelect << "\t"
1147  << "dim" << "\t" << dim << "\t";
1148 
1149  if (featureWeight)
1150  {
1151  result << "featureWeight" << "\t";
1152  for (kkint32 x = 0; x < dim; x++)
1153  {
1154  if (x > 0)
1155  result << ",";
1156  result << featureWeight[x];
1157  }
1158  result << "\t";
1159  }
1160 
1161  result << "confidence" << "\t" << confidence << "\t"
1162  << "A" << "\t" << A << "\t"
1163  << "nr_class" << "\t" << nr_class << "\t"
1164  << "threshold" << "\t" << threshold << "\t"
1165  << "sample" << "\t" << sample << "\t";
1166 
1167  return result;
1168 } /* ToTabDelStr */
1169 
1170 
1171 
1172 
1173 
1174 
1175 
1177 {
1178  KKStr str = _str;
1179 
1180  kkint32 x;
1181 
1182 
1183 /*
1184 
1185 
1186  if (featureWeight)
1187  {
1188  result << "featureWeight" << "\t";
1189  for (kkint32 x = 0; x < dim; x++)
1190  {
1191  if (x > 0)
1192  result << ",";
1193  result << featureWeight[x];
1194  }
1195  result << "\t";
1196  }
1197 */
1198 
1199 
1200 
1201 
1202  while (!str.Empty ())
1203  {
1204  KKStr field = str.ExtractToken2 ("\t");
1205  KKStr value = str.ExtractToken2 ("\t");
1206  kkint32 valueI = value.ToInt ();
1207  double valueD = value.ToDouble ();
1208  float valueF = value.ToFloat ();
1209 
1210  if (field == "svm_type")
1211  svm_type = valueI;
1212 
1213  else if (field == "kernel_type")
1214  kernel_type = valueI;
1215 
1216  else if (field == "degree")
1217  degree = valueD;
1218 
1219  else if (field == "gamma")
1220  gamma = valueD;
1221 
1222  else if (field == "coef0")
1223  coef0 = valueD;
1224 
1225  else if (field == "cache_size")
1226  cache_size = valueD;
1227 
1228  else if (field == "eps")
1229  eps = valueD;
1230 
1231  else if (field == "C")
1232  C = valueD;
1233 
1234  else if (field == "nr_weight")
1235  {
1236  nr_weight = valueI;
1237  if (nr_weight > 0)
1238  {
1239  delete[] weight_label;
1241 
1242  // value = weight label.
1243  for (x = 0; x < nr_weight; x++)
1244  {
1245  weight_label[x] = value.ExtractTokenInt (",");
1246  }
1247 
1248  delete[] weight;
1249  weight = new double [nr_weight];
1250  KKStr weightStr = str.ExtractToken2 ("\t");
1251  for (x = 0; x < nr_weight; x++)
1252  {
1253  weight[x] = weightStr.ExtractTokenDouble (",");
1254  }
1255  }
1256  }
1257 
1258  else if (field == "nu")
1259  nu = valueD;
1260 
1261  else if (field == "p")
1262  p = valueD;
1263 
1264  else if (field == "shrinking")
1265  shrinking = valueI;
1266 
1267  else if (field == "probability")
1268  probability = valueI;
1269 
1270  else if (field == "numSVM")
1271  numSVM = valueI;
1272 
1273  else if (field == "sampleSV")
1274  sampleSV = valueI;
1275 
1276  else if (field == "hist")
1277  hist = valueI;
1278 
1279  else if (field == "boosting")
1280  boosting = valueI;
1281 
1282  else if (field == "cBoost")
1283  cBoost = valueF;
1284 
1285  else if (field == "dimSelect")
1286  dimSelect = valueI;
1287 
1288  else if (field == "dim")
1289  dim = valueI;
1290 
1291  else if (field == "featureWeight")
1292  {
1293  delete[] featureWeight;
1294  featureWeight = new double[dim];
1295  for (x = 0; x < dim; x++)
1296  {
1297  featureWeight[x] = value.ExtractTokenDouble (",");
1298  }
1299  }
1300 
1301  else if (field == "confidence" )
1302  confidence = valueD;
1303 
1304  else if (field == "A")
1305  A = valueF;
1306 
1307  else if (field == "nr_class")
1308  nr_class = valueI;
1309 
1310  else if (field == "threshold")
1311  threshold = valueF;
1312 
1313  else if (field == "sample")
1314  sample = valueF;
1315  }
1316 } /* ParseTabDelStr */
1317 
1318 
1319 
1320 
1322 {
1323  l = 0;
1324  y = NULL;
1325  index = NULL;
1326  x = NULL;
1327  W = NULL;
1328  weOwnContents = false;
1329 };
1330 
1331 
1332 
1333 
1335 {
1336  if (!weOwnContents)
1337  return;
1338 
1339  for (kkint32 zed = 0; zed < l; zed++)
1340  {
1341  delete x[zed];
1342  x[zed] = NULL;
1343  }
1344 
1345  delete y; y = NULL;
1346  delete index; index = NULL;
1347  delete x; x = NULL;
1348  delete W; W = NULL;
1349 }
1350 
1351 
1352 
1353 
1354 
1355 //
1356 // Kernel Cache
1357 //
1358 // l is the number of total data items
1359 // size is the cache size limit in bytes
1360 //
1362 {
1363 public:
1364  Cache (kkint32 l,
1365  kkint32 size
1366  );
1367  ~Cache();
1368 
1369  // request data [0,len)
1370  // return some position p where [p,len) need to be filled
1371  // (p >= len if nothing needs to be filled)
1372  kkint32 get_data (const kkint32 index,
1373  Qfloat** data,
1374  kkint32 len
1375  );
1376 
1377  void swap_index (kkint32 i,
1378  kkint32 j
1379  ); // future_option
1380 
1381 private:
1382  kkint32 l;
1383  kkint32 size;
1384 
1385  struct head_t
1386  {
1387  head_t *prev, *next; // a circular list
1388  Qfloat *data;
1389  kkint32 len; // data[0,len) is cached in this entry
1390  };
1391 
1392  head_t* head;
1393  head_t lru_head;
1394  void lru_delete (head_t *h);
1395  void lru_insert (head_t *h);
1396 };
1397 
1398 
1399 
1401  kkint32 size_
1402  ):
1403 
1404 l (l_),
1405 size (size_)
1406 
1407 {
1408  head = (head_t *)calloc (l, sizeof (head_t)); // initialized to 0
1409  size /= sizeof (Qfloat);
1410  size -= l * sizeof (head_t) / sizeof (Qfloat);
1411  lru_head.next = lru_head.prev = &lru_head;
1412 }
1413 
1414 
1415 
1417 {
1418  for (head_t *h = lru_head.next; h != &lru_head; h = h->next)
1419  free(h->data);
1420  free(head);
1421 }
1422 
1423 
1424 
1425 void SVM233::Cache::lru_delete (head_t *h)
1426 {
1427  // delete from current location
1428  h->prev->next = h->next;
1429  h->next->prev = h->prev;
1430 }
1431 
1432 
1433 
1434 void SVM233::Cache::lru_insert(head_t *h)
1435 {
1436  // insert to last position
1437  h->next = &lru_head;
1438  h->prev = lru_head.prev;
1439  h->prev->next = h;
1440  h->next->prev = h;
1441 }
1442 
1443 
1444 
1446  Qfloat** data,
1447  kkint32 len
1448  )
1449 {
1450  head_t *h = &head[index];
1451 
1452  if (h->len)
1453  lru_delete(h);
1454 
1455  kkint32 more = len - h->len;
1456 
1457  if (more > 0)
1458  {
1459  // free old space
1460  while(size < more)
1461  {
1462  head_t *old = lru_head.next;
1463  lru_delete(old);
1464  free(old->data);
1465  size += old->len;
1466  old->data = 0;
1467  old->len = 0;
1468  }
1469 
1470  // allocate new space
1471  h->data = (Qfloat *)realloc(h->data,sizeof(Qfloat)*len);
1472  size -= more;
1473  Swap(h->len, len);
1474  }
1475 
1476  lru_insert (h);
1477  *data = h->data;
1478  return len;
1479 }
1480 
1481 
1482 
1484  kkint32 j
1485  )
1486 {
1487  if(i==j) return;
1488 
1489  if(head[i].len) lru_delete(&head[i]);
1490  if(head[j].len) lru_delete(&head[j]);
1491  Swap(head[i].data,head[j].data);
1492  Swap(head[i].len,head[j].len);
1493  if(head[i].len) lru_insert(&head[i]);
1494  if(head[j].len) lru_insert(&head[j]);
1495 
1496  if(i>j) Swap(i,j);
1497  for(head_t *h = lru_head.next; h!=&lru_head; h=h->next)
1498  {
1499  if(h->len > i)
1500  {
1501  if(h->len > j)
1502  Swap(h->data[i],h->data[j]);
1503  else
1504  {
1505  // give up
1506  lru_delete(h);
1507  free(h->data);
1508  size += h->len;
1509  h->data = 0;
1510  h->len = 0;
1511  }
1512  }
1513  }
1514 }
1515 
1516 
1517 
1518 /**
1519  *@brief Kernel evaluation
1520  *@details
1521  * the static method k_function is for doing single kernel evaluation
1522  * the constructor of Kernel prepares to calculate the l*l kernel matrix
1523  * the member function get_Q is for getting one column from the Q Matrix
1524  */
1525 class SVM233::Kernel {
1526 public:
1527  Kernel (kkint32 l,
1528  svm_node * const * x,
1529  const svm_parameter& param
1530  );
1531 
1532  virtual ~Kernel();
1533 
1534  static double k_function (const svm_node* x,
1535  const svm_node* y,
1536  const svm_parameter& param
1537  );
1538 
1539  static double k_function_subspace (const svm_node* x,
1540  const svm_node* y,
1541  const svm_parameter& param,
1542  const double* featureWeight
1543  );
1544 
1545  virtual Qfloat *get_Q (kkint32 column, kkint32 len) const = 0;
1546 
1547  virtual void swap_index(kkint32 i, kkint32 j) const // no so const...
1548  {
1549  Swap (x[i],x[j]);
1550  if(x_square) Swap(x_square[i],x_square[j]);
1551  }
1552 
1553 protected:
1554 
1555  double (Kernel::*kernel_function)(kkint32 i, kkint32 j) const;
1556 
1557 private:
1558  const svm_node **x;
1559  double* x_square;
1560 
1561  // svm_parameter
1562  const kkint32 kernel_type;
1563  const double degree;
1564  const double gamma;
1565  const double coef0;
1566  //luo add
1567  kkint32 dim;
1568  double *featureWeight;
1569 
1570  static double dot(const svm_node *px, const svm_node *py);
1571  static double dotSubspace(const svm_node *px, const svm_node *py, const double *featureWeight);
1572 
1573  double kernel_linear (kkint32 i, kkint32 j) const
1574  {
1575  return dot(x[i],x[j]);
1576  }
1577  double kernel_linear_subspace(kkint32 i, kkint32 j) const
1578  {
1579  return dotSubspace(x[i],x[j], featureWeight);
1580  }
1581  double kernel_poly (kkint32 i, kkint32 j) const
1582  {
1583  return pow(gamma*dot(x[i],x[j])+coef0,degree);
1584  }
1585  double kernel_poly_subspace(kkint32 i, kkint32 j) const
1586  {
1587  return pow(gamma*dotSubspace(x[i],x[j], featureWeight)+coef0,degree);
1588  }
1589  double kernel_rbf (kkint32 i, kkint32 j) const
1590  {
1591  return exp(-gamma*(x_square[i]+x_square[j]-2*dot(x[i],x[j])));
1592  }
1593  double kernel_rbf_subspace(kkint32 i, kkint32 j) const
1594  {
1595  return exp(-gamma*(x_square[i]+x_square[j]-2*dotSubspace(x[i],x[j],featureWeight)));
1596  }
1597  double kernel_sigmoid(kkint32 i, kkint32 j) const
1598  {
1599  return tanh(gamma*dot(x[i],x[j])+coef0);
1600  }
1601  double kernel_sigmoid_subspace(kkint32 i, kkint32 j) const
1602  {
1603  return tanh(gamma*dotSubspace(x[i],x[j],featureWeight)+coef0);
1604  }
1605 };
1606 
1607 
1608 
1609 SVM233::Kernel::Kernel (kkint32 l,
1610  svm_node * const * x_,
1611  const svm_parameter& param
1612  )
1613  :
1614  kernel_type (param.kernel_type),
1615  degree (param.degree),
1616  gamma (param.gamma),
1617  coef0 (param.coef0)
1618 
1619 {
1620  dim=0;
1621  if (param.dimSelect >0)
1622  {
1623  dim = param.dim;
1624  featureWeight = new double[dim];
1625  std::copy (param.featureWeight, param.featureWeight + dim, featureWeight);
1626  }
1627 
1628  switch (kernel_type)
1629  {
1630  case LINEAR:
1631  if(param.dimSelect >0)
1632  kernel_function = &Kernel::kernel_linear_subspace;
1633  else
1634  kernel_function = &Kernel::kernel_linear;
1635  break;
1636 
1637  case POLY:
1638  if(param.dimSelect >0)
1639  kernel_function = &Kernel::kernel_poly_subspace;
1640  else
1641  kernel_function = &Kernel::kernel_poly;
1642  break;
1643 
1644  case RBF:
1645  if(param.dimSelect >0)
1646  kernel_function = &Kernel::kernel_rbf_subspace;
1647  else
1648  kernel_function = &Kernel::kernel_rbf;
1649  break;
1650 
1651  case SIGMOID:
1652  if(param.dimSelect >0)
1653  kernel_function = &Kernel::kernel_sigmoid_subspace;
1654  else
1655  kernel_function = &Kernel::kernel_sigmoid;
1656  break;
1657  }
1658 
1659  clone (x, x_, l);
1660 
1661  if (kernel_type == RBF)
1662  {
1663  x_square = new double[l];
1664  for(kkint32 i=0;i<l;i++)
1665  {
1666  if(param.dimSelect > 0)
1667  x_square[i] = dotSubspace(x[i],x[i],featureWeight);
1668  else
1669  x_square[i] = dot(x[i],x[i]);
1670  }
1671  }
1672  else
1673  x_square = 0;
1674 }
1675 
1676 SVM233::Kernel::~Kernel()
1677 {
1678  if (dim>0)
1679  delete[] featureWeight;
1680  delete[] x;
1681  delete[] x_square;
1682 }
1683 
1684 
1685 
1686 double SVM233::Kernel::dot(const svm_node *px, const svm_node *py)
1687 {
1688  double sum = 0;
1689  while(px->index != -1 && py->index != -1)
1690  {
1691  if(px->index == py->index)
1692  {
1693  sum += px->value * py->value;
1694  ++px;
1695  ++py;
1696  }
1697  else
1698  {
1699  if(px->index > py->index)
1700  ++py;
1701  else
1702  ++px;
1703  }
1704  }
1705  return sum;
1706 }
1707 
1708 
1709 
1710 double SVM233::Kernel::dotSubspace(const svm_node *px, const svm_node *py, const double *featureWeight)
1711 {
1712  double sum = 0;
1713  while(px->index != -1 && py->index != -1)
1714  {
1715  if(px->index == py->index)
1716  {
1717  sum += px->value * py->value * featureWeight[px->index-1];
1718  ++px;
1719  ++py;
1720  }
1721  else
1722  {
1723  if(px->index > py->index)
1724  ++py;
1725  else
1726  ++px;
1727  }
1728  }
1729  return sum;
1730 }
1731 
1732 
1733 
1734 
1735 double SVM233::Kernel::k_function (const svm_node* x,
1736  const svm_node* y,
1737  const svm_parameter& param
1738  )
1739 {
1740 
1741  switch(param.kernel_type)
1742  {
1743  case LINEAR:
1744  return dot(x,y);
1745 
1746  case POLY:
1747  return pow(param.gamma*dot(x,y)+param.coef0,param.degree);
1748 
1749  case RBF:
1750  {
1751  double sum = 0;
1752  while(x->index != -1 && y->index !=-1)
1753  {
1754  if(x->index == y->index)
1755  {
1756  double d = x->value - y->value;
1757  sum += d*d;
1758  ++x;
1759  ++y;
1760  }
1761  else
1762  {
1763  if(x->index > y->index)
1764  {
1765  double d=y->value;
1766  sum += d*d;
1767  ++y;
1768  }
1769  else
1770  {
1771  double d=x->value;
1772  sum += d*d;
1773  ++x;
1774  }
1775  }
1776  }
1777 
1778  while(x->index != -1)
1779  {
1780  double d = x->value;
1781  sum += d*d;
1782  //sum += x->value * x->value;
1783  ++x;
1784  }
1785 
1786  while(y->index != -1)
1787  {
1788  double d=y->value;
1789  sum += d * d;
1790  //sum += y->value * y->value;
1791  ++y;
1792  }
1793 
1794  return exp (-param.gamma * sum);
1795  }
1796  case SIGMOID:
1797  return tanh(param.gamma*dot(x,y)+param.coef0);
1798  default:
1799  return 0; /* Unreachable */
1800  }
1801 }
1802 
1803 
1804 
1805 double SVM233::Kernel::k_function_subspace (const svm_node* x,
1806  const svm_node* y,
1807  const svm_parameter& param,
1808  const double* featureWeight
1809  )
1810 {
1811  switch (param.kernel_type)
1812  {
1813  case LINEAR:
1814  return dotSubspace(x,y,featureWeight);
1815  case POLY:
1816  return pow(param.gamma*dotSubspace(x,y,featureWeight)+param.coef0,param.degree);
1817 
1818  case RBF:
1819  {
1820  double sum = 0;
1821  while(x->index != -1 && y->index !=-1)
1822  {
1823  if(x->index == y->index)
1824  {
1825  double d = x->value - y->value;
1826  sum+=d*d*featureWeight[x->index-1];
1827 
1828  ++x;
1829  ++y;
1830  }
1831  else
1832  {
1833  if(x->index > y->index)
1834  {
1835  double d=y->value;
1836  sum+=d*d*featureWeight[y->index-1];
1837  ++y;
1838  }
1839  else
1840  {
1841  double d=x->value;
1842  sum+=d*d*featureWeight[x->index-1];
1843  ++x;
1844  }
1845  }
1846  }
1847 
1848  while(x->index != -1)
1849  {
1850  double d = x->value;
1851  sum+=d*d*featureWeight[x->index-1];
1852 
1853  //sum += x->value * x->value;
1854  ++x;
1855  }
1856 
1857  while(y->index != -1)
1858  {
1859  double d=y->value;
1860 
1861  sum+=d*d*featureWeight[y->index-1];
1862 
1863  //sum += y->value * y->value;
1864  ++y;
1865  }
1866 
1867  return exp (-param.gamma * sum);
1868  }
1869  case SIGMOID:
1870  return tanh(param.gamma*dotSubspace(x,y, featureWeight)+param.coef0);
1871  default:
1872  return 0; /* Unreachable */
1873  }
1874 } /* k_function_subspace */
1875 
1876 
1877 
1878 
1879 
1880 
1882 {
1883  Q->swap_index(i,j);
1884  Swap(y[i],y[j]);
1885  Swap(G[i],G[j]);
1886  Swap(alpha_status[i],alpha_status[j]);
1887  Swap(alpha[i],alpha[j]);
1888  Swap(b[i],b[j]);
1889  Swap(active_set[i],active_set[j]);
1890  Swap(G_bar[i],G_bar[j]);
1891  Swap(C[i], C[j]);
1892 }
1893 
1894 
1895 
1896 
1898 {
1899  // reconstruct inactive elements of G from G_bar and free variables
1900 
1901  if (active_size == l)
1902  return;
1903 
1904  kkint32 i;
1905  for(i=active_size;i<l;i++)
1906  G[i] = G_bar[i] + b[i];
1907 
1908  for(i=0;i<active_size;i++)
1909  if(is_free(i))
1910  {
1911  const Qfloat *Q_i = Q->get_Q(i,l);
1912  double alpha_i = alpha[i];
1913  for(kkint32 j=active_size;j<l;j++)
1914  G[j] += alpha_i * Q_i[j];
1915  }
1916 }
1917 
1918 
1919 
1921  const Kernel& Q,
1922  const double* b_,
1923  const schar* y_,
1924  double* alpha_,
1925  double* C_,
1926  double eps,
1927  SolutionInfo* si,
1928  kkint32 shrinking
1929  )
1930 {
1931  this->l = l;
1932  this->Q = &Q;
1933  clone (b, b_,l);
1934  clone (y, y_,l);
1935  clone (alpha,alpha_,l);
1936  clone (C, C_, l);
1937  this->eps = eps;
1938  unshrinked = false;
1939 
1940  // initialize alpha_status
1941  {
1942  alpha_status = new char[l];
1943  for (kkint32 i=0;i<l;i++){
1945  }
1946  }
1947 
1948  // initialize active set (for shrinking)
1949  {
1950  active_set = new kkint32[l];
1951  for(kkint32 i=0;i<l;i++)
1952  active_set[i] = i;
1953  active_size = l;
1954  }
1955 
1956  // initialize gradient
1957  {
1958  G = new double[l];
1959  G_bar = new double[l];
1960  kkint32 i;
1961  for(i=0;i<l;i++)
1962  {
1963  G[i] = b[i];
1964  G_bar[i] = 0;
1965  }
1966  for (i=0;i<l;i++)
1967  if (!is_lower_bound(i))
1968  {
1969  Qfloat *Q_i = Q.get_Q(i,l);
1970  double alpha_i = alpha[i];
1971  kkint32 j;
1972  for(j=0;j<l;j++)
1973  G[j] += alpha_i*Q_i[j];
1974  if(is_upper_bound(i))
1975  for(j=0;j<l;j++)
1976  G_bar[j] += get_C(i) * Q_i[j];
1977  }
1978  }
1979 
1980  // optimization step
1981 
1982  kkint32 iter = 0;
1983  kkint32 counter = min ((kkint32)l, (kkint32)1000) + 1;
1984 
1985  while(1)
1986  {
1987  // show progress and do shrinking
1988 
1989  if(--counter == 0)
1990  {
1991  counter = min(l,1000);
1992  if(shrinking) do_shrinking();
1993  info("."); info_flush();
1994  }
1995 
1996  kkint32 i,j;
1997  if(select_working_set(i,j)!=0)
1998  {
1999  // reconstruct the whole gradient
2001  // reset active set size and check
2002  active_size = l;
2003  info("*"); info_flush();
2004  if(select_working_set(i,j)!=0)
2005  break;
2006  else
2007  counter = 1; // do shrinking next iteration
2008  }
2009 
2010  ++iter;
2011 
2012  // update alpha[i] and alpha[j], handle bounds carefully
2013 
2014  const Qfloat *Q_i = Q.get_Q(i,active_size);
2015  const Qfloat *Q_j = Q.get_Q(j,active_size);
2016 
2017  double C_i = get_C(i);
2018  double C_j = get_C(j);
2019 
2020  double old_alpha_i = alpha[i];
2021  double old_alpha_j = alpha[j];
2022 
2023  if(y[i]!=y[j])
2024  {
2025  double delta = (-G[i]-G[j])/max(Q_i[i]+Q_j[j]+2*Q_i[j],(Qfloat)0);
2026  double diff = alpha[i] - alpha[j];
2027  alpha[i] += delta;
2028  alpha[j] += delta;
2029 
2030  if(diff > 0)
2031  {
2032  if(alpha[j] < 0)
2033  {
2034  alpha[j] = 0;
2035  alpha[i] = diff;
2036  }
2037  }
2038  else
2039  {
2040  if(alpha[i] < 0)
2041  {
2042  alpha[i] = 0;
2043  alpha[j] = -diff;
2044  }
2045  }
2046  if(diff > C_i - C_j)
2047  {
2048  if(alpha[i] > C_i)
2049  {
2050  alpha[i] = C_i;
2051  alpha[j] = C_i - diff;
2052  }
2053  }
2054  else
2055  {
2056  if(alpha[j] > C_j)
2057  {
2058  alpha[j] = C_j;
2059  alpha[i] = C_j + diff;
2060  }
2061  }
2062  }
2063  else
2064  {
2065  double delta = (G[i]-G[j])/max(Q_i[i]+Q_j[j]-2*Q_i[j],(Qfloat)0);
2066  double sum = alpha[i] + alpha[j];
2067  alpha[i] -= delta;
2068  alpha[j] += delta;
2069  if(sum > C_i)
2070  {
2071  if(alpha[i] > C_i)
2072  {
2073  alpha[i] = C_i;
2074  alpha[j] = sum - C_i;
2075  }
2076  }
2077  else
2078  {
2079  if(alpha[j] < 0)
2080  {
2081  alpha[j] = 0;
2082  alpha[i] = sum;
2083  }
2084  }
2085  if(sum > C_j)
2086  {
2087  if(alpha[j] > C_j)
2088  {
2089  alpha[j] = C_j;
2090  alpha[i] = sum - C_j;
2091  }
2092  }
2093  else
2094  {
2095  if(alpha[i] < 0)
2096  {
2097  alpha[i] = 0;
2098  alpha[j] = sum;
2099  }
2100  }
2101  }
2102 
2103  // update G
2104 
2105  double delta_alpha_i = alpha[i] - old_alpha_i;
2106  double delta_alpha_j = alpha[j] - old_alpha_j;
2107 
2108  for(kkint32 k=0;k<active_size;k++)
2109  {
2110  G[k] += Q_i[k]*delta_alpha_i + Q_j[k]*delta_alpha_j;
2111  }
2112 
2113  // update alpha_status and G_bar
2114 
2115  {
2116  bool ui = is_upper_bound(i);
2117  bool uj = is_upper_bound(j);
2120  kkint32 k;
2121  if(ui != is_upper_bound(i))
2122  {
2123  Q_i = Q.get_Q(i,l);
2124  if(ui)
2125  for(k=0;k<l;k++)
2126  G_bar[k] -= C_i * Q_i[k];
2127  else
2128  for(k=0;k<l;k++)
2129  G_bar[k] += C_i * Q_i[k];
2130  }
2131 
2132  if(uj != is_upper_bound(j))
2133  {
2134  Q_j = Q.get_Q(j,l);
2135  if(uj)
2136  for(k=0;k<l;k++)
2137  G_bar[k] -= C_j * Q_j[k];
2138  else
2139  for(k=0;k<l;k++)
2140  G_bar[k] += C_j * Q_j[k];
2141  }
2142  }
2143  }
2144 
2145  // calculate rho
2146 
2147  si->rho = calculate_rho();
2148 
2149  // calculate objective value
2150  {
2151  double v = 0;
2152  kkint32 i;
2153  for(i=0;i<l;i++)
2154  v += alpha[i] * (G[i] + b[i]);
2155 
2156  si->obj = v/2;
2157  }
2158 
2159  // put back the solution
2160  {
2161  for(kkint32 i=0;i<l;i++)
2162  alpha_[active_set[i]] = alpha[i];
2163  }
2164 
2165  // juggle everything back
2166  /*{
2167  for(kkint32 i=0;i<l;i++)
2168  while(active_set[i] != i)
2169  swap_index(i,active_set[i]);
2170  // or Q.swap_index(i,active_set[i]);
2171  }*/
2172 
2173  info("\noptimization finished, #iter = %d\n",iter);
2174 
2175  delete[] C;
2176  delete[] b;
2177  delete[] y;
2178  delete[] alpha;
2179  delete[] alpha_status;
2180  delete[] active_set;
2181  delete[] G;
2182  delete[] G_bar;
2183 }
2184 
2185 
2187  const Kernel& Q,
2188  const double* b_,
2189  const schar* y_,
2190  double* alpha_,
2191  double Cp,
2192  double Cn,
2193  double eps,
2194  SolutionInfo* si,
2195  kkint32 shrinking
2196  )
2197 {
2198  double* C_ = new double[l];
2199  for(kkint32 i=0;i<l;i++)
2200  C_[i] = (y_[i] > 0 ? Cp : Cn);
2201 
2202  Solve (l, Q, b_, y_, alpha_, C_, eps, si, shrinking);
2203 
2204  si->upper_bound_p = Cp;
2205  si->upper_bound_n = Cn;
2206  delete [] C_;
2207 }
2208 
2209 
2210 
2211 // return 1 if already optimal, return 0 otherwise
2213 {
2214  // return i,j which maximize -grad(f)^T d , under constraint
2215  // if alpha_i == C, d != +1
2216  // if alpha_i == 0, d != -1
2217 
2218  double Gmax1 = -INF; // max { -grad(f)_i * d | y_i*d = +1 }
2219  kkint32 Gmax1_idx = -1;
2220 
2221  double Gmax2 = -INF; // max { -grad(f)_i * d | y_i*d = -1 }
2222  kkint32 Gmax2_idx = -1;
2223 
2224  for(kkint32 i=0;i<active_size;i++)
2225  {
2226  if(y[i]==+1) // y = +1
2227  {
2228  if(!is_upper_bound(i)) // d = +1
2229  {
2230  if(-G[i] > Gmax1)
2231  {
2232  Gmax1 = -G[i];
2233  Gmax1_idx = i;
2234  }
2235  }
2236  if(!is_lower_bound(i)) // d = -1
2237  {
2238  if(G[i] > Gmax2)
2239  {
2240  Gmax2 = G[i];
2241  Gmax2_idx = i;
2242  }
2243  }
2244  }
2245  else // y = -1
2246  {
2247  if(!is_upper_bound(i)) // d = +1
2248  {
2249  if(-G[i] > Gmax2)
2250  {
2251  Gmax2 = -G[i];
2252  Gmax2_idx = i;
2253  }
2254  }
2255  if(!is_lower_bound(i)) // d = -1
2256  {
2257  if(G[i] > Gmax1)
2258  {
2259  Gmax1 = G[i];
2260  Gmax1_idx = i;
2261  }
2262  }
2263  }
2264  }
2265 
2266  if(Gmax1+Gmax2 < eps)
2267  return 1;
2268 
2269  out_i = Gmax1_idx;
2270  out_j = Gmax2_idx;
2271  return 0;
2272 }
2273 
2274 
2275 
2277 {
2278  kkint32 i,j,k;
2279  if (select_working_set (i,j) != 0)
2280  return;
2281 
2282  double Gm1 = -y[j]*G[j];
2283  double Gm2 = y[i]*G[i];
2284 
2285  // shrink
2286 
2287  for (k = 0; k < active_size; k++)
2288  {
2289  if (is_lower_bound (k))
2290  {
2291  if (y[k]==+1)
2292  {
2293  if(-G[k] >= Gm1) continue;
2294  }
2295  else if (-G[k] >= Gm2) continue;
2296  }
2297  else if (is_upper_bound(k))
2298  {
2299  if(y[k]==+1)
2300  {
2301  if(G[k] >= Gm2) continue;
2302  }
2303  else if(G[k] >= Gm1) continue;
2304  }
2305  else continue;
2306 
2307  --active_size;
2309  --k; // look at the newcomer
2310  }
2311 
2312  // unshrink, check all variables again before final iterations
2313 
2314  if(unshrinked || -(Gm1 + Gm2) > eps*10) return;
2315 
2316  unshrinked = true;
2318 
2319  for(k=l-1;k>=active_size;k--)
2320  {
2321  if(is_lower_bound(k))
2322  {
2323  if(y[k]==+1)
2324  {
2325  if(-G[k] < Gm1) continue;
2326  }
2327  else if(-G[k] < Gm2) continue;
2328  }
2329  else if(is_upper_bound(k))
2330  {
2331  if(y[k]==+1)
2332  {
2333  if(G[k] < Gm2) continue;
2334  }
2335  else if(G[k] < Gm1) continue;
2336  }
2337  else continue;
2338 
2340  active_size++;
2341  ++k; // look at the newcomer
2342  }
2343 }
2344 
2345 
2346 
2347 
2349 {
2350  double r;
2351  kkint32 nr_free = 0;
2352  double ub = INF, lb = -INF, sum_free = 0;
2353  for (kkint32 i = 0; i < active_size; i++)
2354  {
2355  double yG = y[i]*G[i];
2356 
2357  if(is_lower_bound(i))
2358  {
2359  if(y[i] > 0)
2360  ub = min(ub,yG);
2361  else
2362  lb = max(lb,yG);
2363  }
2364  else if(is_upper_bound(i))
2365  {
2366  if(y[i] < 0)
2367  ub = min(ub,yG);
2368  else
2369  lb = max(lb,yG);
2370  }
2371  else
2372  {
2373  ++nr_free;
2374  sum_free += yG;
2375  }
2376  }
2377 
2378  if(nr_free>0)
2379  r = sum_free/nr_free;
2380  else
2381  r = (ub+lb)/2;
2382 
2383  return r;
2384 }
2385 
2386 
2387 
2388 
2389 //
2390 // Solver for nu-svm classification and regression
2391 //
2392 // additional constraint: e^T \alpha = constant
2393 //
2394 class SVM233::Solver_NU : public Solver
2395 {
2396 public:
2398  void Solve (kkint32 l,
2399  const Kernel& Q,
2400  const double *b,
2401  const schar *y,
2402  double *alpha,
2403  double Cp,
2404  double Cn,
2405  double eps,
2406  SolutionInfo* si,
2407  kkint32 shrinking
2408  )
2409  {
2410  this->si = si;
2411  Solver::Solve(l,Q,b,y,alpha,Cp,Cn,eps,si,shrinking);
2412  }
2413 
2414 private:
2415  SolutionInfo *si;
2416  kkint32 select_working_set(kkint32 &i, kkint32 &j);
2417  double calculate_rho();
2418  void do_shrinking();
2419 };
2420 
2421 
2422 
2423 
2424 kkint32 SVM233::Solver_NU::select_working_set(kkint32 &out_i, kkint32 &out_j)
2425 {
2426  // return i,j which maximize -grad(f)^T d , under constraint
2427  // if alpha_i == C, d != +1
2428  // if alpha_i == 0, d != -1
2429 
2430  double Gmax1 = -INF; // max { -grad(f)_i * d | y_i = +1, d = +1 }
2431  kkint32 Gmax1_idx = -1;
2432 
2433  double Gmax2 = -INF; // max { -grad(f)_i * d | y_i = +1, d = -1 }
2434  kkint32 Gmax2_idx = -1;
2435 
2436  double Gmax3 = -INF; // max { -grad(f)_i * d | y_i = -1, d = +1 }
2437  kkint32 Gmax3_idx = -1;
2438 
2439  double Gmax4 = -INF; // max { -grad(f)_i * d | y_i = -1, d = -1 }
2440  kkint32 Gmax4_idx = -1;
2441 
2442  for(kkint32 i=0;i<active_size;i++)
2443  {
2444  if(y[i]==+1) // y == +1
2445  {
2446  if(!is_upper_bound(i)) // d = +1
2447  {
2448  if(-G[i] > Gmax1)
2449  {
2450  Gmax1 = -G[i];
2451  Gmax1_idx = i;
2452  }
2453  }
2454  if(!is_lower_bound(i)) // d = -1
2455  {
2456  if(G[i] > Gmax2)
2457  {
2458  Gmax2 = G[i];
2459  Gmax2_idx = i;
2460  }
2461  }
2462  }
2463  else // y == -1
2464  {
2465  if(!is_upper_bound(i)) // d = +1
2466  {
2467  if(-G[i] > Gmax3)
2468  {
2469  Gmax3 = -G[i];
2470  Gmax3_idx = i;
2471  }
2472  }
2473  if(!is_lower_bound(i)) // d = -1
2474  {
2475  if(G[i] > Gmax4)
2476  {
2477  Gmax4 = G[i];
2478  Gmax4_idx = i;
2479  }
2480  }
2481  }
2482  }
2483 
2484  if(max(Gmax1+Gmax2,Gmax3+Gmax4) < eps)
2485  return 1;
2486 
2487  if(Gmax1+Gmax2 > Gmax3+Gmax4)
2488  {
2489  out_i = Gmax1_idx;
2490  out_j = Gmax2_idx;
2491  }
2492  else
2493  {
2494  out_i = Gmax3_idx;
2495  out_j = Gmax4_idx;
2496  }
2497  return 0;
2498 }
2499 
2500 
2501 
2502 
2503 void SVM233::Solver_NU::do_shrinking()
2504 {
2505  double Gmax1 = -INF; // max { -grad(f)_i * d | y_i = +1, d = +1 }
2506  double Gmax2 = -INF; // max { -grad(f)_i * d | y_i = +1, d = -1 }
2507  double Gmax3 = -INF; // max { -grad(f)_i * d | y_i = -1, d = +1 }
2508  double Gmax4 = -INF; // max { -grad(f)_i * d | y_i = -1, d = -1 }
2509 
2510  kkint32 k;
2511  for (k = 0; k < active_size; k++)
2512  {
2513  if(!is_upper_bound(k))
2514  {
2515  if(y[k]==+1)
2516  {
2517  if(-G[k] > Gmax1) Gmax1 = -G[k];
2518  }
2519  else if(-G[k] > Gmax3) Gmax3 = -G[k];
2520  }
2521  if(!is_lower_bound(k))
2522  {
2523  if(y[k]==+1)
2524  {
2525  if(G[k] > Gmax2) Gmax2 = G[k];
2526  }
2527  else if(G[k] > Gmax4) Gmax4 = G[k];
2528  }
2529  }
2530 
2531  double Gm1 = -Gmax2;
2532  double Gm2 = -Gmax1;
2533  double Gm3 = -Gmax4;
2534  double Gm4 = -Gmax3;
2535 
2536  for(k=0;k<active_size;k++)
2537  {
2538  if(is_lower_bound(k))
2539  {
2540  if(y[k]==+1)
2541  {
2542  if(-G[k] >= Gm1) continue;
2543  }
2544  else if(-G[k] >= Gm3) continue;
2545  }
2546  else if(is_upper_bound(k))
2547  {
2548  if(y[k]==+1)
2549  {
2550  if(G[k] >= Gm2) continue;
2551  }
2552  else if(G[k] >= Gm4) continue;
2553  }
2554  else continue;
2555 
2556  --active_size;
2558  --k; // look at the newcomer
2559  }
2560 
2561  // un-shrink, check all variables again before final iterations
2562 
2563  if(unshrinked || max(-(Gm1+Gm2),-(Gm3+Gm4)) > eps*10) return;
2564 
2565  unshrinked = true;
2567 
2568  for(k=l-1;k>=active_size;k--)
2569  {
2570  if(is_lower_bound(k))
2571  {
2572  if(y[k]==+1)
2573  {
2574  if(-G[k] < Gm1) continue;
2575  }
2576  else if(-G[k] < Gm3) continue;
2577  }
2578  else if(is_upper_bound(k))
2579  {
2580  if(y[k]==+1)
2581  {
2582  if(G[k] < Gm2) continue;
2583  }
2584  else if(G[k] < Gm4) continue;
2585  }
2586  else continue;
2587 
2589  active_size++;
2590  ++k; // look at the newcomer
2591  }
2592 }
2593 
2594 
2595 
2596 
2597 double SVM233::Solver_NU::calculate_rho ()
2598 {
2599  kkint32 nr_free1 = 0,nr_free2 = 0;
2600  double ub1 = INF, ub2 = INF;
2601  double lb1 = -INF, lb2 = -INF;
2602  double sum_free1 = 0, sum_free2 = 0;
2603 
2604  for(kkint32 i=0;i<active_size;i++)
2605  {
2606  if(y[i]==+1)
2607  {
2608  if(is_lower_bound(i))
2609  ub1 = min(ub1,G[i]);
2610  else if(is_upper_bound(i))
2611  lb1 = max(lb1,G[i]);
2612  else
2613  {
2614  ++nr_free1;
2615  sum_free1 += G[i];
2616  }
2617  }
2618  else
2619  {
2620  if(is_lower_bound(i))
2621  ub2 = min(ub2,G[i]);
2622  else if(is_upper_bound(i))
2623  lb2 = max(lb2,G[i]);
2624  else
2625  {
2626  ++nr_free2;
2627  sum_free2 += G[i];
2628  }
2629  }
2630  }
2631 
2632  double r1,r2;
2633  if(nr_free1 > 0)
2634  r1 = sum_free1/nr_free1;
2635  else
2636  r1 = (ub1+lb1)/2;
2637 
2638  if(nr_free2 > 0)
2639  r2 = sum_free2/nr_free2;
2640  else
2641  r2 = (ub2+lb2)/2;
2642 
2643  si->r = (r1+r2)/2;
2644  return (r1-r2)/2;
2645 }
2646 
2647 //
2648 // Q matrices for various formulations
2649 //
2650 class SVM233::SVC_Q: public Kernel
2651 {
2652 public:
2653  SVC_Q (const svm_problem& prob,
2654  const svm_parameter& param,
2655  const schar *y_
2656  )
2657  :Kernel (prob.l, prob.x, param)
2658  {
2659  clone(y,y_,prob.l);
2660  cache = new Cache(prob.l,(kkint32)(param.cache_size*(1<<20)));
2661  }
2662 
2663  Qfloat *get_Q(kkint32 i, kkint32 len) const
2664  {
2665  Qfloat *data;
2666  kkint32 start;
2667  if ((start = cache->get_data (i, &data, len)) < len)
2668  {
2669  for (kkint32 j = start; j < len; j++)
2670  data[j] = (Qfloat)(y[i] * y[j] * (this->*kernel_function)(i,j));
2671  //luo add data[j] = (Qfloat)(w[i]*w[j]*y[i]*y[j]*(this->*kernel_function)(i,j));
2672  }
2673  return data;
2674  }
2675 
2676  void swap_index(kkint32 i, kkint32 j) const
2677  {
2678  cache->swap_index(i,j);
2679  Kernel::swap_index(i,j);
2680  Swap(y[i],y[j]);
2681  }
2682 
2684  {
2685  delete[] y;
2686  delete cache;
2687  }
2688 
2689 private:
2690  schar *y;
2691  Cache *cache;
2692 };
2693 
2694 
2695 
2696 
2697 class SVM233::ONE_CLASS_Q: public Kernel
2698 {
2699 public:
2700  ONE_CLASS_Q (const svm_problem& prob,
2701  const svm_parameter& param
2702  )
2703  :Kernel (prob.l, prob.x, param)
2704  {
2705  cache = new Cache(prob.l,(kkint32)(param.cache_size*(1<<20)));
2706  }
2707 
2708  Qfloat *get_Q(kkint32 i, kkint32 len) const
2709  {
2710  Qfloat *data;
2711  kkint32 start;
2712  if((start = cache->get_data(i,&data,len)) < len)
2713  {
2714  for(kkint32 j=start;j<len;j++)
2715  data[j] = (Qfloat)(this->*kernel_function)(i,j);
2716  }
2717  return data;
2718  }
2719 
2720  void swap_index(kkint32 i, kkint32 j) const
2721  {
2722  cache->swap_index(i,j);
2723  Kernel::swap_index(i,j);
2724  }
2725 
2726 
2728  {
2729  delete cache;
2730  }
2731 
2732 private:
2733  Cache *cache;
2734 };
2735 
2736 
2737 
2738 class SVM233::SVR_Q: public Kernel
2739 {
2740 public:
2741  SVR_Q (const svm_problem& prob,
2742  const svm_parameter& param
2743  )
2744  :Kernel (prob.l, prob.x, param)
2745  {
2746  l = prob.l;
2747  cache = new Cache(l,(kkint32)(param.cache_size*(1<<20)));
2748  sign = new schar[2*l];
2749  index = new kkint32[2*l];
2750  for(kkint32 k=0;k<l;k++)
2751  {
2752  sign[k] = 1;
2753  sign[k+l] = -1;
2754  index[k] = k;
2755  index[k+l] = k;
2756  }
2757  buffer[0] = new Qfloat[2*l];
2758  buffer[1] = new Qfloat[2*l];
2759  next_buffer = 0;
2760  }
2761 
2762  void swap_index(kkint32 i, kkint32 j) const
2763  {
2764  Swap(sign[i],sign[j]);
2765  Swap(index[i],index[j]);
2766  }
2767 
2768 
2769  Qfloat *get_Q(kkint32 i, kkint32 len) const
2770  {
2771  Qfloat *data;
2772  kkint32 real_i = index[i];
2773  if(cache->get_data(real_i,&data,l) < l)
2774  {
2775  for(kkint32 j=0;j<l;j++)
2776  data[j] = (Qfloat)(this->*kernel_function)(real_i,j);
2777  }
2778 
2779  // reorder and copy
2780  Qfloat *buf = buffer[next_buffer];
2781  next_buffer = 1 - next_buffer;
2782  schar si = sign[i];
2783  for(kkint32 j=0;j<len;j++)
2784  buf[j] = si * sign[j] * data[index[j]];
2785  return buf;
2786  }
2787 
2789  {
2790  delete cache;
2791  delete[] sign;
2792  delete[] index;
2793  delete[] buffer[0];
2794  delete[] buffer[1];
2795  }
2796 private:
2797  kkint32 l;
2798  Cache *cache;
2799  schar *sign;
2800  kkint32 *index;
2801  mutable kkint32 next_buffer;
2802  Qfloat* buffer[2];
2803 };
2804 
2805 
2806 
2807 
2808 //
2809 // construct and solve various formulations
2810 //
2811 static void SVM233::solve_c_svc (const svm_problem* prob,
2812  const svm_parameter* param,
2813  double* alpha,
2814  Solver::SolutionInfo* si,
2815  double Cp,
2816  double Cn
2817  )
2818 {
2819  kkint32 l = prob->l;
2820  double *minus_ones = new double[l];
2821  schar *y = new schar[l];
2822 
2823  kkint32 i;
2824 
2825  for(i=0;i<l;i++)
2826  {
2827  alpha[i] = 0;
2828  minus_ones[i] = -1;
2829  if (prob->y[i] > 0)
2830  y[i] = +1;
2831  else
2832  y[i]=-1;
2833  }
2834 
2835  Solver s;
2836  s.Solve (l,
2837  SVC_Q(*prob,*param,y),
2838  minus_ones,
2839  y,
2840  alpha,
2841  Cp,
2842  Cn,
2843  param->eps,
2844  si,
2845  param->shrinking
2846  );
2847 
2848  double sum_alpha=0;
2849  for(i=0;i<l;i++)
2850  sum_alpha += alpha[i];
2851 
2852  info("nu = %f\n", sum_alpha/(param->C*prob->l));
2853 
2854  for(i=0;i<l;i++)
2855  alpha[i] *= y[i];
2856 
2857  delete[] minus_ones;
2858  delete[] y;
2859 } /* solve_c_svc */
2860 
2861 
2862 
2863 //luo: the weighted training
2864 static void SVM233::solve_c_svc (const svm_problem* prob,
2865  const svm_parameter* param,
2866  double* alpha,
2867  Solver::SolutionInfo* si,
2868  double* C_
2869  )
2870 {
2871  kkint32 l = prob->l;
2872  double *minus_ones = new double[l];
2873  schar *y = new schar[l];
2874 
2875  kkint32 i;
2876 
2877  for (i = 0; i < l; i++)
2878  {
2879  alpha[i] = 0;
2880  minus_ones[i] = -1;
2881  if (prob->y[i] > 0)
2882  y[i] = +1;
2883  else
2884  y[i] = -1;
2885  }
2886 
2887  Solver s;
2888  s.Solve (l,
2889  SVC_Q (*prob, *param, y),
2890  minus_ones,
2891  y,
2892  alpha,
2893  C_,
2894  param->eps,
2895  si,
2896  param->shrinking
2897  );
2898 
2899  double sum_alpha=0;
2900  for (i = 0; i < l; i++)
2901  sum_alpha += alpha[i];
2902 
2903  info("nu = %f\n", sum_alpha/(param->C * prob->l));
2904 
2905  for (i = 0; i < l; i++)
2906  alpha[i] *= y[i];
2907 
2908  delete[] minus_ones;
2909  delete[] y;
2910 } /* solve_c_svc */
2911 
2912 
2913 
2914 static void SVM233::solve_nu_svc (const svm_problem* prob,
2915  const svm_parameter* param,
2916  double* alpha,
2917  Solver::SolutionInfo* si
2918  )
2919 {
2920  kkint32 i;
2921  kkint32 l = prob->l;
2922  double nu = param->nu;
2923 
2924  schar *y = new schar[l];
2925 
2926  for(i=0;i<l;i++)
2927  if(prob->y[i]>0)
2928  y[i] = +1;
2929  else
2930  y[i] = -1;
2931 
2932  double sum_pos = nu*l/2;
2933  double sum_neg = nu*l/2;
2934 
2935  for(i=0;i<l;i++)
2936  if(y[i] == +1)
2937  {
2938  alpha[i] = min(1.0,sum_pos);
2939  sum_pos -= alpha[i];
2940  }
2941  else
2942  {
2943  alpha[i] = min(1.0,sum_neg);
2944  sum_neg -= alpha[i];
2945  }
2946 
2947  double *zeros = new double[l];
2948 
2949  for(i=0;i<l;i++)
2950  zeros[i] = 0;
2951 
2952  Solver_NU s;
2953  s.Solve(l, SVC_Q(*prob,*param,y), zeros, y,
2954  alpha, 1.0, 1.0, param->eps, si, param->shrinking);
2955  double r = si->r;
2956 
2957  info("C = %f\n",1/r);
2958 
2959  for(i=0;i<l;i++)
2960  alpha[i] *= y[i]/r;
2961 
2962  si->rho /= r;
2963  si->obj /= (r*r);
2964  si->upper_bound_p = 1/r;
2965  si->upper_bound_n = 1/r;
2966 
2967  delete[] y;
2968  delete[] zeros;
2969 } /* solve_nu_svc */
2970 
2971 
2972 
2973 static void SVM233::solve_one_class (const svm_problem* prob,
2974  const svm_parameter* param,
2975  double* alpha,
2976  Solver::SolutionInfo* si
2977  )
2978 {
2979  kkint32 l = prob->l;
2980  double *zeros = new double[l];
2981  schar *ones = new schar[l];
2982  kkint32 i;
2983 
2984  kkint32 n = (kkint32)(param->nu*prob->l); // # of alpha's at upper bound
2985 
2986  for(i=0;i<n;i++)
2987  alpha[i] = 1;
2988  alpha[n] = param->nu * prob->l - n;
2989  for(i=n+1;i<l;i++)
2990  alpha[i] = 0;
2991 
2992  for(i=0;i<l;i++)
2993  {
2994  zeros[i] = 0;
2995  ones[i] = 1;
2996  }
2997 
2998  Solver s;
2999  s.Solve(l, ONE_CLASS_Q(*prob,*param), zeros, ones,
3000  alpha, 1.0, 1.0, param->eps, si, param->shrinking);
3001 
3002  delete[] zeros;
3003  delete[] ones;
3004 } /* solve_one_class */
3005 
3006 
3007 
3008 static void SVM233::solve_epsilon_svr (const svm_problem* prob,
3009  const svm_parameter* param,
3010  double* alpha,
3011  Solver::SolutionInfo* si
3012  )
3013 {
3014  kkint32 l = prob->l;
3015  double *alpha2 = new double[2*l];
3016  double *linear_term = new double[2*l];
3017  schar *y = new schar[2*l];
3018  kkint32 i;
3019 
3020  for(i=0;i<l;i++)
3021  {
3022  alpha2[i] = 0;
3023  linear_term[i] = param->p - prob->y[i];
3024  y[i] = 1;
3025 
3026  alpha2[i+l] = 0;
3027  linear_term[i+l] = param->p + prob->y[i];
3028  y[i+l] = -1;
3029  }
3030 
3031  Solver s;
3032  s.Solve(2 * l,
3033  SVR_Q (*prob,*param),
3034  linear_term,
3035  y,
3036  alpha2,
3037  param->C,
3038  param->C,
3039  param->eps,
3040  si,
3041  param->shrinking
3042  );
3043 
3044  double sum_alpha = 0;
3045  for(i=0;i<l;i++)
3046  {
3047  alpha[i] = alpha2[i] - alpha2[i+l];
3048  sum_alpha += fabs(alpha[i]);
3049  }
3050  info("nu = %f\n",sum_alpha/(param->C*l));
3051 
3052  delete[] alpha2;
3053  delete[] linear_term;
3054  delete[] y;
3055 }
3056 
3057 
3058 
3059 static void SVM233::solve_nu_svr (const svm_problem* prob,
3060  const svm_parameter* param,
3061  double* alpha,
3062  Solver::SolutionInfo* si
3063  )
3064 {
3065  kkint32 l = prob->l;
3066  double C = param->C;
3067  double *alpha2 = new double[2*l];
3068  double *linear_term = new double[2*l];
3069  schar *y = new schar[2*l];
3070  kkint32 i;
3071 
3072  double sum = C * param->nu * l / 2;
3073  for(i=0;i<l;i++)
3074  {
3075  alpha2[i] = alpha2[i+l] = min(sum,C);
3076  sum -= alpha2[i];
3077 
3078  linear_term[i] = - prob->y[i];
3079  y[i] = 1;
3080 
3081  linear_term[i+l] = prob->y[i];
3082  y[i+l] = -1;
3083  }
3084 
3085  Solver_NU s;
3086  s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
3087  alpha2, C, C, param->eps, si, param->shrinking);
3088 
3089  info("epsilon = %f\n",-si->r);
3090 
3091  for (i = 0; i < l; i++)
3092  {
3093  alpha[i] = alpha2[i] - alpha2[i + l];
3094  }
3095 
3096  delete[] alpha2;
3097  delete[] linear_term;
3098  delete[] y;
3099 }
3100 
3101 
3102 
3103 
3104 
3105 
3106 
3108  const svm_parameter* param
3109  )
3110 {
3111  double *alpha = Malloc(double,prob->l);
3112  Solver::SolutionInfo si;
3113  switch(param->svm_type)
3114  {
3115  case C_SVC:
3116  solve_c_svc (prob, param, alpha,&si, prob->W);
3117  break;
3118  }
3119 
3120  info("obj = %f, rho = %f\n",si.obj,si.rho);
3121 
3122  // output SVs
3123 
3124  kkint32 nSV = 0;
3125  kkint32 nBSV = 0;
3126  for (kkint32 i = 0; i < prob->l; i++)
3127  {
3128  if (fabs (alpha[i]) > 0)
3129  {
3130  ++nSV;
3131  if (prob->y[i] > 0)
3132  {
3133  if (fabs (alpha[i]) >= prob->W[i])
3134  ++nBSV;
3135  }
3136  else
3137  {
3138  if (fabs(alpha[i]) >= prob->W[i])
3139  ++nBSV;
3140  }
3141  }
3142  }
3143 
3144  info("nSV = %d, nBSV = %d\n",nSV,nBSV);
3145 
3147  f.alpha = alpha;
3148  f.rho = si.rho;
3149  return f;
3150 } /* svm_train_one */
3151 
3152 
3153 
3154 decision_function SVM233::svm_train_one (const svm_problem* prob,
3155  const svm_parameter* param,
3156  double Cp,
3157  double Cn,
3158  std::set<kkint32>& BSVIndex
3159  )
3160 {
3161  double *alpha = Malloc (double, prob->l);
3162  Solver::SolutionInfo si;
3163  switch(param->svm_type)
3164  {
3165  case C_SVC:
3166  solve_c_svc (prob, param, alpha, &si, Cp, Cn);
3167  break;
3168 
3169  case NU_SVC:
3170  solve_nu_svc(prob,param,alpha,&si);
3171  break;
3172 
3173  case ONE_CLASS:
3174  solve_one_class(prob,param,alpha,&si);
3175  break;
3176 
3177  case EPSILON_SVR:
3178  solve_epsilon_svr(prob,param,alpha,&si);
3179  break;
3180 
3181  case NU_SVR:
3182  solve_nu_svr(prob,param,alpha,&si);
3183  break;
3184  }
3185 
3186  info("obj = %f, rho = %f\n",si.obj,si.rho);
3187 
3188  // output SVs
3189 
3190  std::vector<kkint32> SVIndex;
3191 
3192  kkint32 nSV = 0;
3193  kkint32 nBSV = 0;
3194 
3195  for (kkint32 i = 0; i < prob->l; i++)
3196  {
3197  if (fabs(alpha[i]) > 0)
3198  {
3199  ++nSV;
3200  SVIndex.push_back (i);
3201  if (prob->y[i] > 0)
3202  {
3203  if (fabs (alpha[i]) >= si.upper_bound_p)
3204  {
3205  ++nBSV;
3206  BSVIndex.insert (prob->index[i]);
3207  }
3208  }
3209  else
3210  {
3211  if (fabs(alpha[i]) >= si.upper_bound_n)
3212  {
3213  ++nBSV;
3214  BSVIndex.insert (prob->index[i]);
3215  }
3216  }
3217  }
3218  }
3219 
3220  info("nSV = %d, nBSV = %d\n",nSV,nBSV);
3221 
3222  double sum=0.0;
3223  std::vector<kkint32>::iterator it,it2;
3224 
3225  for (it = SVIndex.begin(); it < SVIndex.end(); it++)
3226  {
3227  for (it2 = SVIndex.begin(); it2 < SVIndex.end(); it2++)
3228  {
3229  kkint32 k = *it;
3230  kkint32 kk = *it2;
3231 
3232  double kvalue;
3233 
3234  if (param->dimSelect > 0)
3235  {
3236  kvalue = Kernel::k_function_subspace (prob->x[k],
3237  prob->x[kk],
3238  *param,
3239  param->featureWeight
3240  );
3241  }
3242  else
3243  {
3244  kvalue = Kernel::k_function(prob->x[k], prob->x[kk], *param);
3245  }
3246 
3247  sum+= prob->y[k]*prob->y[kk]*alpha[k]*alpha[kk]*kvalue;
3248  }
3249  }
3250 
3251  sum /= SVIndex.size();
3252  sum = sqrt(sum);
3253 
3254  for (it = SVIndex.begin(); it < SVIndex.end(); it++)
3255  {
3256  alpha[*it] /= sum;
3257  }
3258 
3259  si.rho /= sum;
3260 
3262 
3263  f.alpha = alpha;
3264  f.rho = si.rho;
3265  return f;
3266 } /* svm_train_one */
3267 
3268 
3269 
3270 
3271 
3272 //
3273 // Interface functions
3274 //
3275 
3276 SvmModel233* SVM233::svm_train (const svm_problem* prob,
3277  const svm_parameter* param
3278  )
3279 {
3280  //SvmModel233 *model = Malloc(SvmModel233,1);
3281 
3282  SvmModel233 *model = new SvmModel233();
3283  //memset(model, 0, sizeof(SvmModel233)); - KNS
3284  model->param = *param;
3285  model->dim =0;
3286 
3287  if (param->dimSelect > 0)
3288  {
3289  model->dim=param->dim;
3290  model->featureWeight = new double[model->dim];
3291  std::copy (param->featureWeight,
3292  param->featureWeight + model->dim,
3293  model->featureWeight
3294  );
3295  }
3296 
3297  if (param->svm_type == ONE_CLASS ||
3298  param->svm_type == EPSILON_SVR ||
3299  param->svm_type == NU_SVR
3300  )
3301  {
3302  // regression or one-class-svm
3303  model->nr_class = 2;
3304  model->label = NULL;
3305  model->nSV = NULL;
3306  model->sv_coef = Malloc(double *,1);
3307  decision_function f = svm_train_one (prob, param, 0, 0, model->BSVIndex);
3308  model->rho = Malloc(double, 1);
3309  model->rho[0] = f.rho;
3310 
3311  kkint32 nSV = 0;
3312  kkint32 i;
3313 
3314  for (i = 0; i < prob->l; i++)
3315  if (fabs (f.alpha[i]) > 0) ++nSV;
3316 
3317  model->l = nSV;
3318  model->SV = Malloc(svm_node *,nSV);
3319 
3320  //luo add
3321  model->numNonSV = prob->l - nSV;
3322  model->nonSVIndex = Malloc(kkint32, model->numNonSV);
3323  model->SVIndex=Malloc(kkint32, nSV);
3324  //model->rest=Malloc(svm_node *,model->numRest);
3325  //luo
3326  model->sv_coef[0] = Malloc (double, nSV);
3327  kkint32 j = 0;
3328  kkint32 jj=0;
3329  for (i = 0; i < prob->l; i++)
3330  {
3331  if (fabs (f.alpha[i]) > 0)
3332  {
3333  model->SVIndex[j] = prob->index[i]; //luo add
3334  model->SV[j] = prob->x[i];
3335  model->sv_coef[0][j] = f.alpha[i];
3336  ++j;
3337  }
3338  else
3339  {
3340  model->nonSVIndex[jj++]=prob->index[i]; //luo add
3341  }
3342  }
3343 
3344  free(f.alpha);
3345  }
3346  else
3347  {
3348  // classification
3349  // find out the number of classes
3350  kkint32 l = prob->l;
3351  kkint32 max_nr_class = 16;
3352  kkint32 nr_class = 0;
3353  kkint32 *label = Malloc(kkint32,max_nr_class);
3354  kkint32 *count = Malloc(kkint32,max_nr_class);
3355  kkint32 *index = Malloc(kkint32, l);
3356 
3357  bool weHaveExampleNames = ((kkint32)prob->exampleNames.size () >= prob->l);
3358 
3359  kkint32 i;
3360  for (i = 0; i < l; i++)
3361  {
3362  kkint32 this_label = (kkint32)prob->y[i];
3363  kkint32 j;
3364  for (j = 0; j < nr_class; j++)
3365  {
3366  if (this_label == label[j])
3367  {
3368  ++count[j];
3369  break;
3370  }
3371  }
3372 
3373  index[i] = j;
3374  if (j == nr_class)
3375  {
3376  if (nr_class == max_nr_class)
3377  {
3378  max_nr_class *= 2;
3379  label = (kkint32 *)realloc(label,max_nr_class*sizeof(kkint32));
3380  count = (kkint32 *)realloc(count,max_nr_class*sizeof(kkint32));
3381  }
3382  label[nr_class] = this_label;
3383  count[nr_class] = 1;
3384  ++nr_class;
3385  }
3386  }
3387 
3388  // group training data of the same class
3389 
3390  kkint32 *start = Malloc (kkint32, nr_class);
3391  start[0] = 0;
3392  for (i = 1; i < nr_class; i++)
3393  start[i] = start[i-1] + count[i-1];
3394 
3395 
3396  svm_node **x = Malloc(svm_node *,l);
3397  double *W = NULL;
3398  if (prob->W != NULL)
3399  W = Malloc(double, l);
3400  std::vector<kkint32> reindex(l);
3401 
3402  for (i = 0; i < l; i++)
3403  {
3404  x[start[index[i]]] = prob->x[i];
3405  reindex[start[index[i]]] = prob->index[i];
3406  if (W != NULL)
3407  W[start[index[i]]] = prob->W[i];
3408  ++start[index[i]];
3409  }
3410 
3411  start[0] = 0;
3412  for (i = 1; i < nr_class; i++)
3413  start[i] = start[i - 1] + count[i - 1];
3414 
3415  // calculate weighted C
3416 
3417  double *weighted_C = Malloc(double, nr_class);
3418  for (i = 0; i < nr_class; i++)
3419  weighted_C[i] = param->C;
3420 
3421  for(i = 0; i < param->nr_weight; i++)
3422  {
3423  kkint32 j;
3424 
3425  for (j = 0; j < nr_class; j++)
3426  if (param->weight_label[i] == label[j])
3427  break;
3428 
3429  if (j == nr_class)
3430  fprintf (stderr,"warning: class label %d specified in weight is not found\n", param->weight_label[i]);
3431  else
3432  weighted_C[j] *= param->weight[i];
3433  }
3434 
3435  // train n*(n-1)/2 models
3436 
3437  bool *nonzero = Malloc(bool,l);
3438  for(i=0;i<l;i++)
3439  nonzero[i] = false;
3440 
3441  decision_function *f = Malloc(decision_function,nr_class*(nr_class-1)/2);
3442 
3443  kkint32 p = 0;
3444  for(i=0;i<nr_class;i++)
3445  {
3446  for(kkint32 j=i+1;j<nr_class;j++)
3447  {
3448  svm_problem sub_prob;
3449  //memset(&sub_prob, 0, sizeof(sub_prob)); // kak
3450 
3451  kkint32 si = start[i], sj = start[j];
3452  kkint32 ci = count[i], cj = count[j];
3453  sub_prob.l = ci+cj;
3454  sub_prob.x = Malloc(svm_node *,sub_prob.l);
3455  sub_prob.y = Malloc(double, sub_prob.l);
3456  if (W != NULL)
3457  sub_prob.W = Malloc(double, sub_prob.l);
3458  sub_prob.index = Malloc(kkint32, sub_prob.l);
3459 
3460  kkint32 k;
3461  for(k=0;k<ci;k++)
3462  {
3463  sub_prob.x[k] = x[si+k];
3464  sub_prob.y[k] = +1;
3465  if (W != NULL)
3466  sub_prob.W[k] = W[si+k];
3467  sub_prob.index[k]=reindex[si+k];
3468  }
3469  for(k=0;k<cj;k++)
3470  {
3471  sub_prob.x[ci+k] = x[sj+k];
3472  sub_prob.y[ci+k] = -1;
3473  if (W != NULL)
3474  sub_prob.W[ci+k] = W[sj+k];
3475  sub_prob.index[ci+k]=reindex[sj+k];
3476  }
3477 
3478  if (W != NULL)
3479  f[p] = svm_train_one(&sub_prob, param);
3480  else
3481  f[p] = svm_train_one(&sub_prob,param,weighted_C[i],weighted_C[j],model->BSVIndex);
3482 
3483  //printf ("svm Training Classes %d[%d] and %d[%d]\n",
3484  // label[i], count[i],
3485  // label[j], count[j]
3486  // );
3487 
3488  fflush (stdout);
3489 
3490  // KNS - I believe this line is what was causing the training time to double
3491  // f[p] = svm_train_one(&sub_prob,param,weighted_C[i],weighted_C[j],model->BSVIndex);
3492 
3493  for (k = 0; k < ci; k++)
3494  {
3495  if(!nonzero[si+k] && fabs(f[p].alpha[k]) > 0)
3496  nonzero[si+k] = true;
3497  }
3498 
3499  for (k = 0; k < cj; k++)
3500  {
3501  if (!nonzero[sj+k] && fabs(f[p].alpha[ci+k]) > 0)
3502  nonzero[sj+k] = true;
3503  }
3504 
3505  free(sub_prob.x);
3506  free(sub_prob.y);
3507  if (sub_prob.W != NULL)
3508  free(sub_prob.W);
3509  free(sub_prob.index);
3510  ++p;
3511  }
3512  }
3513  // build output
3514 
3515 
3516  model->nr_class = nr_class;
3517 
3518  model->label = Malloc (kkint32, nr_class);
3519  for (i = 0; i < nr_class; i++)
3520  model->label[i] = label[i];
3521 
3522  model->rho = Malloc (double, nr_class*(nr_class-1)/2);
3523  for (i = 0; i < nr_class * (nr_class - 1) / 2; i++)
3524  model->rho[i] = f[i].rho;
3525 
3526  kkint32 total_sv = 0;
3527  kkint32 *nz_count = Malloc (kkint32,nr_class);
3528  model->nSV = Malloc (kkint32,nr_class);
3529  for (i=0; i < nr_class; i++)
3530  {
3531  kkint32 nSV = 0;
3532  for (kkint32 j = 0; j < count[i]; j++)
3533  {
3534  if (nonzero[start[i]+j])
3535  {
3536  ++nSV;
3537  ++total_sv;
3538  }
3539  model->nSV[i] = nSV;
3540  nz_count[i] = nSV;
3541  }
3542  }
3543 
3544  info("Total nSV = %d\n",total_sv);
3545 
3546  model->l = total_sv;
3547  model->SV = Malloc (svm_node *,total_sv);
3548  model->exampleNames.clear ();
3549 
3550  if (weHaveExampleNames)
3551  {
3552  for (kkint32 zed = 0; zed < total_sv; zed++)
3553  model->exampleNames.push_back ("");
3554  }
3555 
3556 
3557  //luo add
3558  kkint32 pp=0;
3559  model->numNonSV = l - total_sv;
3560  model->SVIndex = Malloc(kkint32, total_sv);
3561  model->nonSVIndex = Malloc(kkint32, model->numNonSV);
3562 
3563  //model->numRest = l - total_sv;
3564  //model->rest=Malloc(svm_node *, model->numRest);
3565  //luo
3566 
3567  p = 0;
3568  for (i = 0; i < l; i++)
3569  {
3570  if (nonzero[i])
3571  {
3572  model->SV[p] = x[i];
3573  model->SVIndex[p]=prob->index[i];//luo add
3574  if (weHaveExampleNames)
3575  model->exampleNames[p] = prob->exampleNames[i];
3576  p++;
3577  }
3578  else
3579  {
3580  //model->rest[pp++]=x[i];
3581  model->nonSVIndex[pp] = prob->index[i];
3582  pp++;
3583  }
3584  }
3585 
3586  kkint32 *nz_start = Malloc (kkint32,nr_class);
3587  nz_start[0] = 0;
3588  for(i=1;i<nr_class;i++)
3589  nz_start[i] = nz_start[i-1]+nz_count[i-1];
3590 
3591  model->sv_coef = Malloc(double *,nr_class-1);
3592  for(i=0;i<nr_class-1;i++)
3593  {
3594  model->sv_coef[i] = Malloc(double,total_sv);
3595  for (kkint32 zed = 0; zed < total_sv; zed++)
3596  model->sv_coef[i][zed] = 0.0;
3597  }
3598 
3599  p = 0;
3600  for (i = 0; i < nr_class; i++)
3601  for (kkint32 j = i + 1; j < nr_class; j++)
3602  {
3603  // classifier (i,j): coefficients with
3604  // i are in sv_coef[j-1][nz_start[i]...],
3605  // j are in sv_coef[i][nz_start[j]...]
3606 
3607  kkint32 si = start[i];
3608  kkint32 sj = start[j];
3609  kkint32 ci = count[i];
3610  kkint32 cj = count[j];
3611 
3612  kkint32 q = nz_start[i];
3613  kkint32 k;
3614  for (k = 0; k < ci; k++)
3615  if (nonzero[si + k])
3616  {
3617  if (model->sv_coef[j-1][q] != 0.0)
3618  {
3619  cerr << endl << endl
3620  << "svm_train ***ERROR*** Alpha Valude Being Overwritten." << endl
3621  << endl;
3622  }
3623  model->sv_coef[j - 1][q++] = f[p].alpha[k];
3624  }
3625  q = nz_start[j];
3626  for(k=0;k<cj;k++)
3627  {
3628  if(nonzero[sj+k])
3629  {
3630  if (model->sv_coef[i][q] != 0.0)
3631  {
3632  cerr << endl << endl
3633  << "svm_train ***ERROR*** Alpha Valude Being Overwritten." << endl
3634  << endl;
3635  }
3636  model->sv_coef[i][q++] = f[p].alpha[ci + k];
3637  }
3638  }
3639  ++p;
3640  }
3641 
3642  free(label);
3643  free(count);
3644  free(index);
3645  free(start);
3646  if (W != NULL)
3647  free(W);
3648  free(x);
3649  free(weighted_C);
3650  free(nonzero);
3651  for(i=0;i<nr_class*(nr_class-1)/2;i++)
3652  free(f[i].alpha);
3653  free(f);
3654  free(nz_count);
3655  free(nz_start);
3656 
3657  // KNS - this was commecnted out in the pre-BR svm
3658  // svm_margin(model);
3659 
3660  model->kValueTable = new double[model->l];
3661  }
3662 
3663  //svm_margin (model);
3664  return model;
3665 } /* svm_train */
3666 
3667 
3668 
3669 
3670 
3671 
3673 {
3674  return model->nr_class;
3675 }
3676 
3677 
3678 
3679 void svm_get_labels(const SvmModel233 *model, kkint32* label)
3680 {
3681  for (kkint32 i = 0; i < model->nr_class; i++)
3682  label[i] = model->label[i];
3683 }
3684 
3685 
3686 
3687 const char *svm_type_table[] =
3688 {
3689  "c_svc","nu_svc","one_class","epsilon_svr","nu_svr",NULL
3690 };
3691 
3692 
3693 
3694 const char *kernel_type_table[]=
3695 {
3696  "linear","polynomial","rbf","sigmoid",NULL
3697 };
3698 
3699 
3700 
3701 void SVM233::Svm_Save_Model (ostream& o,
3702  const SvmModel233* model
3703  )
3704 {
3705  const svm_parameter& param = model->param;
3706 
3707  kkint32 nr_class = model->nr_class;
3708  kkint32 numberOfBinaryClassifiers = nr_class * (nr_class - 1) / 2;
3709 
3710  kkint32 origPrecision = (kkint32)o.precision ();
3711  o.precision (14);
3712 
3713  o << "<Svm233>" << endl;
3714 
3715  o << "Parameters" << "\t" << param.ToTabDelStr () << endl;
3716  o << "NumOfClasses" << "\t" << nr_class << endl;
3717 
3718  kkint32 totalNumSVs = model->l;
3719  o << "TotalNumOfSupportVectors" << "\t" << totalNumSVs << endl;
3720 
3721  {
3722  o << "rho";
3723  for (kkint32 i = 0; i < numberOfBinaryClassifiers; i++)
3724  o << "\t" << model->rho[i];
3725  o << endl;
3726  }
3727 
3728  if (model->margin)
3729  {
3730  kkint32 oldPrecision = (kkint32)o.precision ();
3731  o.precision (9);
3732  o << "Margins";
3733  for (kkint32 i = 0; i < numberOfBinaryClassifiers; i++)
3734  o << "\t" << model->margin[i];
3735  o << endl;
3736  o.precision (oldPrecision);
3737  }
3738 
3739  if (model->label)
3740  {
3741  o << "label";
3742  for (kkint32 i = 0; i < nr_class; i++)
3743  o << "\t" << model->label[i];
3744  o << endl;
3745  }
3746 
3747  if (model->nSV)
3748  {
3749  o << "nr_sv";
3750  for (kkint32 i = 0; i < nr_class; i++)
3751  o << "\t" << model->nSV[i];
3752  o << endl;
3753  }
3754 
3755  const double * const *sv_coef = model->sv_coef;
3756  const svm_node * const *SV = model->SV;
3757 
3758  {
3759  // Determine total number of elememts
3760  kkint32 totalNumOfElements = 0;
3761  for (kkint32 i = 0; i < totalNumSVs; i++)
3762  {
3763  const svm_node *p = SV[i];
3764  while (p->index != -1)
3765  {
3766  totalNumOfElements++;
3767  p++;
3768  }
3769 
3770  totalNumOfElements++; // Add one for terminating node
3771  }
3772  o << "TOTALNUMOFELEMENTS" << "\t" << totalNumOfElements << endl;
3773  }
3774 
3775  for (kkint32 i = 0; i < totalNumSVs; i++)
3776  {
3777  if ((kkint32)model->exampleNames.size () > i)
3778  o << "SuportVectorNamed" << "\t" << model->exampleNames[i];
3779  else
3780  o << "SuportVector";
3781 
3782  o.precision (16);
3783  for (kkint32 j = 0; j < nr_class - 1; j++)
3784  o << "\t" << sv_coef[j][i];
3785 
3786  const svm_node *p = SV[i];
3787  while (p->index != -1)
3788  {
3789  o << "\t" << p->index << ":" << p->value;
3790  p++;
3791  }
3792 
3793  o << endl;
3794  }
3795 
3796 
3797  o << "</Svm233>" << endl;
3798 
3799  o.precision (origPrecision);
3800  } /* Svm_Save_Model */
3801 
3802 
3803 
3804 
3805 struct SvmModel233* SVM233::Svm_Load_Model (istream& f,
3806  RunLog& log
3807  )
3808 {
3809  SvmModel233* model = new SvmModel233 ();
3810 
3811  kkint32 bullAllocSize = 500000;
3812  char* buff = new char[bullAllocSize];
3813 
3814  kkint32 numOfClasses = -1;
3815  kkint32 numSVsLoaded = 0;
3816  kkint32 numElementsLoaded = 0;
3817  kkint32 totalNumSVs = -1;
3818  kkint32 totalNumOfElements = -1;
3819  svm_node* x_space = NULL;
3820 
3821 
3822  bool validFormat = true;
3823 
3824  KKStr line (1024); // Preallocating to at least 1024 characters.
3825 
3826  // Get first non blank line. It had better contain "<Smv239>" otherwise we will consider this
3827  // an invalid Training Model.
3828  {
3829  while (f.getline (buff, bullAllocSize))
3830  {
3831  line = buff;
3832  line.TrimLeft ("\n\r\t ");
3833  line.TrimRight ("\n\r\t ");
3834 
3835  if ((line.Len () > 0) && (line.SubStrPart (0, 1) != "//"))
3836  {
3837  // We have our first 'non blank' 'non commented line'
3838  break;
3839  }
3840  }
3841  }
3842 
3843  if (!line.EqualIgnoreCase ("<Svm233>"))
3844  {
3845  // We do not have a valid SVM239 model. We will return a NULL
3846  log.Level (-1) << endl << endl
3847  << "SVM233::Svm_Load_Model ***ERROR*** The '<Svm233>' header is missing. Not a valid model." << endl
3848  << endl;
3849  delete model; model = NULL;
3850  delete[] buff; buff = NULL;
3851  return NULL;
3852  }
3853 
3854  /**
3855  @todo Modify SVM233::Svm_Load_Model to read one token at a time rather than a whol eline at a time.
3856  */
3857 
3858  while (f.getline (buff, bullAllocSize))
3859  {
3860  KKStrParser line (buff);
3861  line.SkipWhiteSpace (" ");
3862 
3863  KKStr lineName = line.GetNextToken ();
3864 
3865  if (lineName.EqualIgnoreCase ("<SvmMachine>"))
3866  continue;
3867 
3868  if (lineName.EqualIgnoreCase ("</Svm233>"))
3869  break;
3870 
3871  lineName.Upper ();
3872 
3873  if (lineName == "PARAMETERS")
3874  {
3875  model->param.ParseTabDelStr (line.GetRestOfLine ());
3876  }
3877 
3878  else if (lineName == "NUMOFCLASSES")
3879  {
3880  numOfClasses = line.GetNextTokenInt ("\t");
3881  model->nr_class = numOfClasses;
3882  }
3883 
3884  else if (lineName == "TOTALNUMOFSUPPORTVECTORS")
3885  {
3886  totalNumSVs = line.GetNextTokenInt ("\t");
3887  model->l = totalNumSVs;
3888  }
3889 
3890  else if (lineName == "RHO")
3891  {
3892  kkint32 n = numOfClasses * (numOfClasses - 1) / 2;
3893  model->rho = Malloc (double, n);
3894  for (kkint32 i = 0; i < n; i++)
3895  model->rho[i] = line.GetNextTokenDouble ("\t");
3896  }
3897 
3898  else if (lineName == "LABEL")
3899  {
3900  model->label = Malloc (kkint32, numOfClasses);
3901  for (kkint32 i=0; i < numOfClasses; i++)
3902  model->label[i] = line.GetNextTokenInt ("\t");
3903  }
3904 
3905 
3906  else if (lineName == "NR_SV")
3907  {
3908  model->nSV = Malloc(kkint32, numOfClasses);
3909  for (kkint32 i = 0; i < numOfClasses; i++)
3910  model->nSV[i] = line.GetNextTokenInt ("\t");
3911  }
3912 
3913 
3914  else if (lineName.EqualIgnoreCase ("Margins"))
3915  {
3916  kkint32 n = numOfClasses * (numOfClasses - 1) / 2;
3917  delete model->margin;
3918  model->margin = new double[n];
3919  for (kkint32 i = 0; i < n; i++)
3920  model->margin[i] = line.GetNextTokenDouble ("\t");
3921  }
3922 
3923  else if (lineName == "TOTALNUMOFELEMENTS")
3924  {
3925  totalNumOfElements = line.GetNextTokenInt ("\t");
3926 
3927  kkint32 m = model->nr_class - 1;
3928  kkint32 l = model->l;
3929  model->sv_coef = Malloc (double*, m);
3930 
3931  for (kkint32 i = 0; i < m; i++)
3932  model->sv_coef[i] = Malloc (double, l);
3933 
3934  model->SV = Malloc (svm_node*, l);
3935  x_space = new svm_node[totalNumOfElements];
3936  model->xSpace = x_space;
3937  model->weOwnXspace = true; // 'model' owns 'x_space' and will be responsible for deleting it.
3938  }
3939 
3940  else if (lineName.EqualIgnoreCase ("SUPORTVECTOR") || lineName.EqualIgnoreCase ("SuportVectorNamed"))
3941  {
3942  if (numSVsLoaded >= totalNumSVs)
3943  {
3944  log.Level (-1) << endl << endl << endl
3945  << "SvmLoadModel **** ERROR **** There are more 'SupportVector' lines defined that there should be." << endl
3946  << endl;
3947  validFormat = false;
3948  break;
3949  }
3950 
3951  if (totalNumOfElements < 1)
3952  {
3953  log.Level (-1) << endl << endl << endl
3954  << "SvmLoadModel **** ERROR **** 'totalNumOfElements' was not defined." << endl
3955  << endl;
3956  validFormat = false;
3957  break;
3958  }
3959 
3960  if (lineName.EqualIgnoreCase ("SuportVectorNamed"))
3961  {
3962  // this Support Vector has a mame to it.
3963  model->exampleNames.push_back (line.GetNextToken ("\t"));
3964  }
3965 
3966  for (kkint32 j = 0; j < numOfClasses - 1; j++)
3967  model->sv_coef[j][numSVsLoaded] = line.GetNextTokenDouble ("\t");
3968 
3969  model->SV[numSVsLoaded] = &(x_space[numElementsLoaded]);
3970  while ((line.MoreTokens ()) && (numElementsLoaded < (totalNumOfElements - 1)))
3971  {
3972  x_space[numElementsLoaded].index = line.GetNextTokenInt (":");
3973  x_space[numElementsLoaded].value = line.GetNextTokenDouble ("\t");
3974  numElementsLoaded++;
3975  }
3976 
3977  if (numElementsLoaded >= totalNumOfElements)
3978  {
3979  log.Level (-1) << endl << endl << endl
3980  << "SvmLoadModel **** ERROR **** 'numElementsLoaded' is greater than what was defined by 'totalNumOfElements'." << endl
3981  << endl;
3982  validFormat = false;
3983  break;
3984  }
3985 
3986  x_space[numElementsLoaded].index = -1;
3987  x_space[numElementsLoaded].value = 0.0;
3988  numElementsLoaded++;
3989 
3990  numSVsLoaded++;
3991  }
3992  }
3993 
3994  if (validFormat)
3995  {
3996  if (numSVsLoaded != totalNumSVs)
3997  {
3998  log.Level (-1) << endl << endl << endl
3999  << "SvmLoadModel ***ERROR*** numSVsLoaded[" << numSVsLoaded << "] does not agree with totalNumSVs[" << totalNumSVs << "]" << endl
4000  << endl;
4001  validFormat = false;
4002  }
4003 
4004  if (numElementsLoaded != totalNumOfElements)
4005  {
4006  log.Level (-1) << endl << endl << endl
4007  << "SvmLoadModel ***ERROR*** numElementsLoaded[" << numElementsLoaded << "] does not agree with totalNumOfElements[" << totalNumOfElements << "]" << endl
4008  << endl;
4009  validFormat = false;
4010  }
4011 
4012  else if (numOfClasses < 1)
4013  {
4014  log.Level (-1) << endl << endl << endl
4015  << "SvmLoadModel ***ERROR*** numOfClasses was not specified." << endl
4016  << endl;
4017  validFormat = false;
4018  }
4019  }
4020 
4021  if (!validFormat)
4022  {
4023  if (model)
4024  {
4025  delete model;
4026  model = NULL;
4027  }
4028  }
4029 
4030  if (model)
4031  model->kValueTable = new double[model->l];
4032 
4033 
4034  delete[] buff;
4035  buff = NULL;
4036 
4037  return model;
4038 } /* Svm_Load_Model */
4039 
4040 
4041 
4042 /****************************************************************************************/
4043 double SVM233::svm_predict (const SvmModel233* model,
4044  const svm_node* x,
4045  std::vector<double>& dist,
4046  std::vector<kkint32>& winners,
4047  kkint32 excludeSupportVectorIDX /*!< Specify index of a S/V to remove from computation. */
4048  )
4049 {
4050  kkint32 dimSelect = model->param.dimSelect;
4051 
4052  winners.erase (winners.begin (), winners.end ());
4053 
4054  if (model->param.svm_type == ONE_CLASS ||
4055  model->param.svm_type == EPSILON_SVR ||
4056  model->param.svm_type == NU_SVR
4057  )
4058  {
4059  double* sv_coef = model->sv_coef[0];
4060  double sum = 0;
4061 
4062  for (kkint32 i=0; i < model->l; i++)
4063  {
4064  if (i == excludeSupportVectorIDX)
4065  continue;
4066 
4067  if (dimSelect>0)
4068  sum += sv_coef[i] * Kernel::k_function_subspace (x, model->SV[i], model->param, model->featureWeight);
4069  else
4070  sum += sv_coef[i] * Kernel::k_function (x, model->SV[i], model->param);
4071  }
4072 
4073  sum -= model->rho[0];
4074 
4075  double returnVal = 0.0;
4076 
4077  if (model->param.svm_type == ONE_CLASS)
4078  returnVal = (sum > 0) ? 1:-1;
4079  else
4080  returnVal = sum;
4081 
4082  winners.push_back ((kkint32)returnVal);
4083  return returnVal;
4084  }
4085  else
4086  {
4087  kkint32 i;
4088  kkint32 nr_class = model->nr_class;
4089 
4090  std::vector<kkint32> voteTable (nr_class * nr_class, 0);
4091  kkint32 l = model->l;
4092 
4093 
4094  double* kvalue = model->kValueTable;
4095 
4096  // Precompute S/V's for all classes.
4097  for (i=0; i<l; i++)
4098  {
4099  if (i == excludeSupportVectorIDX)
4100  {
4101  kvalue[i] = 0.0;
4102  }
4103  else
4104  {
4105  if (dimSelect > 0)
4106  kvalue[i] = Kernel::k_function_subspace (x, model->SV[i], model->param, model->featureWeight);
4107  else
4108  kvalue[i] = Kernel::k_function (x, model->SV[i], model->param);
4109  }
4110  }
4111 
4112 
4113  // 'start' will be built to point to the beginning of the list of S'V's for each class.
4114  kkint32 *start = Malloc (kkint32, nr_class);
4115  start[0] = 0;
4116  for (i = 1; i < nr_class; i++)
4117  start[i] = start[i-1] + model->nSV[i-1];
4118 
4119  kkint32 *vote = Malloc (kkint32, nr_class);
4120 
4121  for (i = 0; i < nr_class; i++)
4122  vote[i] = 0;
4123 
4124  kkint32 p = 0;
4125 
4126  std::vector<double> distTable (nr_class * nr_class, 0);
4127 
4128  for (i = 0; i < nr_class; i++)
4129  {
4130  for (kkint32 j = i + 1; j < nr_class; j++)
4131  {
4132  double sum = 0;
4133  kkint32 si = start[i];
4134  kkint32 sj = start[j];
4135  kkint32 ci = model->nSV[i];
4136  kkint32 cj = model->nSV[j];
4137 
4138  kkint32 k;
4139  double *coef1 = model->sv_coef[j-1];
4140  double *coef2 = model->sv_coef[i];
4141 
4142  for (k = 0; k < ci; k++)
4143  sum += coef1[si + k] * kvalue[si + k];
4144 
4145  for (k = 0; k < cj; k++)
4146  sum += coef2[sj + k] * kvalue[sj + k];
4147 
4148  sum -= model->rho[p];
4149 
4150  if (sum > 0)
4151  {
4152  voteTable[i * nr_class + j]++; // i vs. j
4153  ++vote[i];
4154  }
4155  else
4156  {
4157  voteTable[j * nr_class + i]++; // j vs. i
4158  ++vote[j];
4159  }
4160 
4161  kkint32 row = model->label[i];
4162  kkint32 col = model->label[j];
4163 
4164  distTable[row * nr_class + col] = sum;
4165  distTable[col * nr_class + row] = (-1.0 * sum);
4166 
4167  //dist[p] = sum;
4168  p++;
4169  }
4170  }
4171 
4172  p=0;
4173 
4174  { // kk: jun-06-2003
4175 
4176  for (kkint32 i = 0; i < nr_class - 1; i++)
4177  {
4178  for (kkint32 j=i+1; j< nr_class; j++)
4179  {
4180  dist[p++] = distTable[i * nr_class + j];
4181  }
4182  }
4183 
4184  } // kk: jun-06-2003
4185 
4186  winners.erase (winners.begin (), winners.end ());
4187  kkint32 vote_max_idx = 0;
4188  kkint32 winningAmt = vote[0];
4189  winners.push_back (model->label[0]);
4190 
4191  for (i = 1; i < nr_class; i++)
4192  {
4193  if (vote[i] > winningAmt)
4194  {
4195  winners.erase (winners.begin (), winners.end ());
4196  vote_max_idx = i;
4197  winningAmt = vote[i];
4198  winners.push_back (model->label[i]);
4199  }
4200  else if (vote[i] == winningAmt)
4201  {
4202  winners.push_back (model->label[i]);
4203  }
4204  }
4205 
4206  free (start);
4207  free (vote);
4208 
4209  kkint32 winningLabel = model->label[vote_max_idx];
4210 
4211  return winningLabel;
4212  }
4213 } /* svm_predict */
4214 
4215 
4216 
4217 
4219  const svm_node* x,
4220  double& dist,
4221  kkint32 excludeSupportVectorIDX
4222  )
4223 {
4224  kkint32 winner = 0;
4225 
4226  kkint32 dimSelect = model->param.dimSelect;
4227 
4228  if (model->param.svm_type == ONE_CLASS ||
4229  model->param.svm_type == EPSILON_SVR ||
4230  model->param.svm_type == NU_SVR
4231  )
4232  {
4233  double* sv_coef = model->sv_coef[0];
4234  double sum = 0;
4235 
4236  for (kkint32 i=0; i < model->l; i++)
4237  {
4238  if (i == excludeSupportVectorIDX)
4239  continue;
4240 
4241  if (dimSelect > 0)
4242  sum += sv_coef[i] * Kernel::k_function_subspace (x, model->SV[i],model->param, model->featureWeight);
4243  else
4244  sum += sv_coef[i] * Kernel::k_function (x, model->SV[i], model->param);
4245  }
4246 
4247  sum -= model->rho[0];
4248 
4249  double returnVal = 0.0;
4250 
4251  if (model->param.svm_type == ONE_CLASS)
4252  returnVal = (sum > 0) ? 1:-1;
4253  else
4254  returnVal = sum;
4255 
4256  return returnVal;
4257  }
4258  else
4259  {
4260  kkint32 i;
4261 
4262  kkint32 nr_class = model->nr_class;
4263  if (nr_class != 2)
4264  {
4265  cerr << std::endl
4266  << "svm_predictTwoClasses ***ERROR*** nr_class[" << nr_class << "] != 2" << std::endl
4267  << std::endl;
4268  exit (-1);
4269  }
4270 
4271  kkint32 l = model->l;
4272  //double *kvalue = Malloc (double, l);
4273 
4274  double* kvalue = model->kValueTable;
4275 
4276  if (dimSelect > 0)
4277  {
4278  for (i = 0; i < l; i++)
4279  {
4280  if (i == excludeSupportVectorIDX)
4281  kvalue[i] = 0.0;
4282  else
4283  kvalue[i] = Kernel::k_function_subspace (x, model->SV[i], model->param, model->featureWeight);
4284  }
4285  }
4286  else
4287  {
4288  for (i = 0; i < l; i++)
4289  {
4290  if (i == excludeSupportVectorIDX)
4291  kvalue[i] = 0.0;
4292  else
4293  kvalue[i] = Kernel::k_function (x, model->SV[i], model->param);
4294  }
4295  }
4296 
4297  kkint32 start[2];
4298  start[0] = 0;
4299  for (i = 1; i < nr_class; i++)
4300  start[i] = start[i-1] + model->nSV[i-1];
4301 
4302  kkint32 p = 0;
4303 
4304  i = 0;
4305  kkint32 j = 1;
4306  {
4307  double sum = 0;
4308  kkint32 si = start[i];
4309  kkint32 sj = start[j];
4310  kkint32 ci = model->nSV[i];
4311  kkint32 cj = model->nSV[j];
4312 
4313  kkint32 k;
4314  double *coef1 = model->sv_coef[j-1];
4315  double *coef2 = model->sv_coef[i];
4316 
4317  for (k = 0; k < ci; k++)
4318  sum += coef1[si + k] * kvalue[si + k];
4319 
4320  for (k = 0; k < cj; k++)
4321  sum += coef2[sj + k] * kvalue[sj + k];
4322 
4323  sum -= model->rho[p];
4324 
4325  if (sum > 0)
4326  winner = 0;
4327  else
4328  winner = 1;
4329 
4330  dist = sum;
4331 
4332  //if (model->margin)
4333  //{
4334  // if (model->margin[0] != 0.0)
4335  // dist = dist / model->margin[0];
4336  //}
4337  }
4338 
4339  p=0;
4340 
4341  double winningLabel = (double)model->label[winner];
4342 
4343  return winningLabel;
4344  }
4345 } /* svm_predictTwoClasses */
4346 
4347 
4348 
4349 
4350 
4351 
4352 
4353 
4354 
4355 /****************************************************************************************/
4357  kkint32 excludeSupportVectorIDX /*!< Specify index of a S/V to remove from computation. */
4358  )
4359 {
4360  if (model->param.svm_type == ONE_CLASS ||
4361  model->param.svm_type == EPSILON_SVR ||
4362  model->param.svm_type == NU_SVR
4363  )
4364  {
4365  return NULL;
4366  }
4367 
4368  kkint32 nr_class = model->nr_class;
4369  if (nr_class != 2)
4370  {
4371  printf ("\n\n\n svm_predictTwoClasses *** ERROR *** NumOf Classes != 2\n\n");
4372  return NULL;
4373  }
4374 
4375  if (model->dim > 0)
4376  {
4377  cerr << std::endl
4378  << "SVM233::svm_BuildProbFromTwoClassModel ***ERROR*** model->dim[" << model->dim << "] > 0" << std::endl
4379  << std::endl;
4380  return NULL;
4381  }
4382 
4383 
4384  kkint32 l = model->l;
4385  kkint32 numSVsFirstClass = model->nSV[0];
4386 
4387  svm_problem* newProb = new svm_problem ();
4388  newProb->weOwnContents = true;
4389  newProb->l = l;
4390  if ((excludeSupportVectorIDX >= 0) && (excludeSupportVectorIDX < l))
4391  (newProb->l)--;
4392 
4393  newProb->y = new double[newProb->l];
4394  newProb->x = new svm_node*[newProb->l];
4395  newProb->index = new kkint32[newProb->l];
4396 
4397  kkint32 newIDX = 0;
4398  for (kkint32 svIDX = 0; svIDX < l; svIDX++)
4399  {
4400  if (svIDX == excludeSupportVectorIDX)
4401  continue;
4402 
4403  if (svIDX < numSVsFirstClass)
4404  newProb->y[newIDX] = 0;
4405  else
4406  newProb->y[newIDX] = 1;
4407 
4408  newProb->index[newIDX] = newIDX;
4409  newProb->exampleNames.push_back (model->exampleNames[svIDX]);
4410 
4411  {
4412  kkint32 numElements = 0;
4413  svm_node* nextNode = model->SV[svIDX];
4414  while (nextNode->index != -1)
4415  {
4416  numElements++;
4417  nextNode++;
4418  }
4419  numElements++;
4420 
4421  newProb->x[newIDX] = new svm_node[numElements];
4422 
4423  for (kkint32 fnIDX = 0; fnIDX < numElements; fnIDX++)
4424  {
4425  newProb->x[newIDX][fnIDX].index = model->SV[svIDX][fnIDX].index;
4426  newProb->x[newIDX][fnIDX].value = model->SV[svIDX][fnIDX].value;
4427  }
4428  }
4429 
4430  newIDX++;
4431  }
4432 
4433  return newProb;
4434 } /* svm_BuildProbFromTwoClassModel */
4435 
4436 
4437 
4438 
4439 
4440 
4441 
4443 {
4444  delete model;
4445  model = NULL;
4446 }
4447 
4448 
4449 
4450 const char* SVM233::svm_check_parameter (const svm_problem *prob, const svm_parameter *param)
4451 {
4452  // svm_type
4453 
4454  kkint32 svm_type = param->svm_type;
4455  if (svm_type != C_SVC &&
4456  svm_type != NU_SVC &&
4457  svm_type != ONE_CLASS &&
4458  svm_type != EPSILON_SVR &&
4459  svm_type != NU_SVR
4460  )
4461  return "unknown svm type";
4462 
4463  // kernel_type
4464 
4465  kkint32 kernel_type = param->kernel_type;
4466  if (kernel_type != LINEAR &&
4467  kernel_type != POLY &&
4468  kernel_type != RBF &&
4469  kernel_type != SIGMOID
4470  )
4471  return "unknown kernel type";
4472 
4473  // cache_size,eps,C,nu,p,shrinking
4474 
4475  if(param->cache_size <= 0)
4476  return "cache_size <= 0";
4477 
4478  if(param->eps <= 0)
4479  return "eps <= 0";
4480 
4481  if(svm_type == C_SVC ||
4482  svm_type == EPSILON_SVR ||
4483  svm_type == NU_SVR)
4484  if(param->C <= 0)
4485  return "C <= 0";
4486 
4487  if(svm_type == NU_SVC ||
4488  svm_type == ONE_CLASS ||
4489  svm_type == NU_SVR)
4490  if(param->nu < 0 || param->nu > 1)
4491  return "nu < 0 or nu > 1";
4492 
4493  if(svm_type == EPSILON_SVR)
4494  if(param->p < 0)
4495  return "p < 0";
4496 
4497  if(param->shrinking != 0 &&
4498  param->shrinking != 1)
4499  return "shrinking != 0 and shrinking != 1";
4500 
4501 
4502  // check whether nu-svc is feasible
4503 
4504  if(svm_type == NU_SVC)
4505  {
4506  kkint32 l = prob->l;
4507  kkint32 max_nr_class = 16;
4508  kkint32 nr_class = 0;
4509  kkint32 *label = Malloc(kkint32,max_nr_class);
4510  kkint32 *count = Malloc(kkint32,max_nr_class);
4511 
4512  kkint32 i;
4513  for(i=0;i<l;i++)
4514  {
4515  kkint32 this_label = (kkint32)prob->y[i];
4516  kkint32 j;
4517  for(j=0;j<nr_class;j++)
4518  if(this_label == label[j])
4519  {
4520  ++count[j];
4521  break;
4522  }
4523  if(j == nr_class)
4524  {
4525  if(nr_class == max_nr_class)
4526  {
4527  max_nr_class *= 2;
4528  label = (kkint32 *)realloc(label,max_nr_class*sizeof(kkint32));
4529  count = (kkint32 *)realloc(count,max_nr_class*sizeof(kkint32));
4530  }
4531  label[nr_class] = this_label;
4532  count[nr_class] = 1;
4533  ++nr_class;
4534  }
4535  }
4536 
4537  for(i=0;i<nr_class;i++)
4538  {
4539  kkint32 n1 = count[i];
4540  for(kkint32 j=i+1;j<nr_class;j++)
4541  {
4542  kkint32 n2 = count[j];
4543  if(param->nu*(n1+n2)/2 > min(n1,n2))
4544  {
4545  free(label);
4546  free(count);
4547  return "specified nu is infeasible";
4548  }
4549  }
4550  }
4551  }
4552 
4553  return NULL;
4554 } /* svm_check_parameter */
4555 
4556 
4557 
4558 
4559 //luo add compute the distance of the data to the decision boundary, given the
4560 //model and the input, Now it is only work for the binary case.
4561 /*
4562 double SVM233::svm_dist (const SvmModel233* model,
4563  const svm_node* x
4564  )
4565 {
4566  if (model->param.svm_type == ONE_CLASS ||
4567  model->param.svm_type == EPSILON_SVR ||
4568  model->param.svm_type == NU_SVR)
4569  {
4570  double *sv_coef = model->sv_coef[0];
4571  double sum = 0;
4572  for(kkint32 i=0;i<model->l;i++)
4573  sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param);
4574  sum -= model->rho[0];
4575  if(model->param.svm_type == ONE_CLASS)
4576  return (sum>0)?1:-1;
4577  else
4578  return sum;
4579  }
4580  else
4581  {
4582  kkint32 i;
4583  kkint32 nr_class = model->nr_class;
4584  kkint32 l = model->l;
4585 
4586  double *kvalue = Malloc(double,l);
4587  for(i=0;i<l;i++)
4588  kvalue[i] = Kernel::k_function(x,model->SV[i],model->param);
4589 
4590  kkint32 *start = Malloc(kkint32,nr_class);
4591  start[0] = 0;
4592  for(i=1;i<nr_class;i++)
4593  start[i] = start[i-1]+model->nSV[i-1];
4594 
4595  kkint32 *vote = Malloc(kkint32,nr_class);
4596  for(i=0;i<nr_class;i++)
4597  vote[i] = 0;
4598  kkint32 p=0;
4599 
4600  //luo add
4601  double distance=9999;
4602 
4603  for(i=0;i<nr_class;i++)
4604  {
4605  for(kkint32 j=i+1;j<nr_class;j++)
4606  {
4607  double sum = 0;
4608  kkint32 si = start[i];
4609  kkint32 sj = start[j];
4610  kkint32 ci = model->nSV[i];
4611  kkint32 cj = model->nSV[j];
4612 
4613  kkint32 k;
4614  double *coef1 = model->sv_coef[j-1];
4615  double *coef2 = model->sv_coef[i];
4616  for(k=0;k<ci;k++)
4617  sum += coef1[si+k] * kvalue[si+k];
4618  for(k=0;k<cj;k++)
4619  sum += coef2[sj+k] * kvalue[sj+k];
4620  sum -= model->rho[p];
4621  sum /= model->margin[p];
4622 
4623  distance=sum;
4624 
4625  if(sum > 0)
4626  ++vote[i];
4627  else
4628  ++vote[j];
4629 
4630  p++;
4631 
4632  }
4633 
4634 
4635  free(kvalue);
4636  free(start);
4637  free(vote);
4638  //luo add
4639  assert(distance!=9999);
4640  return distance;
4641  }
4642  }
4643 }
4644 //luo
4645 */
4646 
4647 
4648 
4649 
4651 //modify: model
4652 //effects: if classification, model->margin[nr_class*(nr_class-1)/2] is computed
4653 // else if regression, doing nothing
4654 {
4655  //kkint32 numClass=model->param.numClass;
4656 
4657  assert (model);
4658 
4659  if(model->param.svm_type == ONE_CLASS ||
4660  model->param.svm_type == EPSILON_SVR ||
4661  model->param.svm_type == NU_SVR)
4662  {
4663  /*
4664  double *sv_coef = model->sv_coef[0];
4665  double sum = 0;
4666  for(kkint32 i=0;i<model->l;i++)
4667  sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param);
4668  sum -= model->rho[0];
4669  if(model->param.svm_type == ONE_CLASS)
4670  return (sum>0)?1:-1;
4671  else
4672  return sum;
4673  */
4674  }
4675  else
4676  {
4677  kkint32 i;
4678  kkint32 nr_class = model->nr_class;
4679 
4680  model->margin = new double[nr_class * (nr_class - 1) / 2];
4681 
4682  std::vector<kkint32> start(nr_class,0);
4683  start[0] = 0;
4684  for(i=1;i<nr_class;i++)
4685  start[i] = start[i-1]+model->nSV[i-1];
4686 
4687  kkint32 p=0;
4688  for (i = 0; i < nr_class; i++)
4689  for (kkint32 j = i + 1; j < nr_class; j++)
4690  {
4691  double sum = 0; // computer the L of the K since it is symetric
4692  double trace=0; // compute the trace
4693 
4694  kkint32 si = start[i];
4695  kkint32 sj = start[j];
4696  kkint32 ci = model->nSV[i];
4697  kkint32 cj = model->nSV[j];
4698 
4699  kkint32 k;
4700  double *coef1 = model->sv_coef[j-1];
4701  double *coef2 = model->sv_coef[i];
4702 
4703  for (k = 0; k < ci; k++)
4704  //y[k]=+1;
4705  {
4706  double kvalue = Kernel::k_function(model->SV[si+k],model->SV[si+k],model->param);
4707  trace += coef1[si+k]*coef1[si+k]*kvalue;
4708 
4709  for(kkint32 kk=k+1; kk<ci; kk++)
4710  //y[kk]=+1 and y[k]*y[kk]=+1;
4711  {
4712  kvalue = Kernel::k_function(model->SV[si+k],model->SV[si+kk],model->param);
4713  sum+= coef1[si+k]*coef1[si+kk]*kvalue;
4714  }
4715  //sum += coef1[si+k] * kvalue[si+k];
4716 
4717  { // kk: jun-06-2003
4718  for(kkint32 kk=0; kk<cj; kk++)
4719  //y[kk]=-1 and y[k]*y[kk]=-1
4720  {
4721  kvalue = Kernel::k_function(model->SV[si+k],model->SV[sj+kk],model->param);
4722 
4723  // kk 2010-06-13 I believe that since the coef already reflects the label(sign) of the training
4724  // example that the following line should be adding not subtracting.
4725  // sum -= coef1[si+k]*coef2[sj+kk]*kvalue;
4726  sum += coef1[si+k]*coef2[sj+kk]*kvalue;
4727  }
4728  } // kk: jun-06-2003
4729 
4730  }
4731 
4732  for (k=0; k<cj-1; k++)
4733  //y[k]=-1
4734  {
4735  double kvalue = Kernel::k_function(model->SV[sj+k],model->SV[sj+k],model->param);
4736  trace += coef2[sj + k] * coef2[sj + k] * kvalue;
4737 
4738  for(kkint32 kk=k+1; kk<cj; kk++)
4739  //y[kk]=-1 and y[k]*y[kk]=+1
4740  {
4741  kvalue = Kernel::k_function(model->SV[sj+k],model->SV[sj+kk],model->param);
4742 
4743  // kk 2010-06-13
4744  // I suspect this next line should be subtracting but I am not doing anything
4745  // about it at this point until I understand.
4746  sum += coef2[sj + k] * coef2[sj + kk] * kvalue;
4747  }
4748  }
4749 
4750  double marginSqr = 2 * sum + trace;
4751  if (marginSqr <= 0.0)
4752  {
4753  cerr << endl << endl
4754  << "SVM233::svm_margin ***ERROR*** the computed margin <= 0.0. This is very bad." << endl
4755  << endl;
4756  marginSqr = 0.1;
4757  }
4758 
4759 
4760 
4761  model->margin[p] = sqrt(marginSqr);
4762  p++;
4763  }
4764  }
4765 }
4766 
4767 
4768 
4769 
4770 /**
4771  *@brief Extract Support Vector statistics .
4772  *@param[in] model Training Support Vector Machine.
4773  *@param[out] numSVs The number of training examples selected as Support Vectors.
4774  *@param[out] totalNumSVs Total number of SVs used by all the binary classifiers.
4775  */
4777  kkint32& numSVs, // The number of training examp
4778  kkint32& totalNumSVs
4779  )
4780 {
4781  numSVs = 0;
4782  totalNumSVs = 0;
4783 
4784  if (model == NULL)
4785  {
4786  KKStr errMsg = "svm_GetupportVectorsStatistics ***ERROR*** (model == NULL). Model was not defined.";
4787  cerr << endl << endl << errMsg << endl << endl;
4788  throw KKException (errMsg);
4789  }
4790 
4791  if (model->param.svm_type == ONE_CLASS ||
4792  model->param.svm_type == EPSILON_SVR ||
4793  model->param.svm_type == NU_SVR
4794  )
4795  {
4796  cerr << endl << endl
4797  << "svm_GetupportVectorsStatistics ***ERROR*** This function does not support for SVM Type[" << model->param.svm_type << "]" << endl
4798  << endl;
4799  return;
4800  }
4801 
4802  numSVs = model->l;
4803 
4804  {
4805  kkint32 i;
4806  kkint32 nr_class = model->nr_class;
4807 
4808  kkint32 l = model->l;
4809 
4810 
4811  // 'start' will be built to point to the beginning of the list of S'V's for each class.
4812  kkint32* start = new kkint32[nr_class];
4813  start[0] = 0;
4814  for (i = 1; i < nr_class; i++)
4815  start[i] = start[i-1] + model->nSV[i-1];
4816 
4817 
4818  for (i = 0; i < nr_class; i++)
4819  {
4820  for (kkint32 j = i + 1; j < nr_class; j++)
4821  {
4822  double sum = 0;
4823  kkint32 si = start[i];
4824  kkint32 sj = start[j];
4825  kkint32 ci = model->nSV[i];
4826  kkint32 cj = model->nSV[j];
4827 
4828  kkint32 k;
4829  double *coef1 = model->sv_coef[j-1];
4830  double *coef2 = model->sv_coef[i];
4831 
4832  for (k = 0; k < ci; k++)
4833  if (coef1[si + k] != 0.0)
4834  totalNumSVs++;
4835 
4836  for (k = 0; k < cj; k++)
4837  if (coef2[sj + k] != 0.0)
4838  totalNumSVs++;
4839  }
4840  }
4841 
4842  delete[] start;
4843  start = NULL;
4844  }
4845 
4846  return;
4847 } /* svm_GetupportVectorsStatistic */
KKStr(kkint32 size)
Creates a KKStr object that pre-allocates space for &#39;size&#39; characters.
Definition: KKStr.cpp:655
XmlTag(const KKStr &_name, TagTypes _tagType)
Definition: XmlStream.cpp:586
double ** sv_coef
Definition: svm.h:142
kkint32 dim
Definition: svm.h:161
kkint32 MemoryConsumedEstimated() const
Definition: svm.cpp:886
bool is_free(kkint32 i)
Definition: svm.cpp:603
T max(T x, T y)
Definition: svm.cpp:680
kkint32 l
Definition: svm.cpp:582
bool EqualIgnoreCase(const char *s2) const
Definition: KKStr.cpp:1257
kkint32 dimSelect
Definition: svm.h:102
void Swap(T &x, T &y)
Definition: svm.cpp:687
void ParseTabDelStr(const KKStr &_str)
Definition: svm.cpp:1176
__int32 kkint32
Definition: KKBaseTypes.h:88
void svm_GetSupportVectorStatistics(const struct SvmModel233 *model, kkint32 &numSVs, kkint32 &totalNumSVs)
Extract Support Vector statistics .
Definition: svm.cpp:4776
void swap_index(kkint32 i, kkint32 j) const
Definition: svm.cpp:2762
void TrimWhiteSpace(const char *_whiteSpace=" ")
After this call all leading and trailing whitespace will be trimmed from tokens.
Definition: KKStrParser.cpp:95
static void solve_one_class(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition: svm.cpp:2973
kkint32 boosting
Definition: svm.h:98
void Solve(kkint32 l, const Kernel &Q, const double *b_, const schar *y_, double *alpha_, double Cp, double Cn, double eps, SolutionInfo *si, kkint32 shrinking)
Definition: svm.cpp:2186
decision_function svm_train_one(const svm_problem *prob, const svm_parameter *param, double Cp, double Cn, std::set< kkint32 > &BSVIndex)
Definition: svm.cpp:3154
KKStr ExtractToken2(const char *delStr="\n\t\r ")
Extract first Token from the string.
Definition: KKStr.cpp:3026
KKStr GetNextToken(const char *delStr="\n\t\r ")
Extract next Token from string, tokens will be separated by delimiter characters. ...
Kernel(kkint32 l, svm_node *const *x, const svm_parameter &param)
Definition: svm.cpp:1609
kkint32 svm_type
Definition: svm.h:81
KKStr ExtractToken(const char *delStr="\n\t\r ")
Definition: KKStr.cpp:2969
double * margin
Definition: svm.h:158
kkint32 probability
Definition: svm.h:90
ONE_CLASS_Q(const svm_problem &prob, const svm_parameter &param)
Definition: svm.cpp:2700
double * featureWeight
Definition: svm.h:103
kkint32 * nSV
Definition: svm.h:148
virtual ~Solver()
Definition: svm.cpp:536
KKStr ToCmdLineStr() const
Definition: svm.cpp:1069
void Solve(kkint32 l, const Kernel &Q, const double *b, const schar *y, double *alpha, double Cp, double Cn, double eps, SolutionInfo *si, kkint32 shrinking)
Definition: svm.cpp:2398
double weight
Definition: svm.h:159
static void solve_c_svc(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si, double *C_)
Definition: svm.cpp:2864
XmlContent * XmlContentPtr
Definition: XmlStream.h:24
const char * kernel_type_table[]
Definition: svm.cpp:3694
kkint32 ToInt() const
Definition: KKStr.cpp:3565
double * featureWeight
Definition: svm.h:162
double(Kernel::* kernel_function)(kkint32 i, kkint32 j) const
Definition: svm.cpp:1555
static void solve_nu_svr(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition: svm.cpp:3059
bool operator==(const char *rtStr) const
Definition: KKStr.cpp:1588
virtual void WriteXML(const KKStr &varName, std::ostream &o) const
Definition: svm.cpp:144
bool weOwnContents
Definition: svm.h:55
kkint32 l
Definition: svm.h:139
kkint32 sampleSV
Definition: svm.h:108
Qfloat * get_Q(kkint32 i, kkint32 len) const
Definition: svm.cpp:2769
decision_function svm_train_one(const svm_problem *prob, const svm_parameter *param)
Definition: svm.cpp:3107
kkint32 l
Definition: svm.h:48
KKStr SupportVectorName(kkint32 svIDX)
Definition: svm.cpp:134
struct SvmModel233 * svm_train(const struct svm_problem *prob, const struct svm_parameter *param)
kkint32 * SVIndex
Definition: svm.h:153
double * G
Definition: svm.cpp:572
kkint32 nr_class
Definition: svm.h:138
bool is_upper_bound(kkint32 i)
Definition: svm.cpp:601
double cache_size
Definition: svm.h:85
double svm_predictTwoClasses(const SvmModel233 *model, const svm_node *x, double &dist, kkint32 excludeSupportVectorIDX)
Definition: svm.cpp:4218
double * weight
Definition: svm.h:92
XmlToken * XmlTokenPtr
Definition: XmlStream.h:18
kkint32 * label
Definition: svm.h:147
double degree
Definition: svm.h:78
bool MoreTokens() const
Definition: KKStrParser.h:74
kkint32 * weight_label
Definition: svm.h:93
KKStr & operator=(KKStr &&src)
Definition: KKStr.cpp:1369
double value
Definition: svm.h:39
virtual Qfloat * get_Q(kkint32 column, kkint32 len) const =0
double * C
Definition: svm.cpp:578
struct SvmModel233 * Svm_Load_Model(std::istream &f, RunLog &log)
virtual kkint32 ToInt32() const
Definition: XmlStream.h:317
kkuint32 Len() const
Returns the number of characters in the string.
Definition: KKStr.h:366
SVC_Q(const svm_problem &prob, const svm_parameter &param, const schar *y_)
Definition: svm.cpp:2653
kkint32 nr_class
Definition: svm.h:105
KKTHread * KKTHreadPtr
svm_parameter(KKStr &paramStr)
Definition: svm.cpp:983
Cache(kkint32 l, kkint32 size)
Definition: svm.cpp:1400
KKStrParser(const KKStr &_str)
Definition: KKStrParser.cpp:42
kkint16 index
Definition: svm.h:38
double ExtractTokenDouble(const char *delStr)
Definition: KKStr.cpp:3180
kkint32 hist
Definition: svm.h:104
void swap_index(kkint32 i, kkint32 j)
Definition: svm.cpp:1881
double * alpha
Definition: svm.cpp:575
char * alpha_status
Definition: svm.cpp:574
kkint32 shrinking
Definition: svm.h:91
XmlElement * XmlElementPtr
Definition: XmlStream.h:21
void AddAtribute(const KKStr &attributeName, const KKStr &attributeValue)
Definition: XmlStream.cpp:602
virtual kkint32 select_working_set(kkint32 &i, kkint32 &j)
Definition: svm.cpp:2212
struct svm_node ** x
Definition: svm.h:52
SVR_Q(const svm_problem &prob, const svm_parameter &param)
Definition: svm.cpp:2741
svm_node * xSpace
Definition: svm.h:167
#define INF
Definition: svm.cpp:698
void swap_index(kkint32 i, kkint32 j) const
Definition: svm.cpp:2676
kkint32 get_data(const kkint32 index, Qfloat **data, kkint32 len)
Definition: svm.cpp:1445
void TrimLeft(const char *whiteSpaceChars="\n\r\t ")
Definition: KKStr.cpp:1745
bool Empty() const
Definition: KKStr.h:241
KKStr ToTabDelStr() const
Definition: svm.cpp:1104
XmlTag const * XmlTagConstPtr
Definition: KKStr.h:45
double * W
Definition: svm.h:53
double eps
Definition: svm.cpp:577
Manages the reading and writing of objects in a simple XML format. For a class to be supported by Xml...
Definition: XmlStream.h:46
kkint32 active_size
Definition: svm.cpp:570
double * G_bar
Definition: svm.cpp:581
kkint32 * nonSVIndex
Definition: svm.h:154
double * y
Definition: svm.h:49
kkint32 ToInt32() const
Definition: KKStr.cpp:3587
bool weOwnXspace
Definition: svm.h:171
void clone(T *&dst, S *src, kkint32 n)
Definition: svm.cpp:690
kkint32 nr_weight
Definition: svm.h:87
bool is_lower_bound(kkint32 i)
Definition: svm.cpp:602
static void solve_nu_svc(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition: svm.cpp:2914
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of &#39;std::string&#39; strings.
Definition: KKStr.cpp:1082
void Upper()
Converts all characters in string to their Upper case equivalents via &#39;toupper&#39;.
Definition: KKStr.cpp:2461
static void solve_c_svc(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si, double Cp, double Cn)
Definition: svm.cpp:2811
virtual void do_shrinking()
Definition: svm.cpp:2276
kkint32 MemoryConsumedEstimated() const
Definition: svm.cpp:70
schar * y
Definition: svm.cpp:571
svm_parameter param
Definition: svm.h:137
double GetNextTokenDouble(const char *delStr="\n\t\r ")
virtual const KKStr & VarName() const
Definition: XmlStream.cpp:794
Qfloat * get_Q(kkint32 i, kkint32 len) const
Definition: svm.cpp:2708
kkint32 GetNextTokenInt(const char *delStr="\n\t\r ")
kkint32 numSVM
Definition: svm.h:106
#define Malloc(type, n)
Definition: svm.cpp:699
void WriteXML(const KKStr &varName, std::ostream &o) const
Definition: KKStr.cpp:4420
double ToDouble() const
Definition: KKStr.cpp:3541
std::ostream &__cdecl operator<<(std::ostream &os, const KKStr &str)
kkint32 ExtractTokenInt(const char *delStr)
Definition: KKStr.cpp:3129
double confidence
Definition: svm.h:100
kkint32 * index
Definition: svm.h:51
void info_flush()
Definition: svm.cpp:716
void svm_get_labels(const SvmModel233 *model, kkint32 *label)
Definition: svm.cpp:3679
virtual const KKStr & SectionName() const
Definition: XmlStream.cpp:785
virtual double calculate_rho()
Definition: svm.cpp:2348
bool unshrinked
Definition: svm.cpp:583
void update_alpha_status(kkint32 i)
Definition: svm.cpp:589
void ProcessSvmParameter(KKStr cmd, KKStr value, double valueNum, bool &parmUsed)
Definition: svm.cpp:900
virtual void swap_index(kkint32 i, kkint32 j) const
Definition: svm.cpp:1547
kkint32 svm_get_nr_class(const SvmModel233 *model)
Definition: svm.cpp:3672
virtual ~Kernel()
Definition: svm.cpp:1676
char operator[](kkint32 i) const
Definition: KKStr.cpp:3413
void WriteXML(std::ostream &o)
Definition: XmlStream.cpp:723
KKStr & operator=(const KKStr &src)
Definition: KKStr.cpp:1390
svm_node ** SV
Definition: svm.h:141
KKStrPtr const Content() const
Definition: XmlStream.h:338
kkint32 numNonSV
Definition: svm.h:155
signed char schar
Definition: svm.cpp:522
Used for logging messages.
Definition: RunLog.h:49
void EncodeProblem(const struct svm_paramater &param, struct svm_problem &prob_in, struct svm_problem &prob_out)
const char * svm_type_table[]
Definition: svm.cpp:3687
void svm_margin(SvmModel233 *model)
Definition: svm.cpp:4650
void Svm_Save_Model(std::ostream &o, const SvmModel233 *model)
virtual TokenTypes TokenType()=0
Class that manages the extraction of tokens from a String without being destructive to the original s...
Definition: KKStrParser.h:18
kkint32 * active_set
Definition: svm.cpp:580
void swap_index(kkint32 i, kkint32 j) const
Definition: svm.cpp:2720
void info(const char *fmt,...)
Definition: svm.cpp:715
kkint32 kernel_type
Definition: svm.h:80
const Kernel * Q
Definition: svm.cpp:576
const char * svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param)
double gamma
Definition: svm.h:79
svm_parameter & operator=(const svm_parameter &right)
Definition: svm.cpp:828
float ToFloat() const
Definition: KKStr.cpp:3553
virtual XmlTokenPtr GetNextToken(VolConstBool &cancelFlag, RunLog &log)
Definition: XmlStream.cpp:116
KKException(const KKStr &_exceptionStr)
Definition: KKException.cpp:45
svm_parameter(const svm_parameter &parameters)
Definition: svm.cpp:768
double coef0
Definition: svm.h:77
static void solve_epsilon_svr(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition: svm.cpp:3008
double * kValueTable
Definition: svm.h:165
T min(T x, T y)
Definition: svm.cpp:676
KKStr SubStrPart(kkint32 firstChar) const
returns a SubString consisting of all characters starting at index &#39;firstChar&#39; until the end of the s...
Definition: KKStr.cpp:2780
double get_C(kkint32 i)
Definition: svm.cpp:585
void swap_index(kkint32 i, kkint32 j)
Definition: svm.cpp:1483
#define XmlFactoryMacro(NameOfClass)
Definition: XmlStream.h:688
void reconstruct_gradient()
Definition: svm.cpp:1897
void svm_destroy_model(struct SvmModel233 *model)
Definition: svm.cpp:4442
void Solve(kkint32 l, const Kernel &Q, const double *b_, const schar *y_, double *alpha_, double *C_, double eps, SolutionInfo *si, kkint32 shrinking)
Definition: svm.cpp:1920
double * rho
Definition: svm.h:143
svm_problem * svm_BuildProbFromTwoClassModel(const SvmModel233 *model, kkint32 excludeSupportVectorIDX)
Definition: svm.cpp:4356
virtual void ReadXML(XmlStream &s, XmlTagConstPtr tag, VolConstBool &cancelFlag, RunLog &log)
Definition: svm.cpp:234
static double k_function_subspace(const svm_node *x, const svm_node *y, const svm_parameter &param, const double *featureWeight)
Definition: svm.cpp:1805
double * b
Definition: svm.cpp:579
static double k_function(const svm_node *x, const svm_node *y, const svm_parameter &param)
Definition: svm.cpp:1735
volatile const bool VolConstBool
Definition: KKBaseTypes.h:163
Qfloat * get_Q(kkint32 i, kkint32 len) const
Definition: svm.cpp:2663