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