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