Orfeo Toolbox  4.2
otbSVMKernels.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 #ifndef __otbSVMKernels_h
19 #define __otbSVMKernels_h
20 
21 #include <vector>
22 #include <algorithm> // for std::find
23 #include <cstring> // for strpbrk
24 
25 #include "itkNumericTraits.h"
26 #include "otbMath.h"
27 
28 // Existing kernels
33 
34 #include "svm.h"
35 
36 namespace otb
37 {
41 class CustomKernelFunctor : public GenericKernelFunctorBase
42 {
43 public:
46 
48  {
49  this->SetName("custom");
50  }
51  virtual ~CustomKernelFunctor() {}
52 
53  // Deep copy operator
55  {
56  return new Self(*this);
57  }
58 
59  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& /*param*/) const
60  {
61  return (dot(x, x) - 2.0 * dot(x, y) + dot(y, y));
62  }
63 
64 protected:
66  : Superclass(copy)
67  {
68  *this = copy;
69  }
70 
72  {
74  return *this;
75  }
76 };
77 
81 class InvMultiQuadricKernelFunctor : public GenericKernelFunctorBase
82 {
83 public:
86 
88  {
89  this->SetName("invMultiQuadric");
90  this->SetValue<double>("const_coef", 1);
91  }
93 
94  // Deep copy operator
96  {
97  return new Self(*this);
98  }
99 
100  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
101  {
102  double mq = this->GetValue<double>("const_coef") + m_Custom(x, y, param);
103  if (mq == 0.0)
104  {
106  }
107  return 1.0 / sqrt(mq);
108  }
109 
110 protected:
112  : Superclass(copy)
113  {
114  *this = copy;
115  }
116 
118  {
120  return *this;
121  }
122 
123 private:
125 };
126 
130 class KModKernelFunctor : public GenericKernelFunctorBase
131 {
132 public:
135 
137  {
138  this->SetName("KMod");
139  this->SetValue<double>("const_coef", 1);
140  }
141  virtual ~KModKernelFunctor() {}
142 
143  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
144  {
145  double mq = this->GetValue<double>("const_coef") + m_Custom(x, y, param);
146 
147  if (mq == 0.0)
148  {
150  }
151  return exp(param.gamma / mq) - 1.0;
152  }
153 
154  // Deep copy operator
156  {
157  return new Self(*this);
158  }
159 
160 protected:
161  KModKernelFunctor(const Self& copy)
162  : Superclass(copy)
163  {
164  *this = copy;
165  }
166 
168  {
170  return *this;
171  }
172 
173 private:
175 };
176 
180 class SAMKernelFunctor : public GenericKernelFunctorBase
181 {
182 public:
185 
187  {
188  this->SetName("SAM");
189  }
190  virtual ~SAMKernelFunctor() {}
191 
192  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& /*param*/) const
193  {
194  double den = dot(x, x) * dot(y, y);
195  if (den <= 0.)
196  {
197  return 0.0;
198  }
199  double ss = dot(x, y);
200  return vcl_acos(ss / vcl_sqrt(den));
201  }
202 
203  // Deep copy operator
205  {
206  return new Self(*this);
207  }
208 
209 protected:
210  SAMKernelFunctor(const Self& copy)
211  : Superclass(copy)
212  {
213  *this = copy;
214  }
215 
217  {
219  return *this;
220  }
221 };
222 
226 class RadialSAMKernelFunctor : public GenericKernelFunctorBase
227 {
228 public:
231 
233  {
234  this->SetName("RadialSAM");
235  }
237 
238  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
239  {
240  return vcl_exp(-param.gamma * m_Sam(x, y, param));
241  }
242 
243  // Deep copy operator
245  {
246  return new Self(*this);
247  }
248 
249 protected:
251  : Superclass(copy)
252  {
253  *this = copy;
254  }
255 
257  {
259  return *this;
260  }
261 
262 private:
264 };
265 
269 class InverseCosSAMKernelFunctor : public GenericKernelFunctorBase
270 {
271 public:
274 
276  {
277  this->SetName("InverseCosSAM");
278  }
280 
281  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
282  {
283  return 1.0 - vcl_cos(m_Sam(x, y, param));
284  }
285 
286  // Deep copy operator
288  {
289  return new Self(*this);
290  }
291 
292 protected:
294  : Superclass(copy)
295  {
296  *this = copy;
297  }
298 
300  {
302  return *this;
303  }
304 
305 private:
307 };
308 
312 class InvMultiQuadraticSAMKernelFunctor : public GenericKernelFunctorBase
313 {
314 public:
317 
319  {
320  this->SetName("invMultiQuadraticSAM");
321  this->SetValue<double>("const_coef", 1);
322  }
324 
325  // Deep copy operator
327  {
328  return new Self(*this);
329  }
330 
331  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
332  {
333  double mq = this->GetValue<double>("const_coef") + m_Sam(x, y, param);
334 
335  if (mq == 0.)
336  {
338  }
339  return 1. / sqrt(mq);
340  }
341 
342 protected:
344  : Superclass(copy)
345  {
346  *this = copy;
347  }
348 
350  {
352  return *this;
353  }
354 
355 private:
357 };
358 
362 class KModSAMKernelFunctor : public GenericKernelFunctorBase
363 {
364 public:
367 
369  {
370  this->SetName("KModSAM");
371  this->SetValue<double>("const_coef", 1);
372  }
374 
375  // Deep copy operator
377  {
378  return new Self(*this);
379  }
380 
381  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
382  {
383  double mq = this->GetValue<double>("const_coef") + m_Sam(x, y, param);
384 
385  if (mq == 0.)
386  {
388  }
389  return vcl_exp(param.gamma / mq) - 1.0;
390  }
391 
392 protected:
394  : Superclass(copy)
395  {
396  *this = copy;
397  }
398 
400  {
402  return *this;
403  }
404 
405 private:
407 };
408 
412 class RBFKernelFunctor : public GenericKernelFunctorBase
413 {
414 public:
417 
419  {
420  this->SetName("RBF");
421  this->SetValue<double>("gamma_coef", 0.5);
422  }
423  virtual ~RBFKernelFunctor() {}
424 
425  // Deep copy operator
427  {
428  return new Self(*this);
429  }
430 
431  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
432  {
433  double res = this->GetValue<double>("gamma_coef") * m_Custom(x, y, param);
434  return vcl_exp(-res);
435  }
436 
437  virtual double derivative(const svm_node *x,
438  const svm_node *y,
439  const svm_parameter& param,
440  int degree,
441  int index,
442  bool isAtEnd,
443  double constValue) const
444  {
445  double gamma = this->GetValue<double>("gamma_coef");
446  double kernelValue = 0.;
447  double xval = 0.;
448  double yval = 0.;
449  int compt = 0;
450 
451  const svm_node *xtemp = x;
452  const svm_node *ytemp = y;
453 
454  bool stop = false;
455  while (xtemp->index != -1 && ytemp->index != -1 && stop == false)
456  {
457  if (xtemp->index == ytemp->index)
458  {
459  if (compt == index)
460  {
461  xval = xtemp->value;
462  yval = ytemp->value;
463  stop = true;
464  }
465  else
466  {
467  compt++;
468  ++ytemp;
469  ++xtemp;
470  }
471  }
472  else
473  {
474  if (xtemp->index > ytemp->index) ++ytemp;
475  else ++xtemp;
476  }
477  }
478 
479  if (isAtEnd == true)
480  {
481  kernelValue = this->operator ()(x, y, param);
482  }
483  else
484  {
485  kernelValue = constValue;
486  }
487 
488  if (degree < 0)
489  {
490  return 0;
491  }
492  switch (degree)
493  {
494  case 0:
495  return kernelValue;
496  break;
497  case 1:
498  return (-2 * gamma * (yval - xval) * kernelValue);
499  break;
500  default:
501  return (-2 * gamma *
502  ((degree - 1) *
503  this->derivative(x, y, param, degree - 2, index, isAtEnd, constValue) +
504  (yval - xval) * derivative(x, y, param, degree - 1, index, isAtEnd, constValue)));
505  break;
506  }
507 
508  }
509 
510 protected:
511  RBFKernelFunctor(const Self& copy)
512  : Superclass(copy)
513  {
514  *this = copy;
515  }
516 
518  {
520  return *this;
521  }
522 
523 private:
525 };
526 
530 class RBFRBFSAMKernelFunctor : public GenericKernelFunctorBase
531 {
532 public:
535 
537  {
538  this->SetName("RBFRBFSAM");
539  this->SetValue<double>("lin_coef", 1.);
540  }
542 
543  // Deep copy operator
545  {
546  return new Self(*this);
547  }
548 
549  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
550  {
551  return (this->GetValue<double>("lin_coef") * vcl_exp(-param.gamma * m_Custom(x, y, param))
552  + (1.0 - this->GetValue<double>("lin_coef")) * m_RadialSam(x, y, param));
553  }
554 
555 protected:
557  : Superclass(copy)
558  {
559  *this = copy;
560  }
561 
563  {
565  return *this;
566  }
567 
568 private:
571 };
572 
576 class PolyRBFSAMKernelFunctor : public GenericKernelFunctorBase
577 {
578 public:
581 
583  {
584  this->SetName("polyRBFSAM");
585  this->SetValue<double>("const_coef", 1);
586  this->SetValue<double>("lin_coef", 1);
587  }
589 
590  // Deep copy operator
592  {
593  return new Self(*this);
594  }
595 
596  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
597  {
598  return this->GetValue<double>("const_lin") * vcl_pow(dot(x, y) + this->GetValue<double>("const_coef"), param.degree)
599  + (1.0 - this->GetValue<double>("const_coef"))
600  * m_RadialSam(x, y, param);
601  }
602 
603 protected:
605  : Superclass(copy)
606  {
607  *this = copy;
608  }
609 
611  {
613  return *this;
614  }
615 
616 private:
618 };
619 
623 class RBFDiffKernelFunctor : public GenericKernelFunctorBase
624 {
625 public:
628 
630  {
631  this->SetName("RBFDiff");
632  }
634 
635  // Deep copy operator
637  {
638  return new Self(*this);
639  }
640 
641  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
642  {
643 
644  double total = 0.;
645 
646  while (x->index != -1 && y->index != -1)
647  {
648  if (x->index == y->index)
649  {
650  total = total + vcl_exp(-param.gamma * vcl_abs(x->value - y->value));
651  ++x;
652  ++y;
653  }
654  else
655  {
656  if (x->index < y->index) ++x;
657  else ++y;
658  }
659  }
660  return total;
661  }
662 
663 protected:
665  : Superclass(copy)
666  {
667  *this = copy;
668  }
669 
671  {
673  return *this;
674  }
675 
676 };
677 
681 class CustomLinearKernelFunctor : public GenericKernelFunctorBase
682 {
683 public:
686 
688  {
689  this->SetName("customLinear");
690  }
692 
693  // Deep copy operator
695  {
696  return new Self(*this);
697  }
698 
699  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
700  {
701  double value=-param.gamma*m_Custom(x, y, param);
702  if(value<-30.0)
703  {
704  return 0.0;
705  }
706 
707  return (vcl_exp(value));
708  }
709 
710 protected:
712  : Superclass(copy)
713  {
714  *this = copy;
715  }
716 
718  {
720  return *this;
721  }
722 
723 private:
725 };
726 
730 class GroupedRBFKernelFunctor : public GenericKernelFunctorBase
731 {
732 public:
735 
737  {
738  this->SetName("groupedRBF");
739  }
741 
742  // Deep copy operator
744  {
745  return new Self(*this);
746  }
747 
748  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
749  {
750  const char * parameters = param.custom;
751  const char * twoPoints = ":";
752  const char * position = strpbrk (parameters, twoPoints);
753  int twoPointsPosition = 0;
754  double total = 0.;
755  double value = 0.;
756  int numberOfGroups = atoi(parameters);
757 
758  twoPointsPosition = position - parameters;
759 
760  parameters = parameters + twoPointsPosition + 1;
761 
762  int i, j;
763  std::vector<int> begin;
764  begin.resize(numberOfGroups);
765  std::vector<int> end;
766  end.resize(numberOfGroups);
767 
768  for (i = 0; i < numberOfGroups; ++i)
769  {
770  begin[i] = atoi(parameters);
771  position = strpbrk (parameters, twoPoints);
772  twoPointsPosition = position - parameters;
773  parameters = parameters + twoPointsPosition + 1;
774 
775  end[i] = atoi(parameters);
776  parameters = parameters + twoPointsPosition + 1;
777  }
778 
779  const svm_node * xBuff = x;
780  const svm_node * yBuff = y;
781 
782  int sizeX = 0;
783  int sizeY = 0;
784 
785  while (xBuff->index != 1)
786  {
787  ++sizeX;
788  ++xBuff;
789  }
790 
791  while (yBuff->index != 1)
792  {
793  ++sizeY;
794  ++yBuff;
795  }
796 
797  const svm_node * xTemp = NULL;
798  const svm_node * yTemp = NULL;
799 
800  int index = 0;
801 
802  if (sizeX && sizeY)
803  {
804  svm_node* xGroup = new svm_node[sizeX];
805  svm_node* yGroup = new svm_node[sizeY];
806  for (j = 0; j < numberOfGroups; ++j)
807  {
808  xTemp = x;
809  yTemp = y;
810  index = 0;
811 
812  while (xTemp->index != 1 && yTemp->index != 1)
813  {
814  xGroup[index].index = xTemp->index;
815  yGroup[index].index = yTemp->index;
816  if ((xTemp->index < begin[j]) || (xTemp->index > end[j]))
817  {
818  xGroup[index].value = 0;
819  yGroup[index].value = 0;
820  }
821  else
822  {
823  xGroup[index].value = xTemp->value;
824  yGroup[index].value = yTemp->value;
825  }
826  ++index;
827  ++xTemp;
828  ++yTemp;
829  }
830 
831  // value can have different value according to j
832  value = m_CustomLinear(xGroup, yGroup, param);
833 
834  total += value;
835  }
836  delete[] xGroup;
837  delete[] yGroup;
838  }
839 
840  else if ((sizeX > 0) && (sizeY == 0))
841  {
842  svm_node* xGroup = new svm_node[sizeX];
843  svm_node* yGroup = new svm_node[sizeY];
844 
845  for (j = 0; j < numberOfGroups; ++j)
846  {
847  xTemp = x;
848  index = 0;
849 
850  while (xTemp->index != -1)
851  {
852  xGroup[index].index = xTemp->index;
853  yGroup[index].index = xTemp->index;
854 
855  if ((xTemp->index < begin[j]) || (xTemp->index > end[j]))
856  {
857  xGroup[index].value = 0;
858  yGroup[index].value = 0;
859  }
860  else
861  {
862  xGroup[index].value = xTemp->value;
863  yGroup[index].value = 0;
864  }
865  ++index;
866  ++xTemp;
867  }
868 
869  // value can have different value according to j
870  value = m_CustomLinear(xGroup, yGroup, param);
871 
872  total += value;
873  }
874  delete[] xGroup;
875  delete[] yGroup;
876  }
877 
878  else
879  {
880  total = static_cast<double>(numberOfGroups) * m_CustomLinear(x, y, param);
881  }
882 
883  if (xTemp != NULL) delete xTemp;
884  if (yTemp != NULL) delete yTemp;
885 
886  return total;
887  }
888 
889 protected:
891  : Superclass(copy)
892  {
893  *this = copy;
894  }
895 
897  {
899  return *this;
900  }
901 
902 private:
904 };
905 
909 class GroupingAdaptiveKernelFunctor : public GenericKernelFunctorBase
910 {
911 public:
914 
916  {
917  this->SetName("groupingAdaptive");
918  this->SetValue<double>("lin_coef", 1.);
919  this->SetValue<double>("const_coef", 1.);
920  }
922 
923  // Deep copy operator
925  {
926  return new Self(*this);
927  }
928 
929  virtual double operator ()(const svm_node *x, const svm_node *y, const svm_parameter& param) const
930  {
931  const char * parameters = param.custom;
932  const char * twoPoints = ":";
933  const char * position = strpbrk (parameters, twoPoints);
934  int twoPointsPosition = 0;
935  double total = 0.;
936  double value = 0.;
937  int numberOfGroups = atoi(parameters);
938 
939  twoPointsPosition = position - parameters;
940 
941  parameters = parameters + twoPointsPosition + 1;
942 
943  int i, j;
944 
945  std::vector<int> begin;
946  begin.resize(numberOfGroups);
947  std::vector<int> end;
948  end.resize(numberOfGroups);
949 
950  for (i = 0; i < numberOfGroups; ++i)
951  {
952  begin[i] = atoi(parameters);
953  position = strpbrk (parameters, twoPoints);
954  twoPointsPosition = position - parameters;
955  parameters = parameters + twoPointsPosition + 1;
956 
957  end[i] = atoi(parameters);
958  parameters = parameters + twoPointsPosition + 1;
959  }
960 
961  const svm_node * xBuff = x;
962  const svm_node * yBuff = y;
963 
964  int sizeX = 0;
965  int sizeY = 0;
966 
967  while (xBuff->index != 1)
968  {
969  ++sizeX;
970  ++xBuff;
971  }
972 
973  while (yBuff->index != 1)
974  {
975  ++sizeY;
976  ++yBuff;
977  }
978 
979  const svm_node * xTemp = NULL;
980  const svm_node * yTemp = NULL;
981 
982  int index = 0;
983 
984  if (sizeX && sizeY)
985  {
986  svm_node* xGroup = new svm_node[sizeX];
987  svm_node* yGroup = new svm_node[sizeY];
988 
989  for (j = 0; j < numberOfGroups; ++j)
990  {
991  xTemp = x;
992  yTemp = y;
993  index = 0;
994 
995  while (xTemp->index != 1 && yTemp->index != 1)
996  {
997  xGroup[index].index = xTemp->index;
998  yGroup[index].index = yTemp->index;
999  if ((xTemp->index < begin[j]) || (xTemp->index > end[j]))
1000  {
1001  xGroup[index].value = 0;
1002  yGroup[index].value = 0;
1003  }
1004  else
1005  {
1006  xGroup[index].value = xTemp->value;
1007  yGroup[index].value = yTemp->value;
1008  }
1009  ++index;
1010  ++xTemp;
1011  ++yTemp;
1012  }
1013 
1014  // value can have different value according to j
1015  value = vcl_pow(this->GetValue<double>("lin_coef") * dot(xGroup, yGroup) + this->GetValue<double>(
1016  "const_coef"), static_cast<double>(param.degree));
1017 
1018  total += value;
1019  }
1020  delete[] xGroup;
1021  delete[] yGroup;
1022  }
1023 
1024  else if ((sizeX > 0) && (sizeY == 0))
1025  {
1026  svm_node* xGroup = new svm_node[sizeX];
1027  svm_node* yGroup = new svm_node[sizeY];
1028 
1029  for (j = 0; j < numberOfGroups; ++j)
1030  {
1031  xTemp = x;
1032  index = 0;
1033 
1034  while (xTemp->index != 1)
1035  {
1036  xGroup[index].index = xTemp->index;
1037  yGroup[index].index = xTemp->index;
1038 
1039  if ((xTemp->index < begin[j]) || (xTemp->index > end[j]))
1040  {
1041  xGroup[index].value = 0;
1042  yGroup[index].value = 0;
1043  }
1044  else
1045  {
1046  xGroup[index].value = xTemp->value;
1047  yGroup[index].value = 0;
1048  }
1049  ++index;
1050  ++xTemp;
1051  }
1052 
1053  // value can have different value according to j
1054  value = vcl_pow(this->GetValue<double>("lin_coef") * dot(xGroup, yGroup) + this->GetValue<double>(
1055  "const_coef"), static_cast<double>(param.degree));
1056 
1057  total += value;
1058  }
1059  delete[] xGroup;
1060  delete[] yGroup;
1061  }
1062 
1063  else
1064  {
1065  CustomKernelFunctor custom;
1066  total = static_cast<double>(numberOfGroups) * custom(x, y, param);
1067  }
1068 
1069  return total;
1070  }
1071 
1072 
1073 protected:
1075  : Superclass(copy)
1076  {
1077  *this = copy;
1078  }
1079 
1081  {
1082  Superclass::operator =(copy);
1083  return *this;
1084  }
1085 
1086 };
1087 
1088 }
1089 #endif

Generated at Sat Aug 30 2014 16:29:18 for Orfeo Toolbox with doxygen 1.8.3.1