Hugin trunk 0.1
Loading...
Searching...
No Matches
svm.cpp
Go to the documentation of this file.
1/*
2Copyright (c) 2000-2014 Chih-Chung Chang and Chih-Jen Lin
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
8
91. Redistributions of source code must retain the above copyright
10notice, this list of conditions and the following disclaimer.
11
122. Redistributions in binary form must reproduce the above copyright
13notice, this list of conditions and the following disclaimer in the
14documentation and/or other materials provided with the distribution.
15
163. Neither name of copyright holders nor the names of its contributors
17may be used to endorse or promote products derived from this software
18without specific prior written permission.
19
20
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
25CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33*/
34
35
36#include <math.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <ctype.h>
40#include <float.h>
41#include <string.h>
42#include <stdarg.h>
43#include <limits.h>
44#include <locale.h>
45#include "svm.h"
46#include <hugin_config.h>
47#ifndef HAVE_LOG1P
48#define log1p(x) log(1+x)
49#endif
50
51namespace celeste
52{
53// changes to original libsvm
54// added license to header (Tim Nugent)
55// added celeste namespace
56// switched to C++ header instead a plain C header
57
59typedef float Qfloat;
60typedef signed char schar;
61#ifndef min
62template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }
63#endif
64#ifndef max
65template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }
66#endif
67template <class T> static inline void swap(T& x, T& y) { T t=x; x=y; y=t; }
68template <class S, class T> static inline void clone(T*& dst, S* src, int n)
69{
70 dst = new T[n];
71 memcpy((void *)dst,(void *)src,sizeof(T)*n);
72}
73static inline double powi(double base, int times)
74{
75 double tmp = base, ret = 1.0;
76
77 for(int t=times; t>0; t/=2)
78 {
79 if(t%2==1) ret*=tmp;
80 tmp = tmp * tmp;
81 }
82 return ret;
83}
84#define INF HUGE_VAL
85#define TAU 1e-12
86#define Malloc(type,n) (type *)malloc((n)*sizeof(type))
87
88static void print_string_stdout(const char *s)
89{
90 fputs(s,stdout);
92}
93static void (*svm_print_string) (const char *) = &print_string_stdout;
94#if 1
95static void info(const char *fmt,...)
96{
97 char buf[BUFSIZ];
98 va_list ap;
101 va_end(ap);
102 (*svm_print_string)(buf);
103}
104#else
105static void info(const char *fmt,...) {}
106#endif
107
108//
109// Kernel Cache
110//
111// l is the number of total data items
112// size is the cache size limit in bytes
113//
114class Cache
115{
116public:
117 Cache(int l,long int size);
118 ~Cache();
119
120 // request data [0,len)
121 // return some position p where [p,len) need to be filled
122 // (p >= len if nothing needs to be filled)
123 int get_data(const int index, Qfloat **data, int len);
124 void swap_index(int i, int j);
125private:
126 int l;
127 long int size;
128 struct head_t
129 {
130 head_t *prev, *next; // a circular list
132 int len; // data[0,len) is cached in this entry
133 };
134
137 void lru_delete(head_t *h);
138 void lru_insert(head_t *h);
139};
140
141Cache::Cache(int l_,long int size_):l(l_),size(size_)
142{
143 head = (head_t *)calloc(l,sizeof(head_t)); // initialized to 0
144 size /= sizeof(Qfloat);
145 size -= l * sizeof(head_t) / sizeof(Qfloat);
146 size = max(size, 2 * (long int) l); // cache must be large enough for two columns
148}
149
151{
152 for(head_t *h = lru_head.next; h != &lru_head; h=h->next)
153 free(h->data);
154 free(head);
155}
156
158{
159 // delete from current location
160 h->prev->next = h->next;
161 h->next->prev = h->prev;
162}
163
165{
166 // insert to last position
167 h->next = &lru_head;
168 h->prev = lru_head.prev;
169 h->prev->next = h;
170 h->next->prev = h;
171}
172
173int Cache::get_data(const int index, Qfloat **data, int len)
174{
175 head_t *h = &head[index];
176 if(h->len) lru_delete(h);
177 int more = len - h->len;
178
179 if(more > 0)
180 {
181 // free old space
182 while(size < more)
183 {
186 free(old->data);
187 size += old->len;
188 old->data = 0;
189 old->len = 0;
190 }
191
192 // allocate new space
193 h->data = (Qfloat *)realloc(h->data,sizeof(Qfloat)*len);
194 size -= more;
195 swap(h->len,len);
196 }
197
198 lru_insert(h);
199 *data = h->data;
200 return len;
201}
202
203void Cache::swap_index(int i, int j)
204{
205 if(i==j) return;
206
207 if(head[i].len) lru_delete(&head[i]);
208 if(head[j].len) lru_delete(&head[j]);
209 swap(head[i].data,head[j].data);
210 swap(head[i].len,head[j].len);
211 if(head[i].len) lru_insert(&head[i]);
212 if(head[j].len) lru_insert(&head[j]);
213
214 if(i>j) swap(i,j);
215 for(head_t *h = lru_head.next; h!=&lru_head; h=h->next)
216 {
217 if(h->len > i)
218 {
219 if(h->len > j)
220 swap(h->data[i],h->data[j]);
221 else
222 {
223 // give up
224 lru_delete(h);
225 free(h->data);
226 size += h->len;
227 h->data = 0;
228 h->len = 0;
229 }
230 }
231 }
232}
233
234//
235// Kernel evaluation
236//
237// the static method k_function is for doing single kernel evaluation
238// the constructor of Kernel prepares to calculate the l*l kernel matrix
239// the member function get_Q is for getting one column from the Q Matrix
240//
241class QMatrix {
242public:
243 virtual Qfloat *get_Q(int column, int len) const = 0;
244 virtual double *get_QD() const = 0;
245 virtual void swap_index(int i, int j) const = 0;
246 virtual ~QMatrix() {}
247};
248
249class Kernel: public QMatrix {
250public:
251 Kernel(int l, svm_node * const * x, const svm_parameter& param);
252 virtual ~Kernel();
253
254 static double k_function(const svm_node *x, const svm_node *y,
255 const svm_parameter& param);
256 virtual Qfloat *get_Q(int column, int len) const = 0;
257 virtual double *get_QD() const = 0;
258 virtual void swap_index(int i, int j) const // no so const...
259 {
260 swap(x[i],x[j]);
262 }
263protected:
264
266
267private:
268 const svm_node **x;
269 double *x_square;
270
271 // svm_parameter
272 const int kernel_type;
273 const int degree;
274 const double gamma;
275 const double coef0;
276
277 static double dot(const svm_node *px, const svm_node *py);
278 double kernel_linear(int i, int j) const
279 {
280 return dot(x[i],x[j]);
281 }
282 double kernel_poly(int i, int j) const
283 {
284 return powi(gamma*dot(x[i],x[j])+coef0,degree);
285 }
286 double kernel_rbf(int i, int j) const
287 {
288 return exp(-gamma*(x_square[i]+x_square[j]-2*dot(x[i],x[j])));
289 }
290 double kernel_sigmoid(int i, int j) const
291 {
292 return tanh(gamma*dot(x[i],x[j])+coef0);
293 }
294 double kernel_precomputed(int i, int j) const
295 {
296 return x[i][(int)(x[j][0].value)].value;
297 }
298};
299
300Kernel::Kernel(int l, svm_node * const * x_, const svm_parameter& param)
301:kernel_type(param.kernel_type), degree(param.degree),
302 gamma(param.gamma), coef0(param.coef0)
303{
304 switch(kernel_type)
305 {
306 case LINEAR:
308 break;
309 case POLY:
311 break;
312 case RBF:
314 break;
315 case SIGMOID:
317 break;
318 case PRECOMPUTED:
320 break;
321 }
322
323 clone(x,x_,l);
324
325 if(kernel_type == RBF)
326 {
327 x_square = new double[l];
328 for(int i=0;i<l;i++)
329 x_square[i] = dot(x[i],x[i]);
330 }
331 else
332 x_square = 0;
333}
334
336{
337 delete[] x;
338 delete[] x_square;
339}
340
341double Kernel::dot(const svm_node *px, const svm_node *py)
342{
343 double sum = 0;
344 while(px->index != -1 && py->index != -1)
345 {
346 if(px->index == py->index)
347 {
348 sum += px->value * py->value;
349 ++px;
350 ++py;
351 }
352 else
353 {
354 if(px->index > py->index)
355 ++py;
356 else
357 ++px;
358 }
359 }
360 return sum;
361}
362
363double Kernel::k_function(const svm_node *x, const svm_node *y,
364 const svm_parameter& param)
365{
366 switch(param.kernel_type)
367 {
368 case LINEAR:
369 return dot(x,y);
370 case POLY:
371 return powi(param.gamma*dot(x,y)+param.coef0,param.degree);
372 case RBF:
373 {
374 double sum = 0;
375 while(x->index != -1 && y->index !=-1)
376 {
377 if(x->index == y->index)
378 {
379 double d = x->value - y->value;
380 sum += d*d;
381 ++x;
382 ++y;
383 }
384 else
385 {
386 if(x->index > y->index)
387 {
388 sum += y->value * y->value;
389 ++y;
390 }
391 else
392 {
393 sum += x->value * x->value;
394 ++x;
395 }
396 }
397 }
398
399 while(x->index != -1)
400 {
401 sum += x->value * x->value;
402 ++x;
403 }
404
405 while(y->index != -1)
406 {
407 sum += y->value * y->value;
408 ++y;
409 }
410
411 return exp(-param.gamma*sum);
412 }
413 case SIGMOID:
414 return tanh(param.gamma*dot(x,y)+param.coef0);
415 case PRECOMPUTED: //x: test (validation), y: SV
416 return x[(int)(y->value)].value;
417 default:
418 return 0; // Unreachable
419 }
420}
421
422// An SMO algorithm in Fan et al., JMLR 6(2005), p. 1889--1918
423// Solves:
424//
425// min 0.5(\alpha^T Q \alpha) + p^T \alpha
426//
427// y^T \alpha = \delta
428// y_i = +1 or -1
429// 0 <= alpha_i <= Cp for y_i = 1
430// 0 <= alpha_i <= Cn for y_i = -1
431//
432// Given:
433//
434// Q, p, y, Cp, Cn, and an initial feasible point \alpha
435// l is the size of vectors and matrices
436// eps is the stopping tolerance
437//
438// solution will be put in \alpha, objective value will be put in obj
439//
440class Solver {
441public:
442 Solver() {};
443 virtual ~Solver() {};
444
446 double obj;
447 double rho;
450 double r; // for Solver_NU
451 };
452
453 void Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
454 double *alpha_, double Cp, double Cn, double eps,
455 SolutionInfo* si, int shrinking);
456protected:
459 double *G; // gradient of objective function
461 char *alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE
462 double *alpha;
463 const QMatrix *Q;
464 const double *QD;
465 double eps;
466 double Cp,Cn;
467 double *p;
469 double *G_bar; // gradient, if we treat free variables as 0
470 int l;
471 bool unshrink; // XXX
472
473 double get_C(int i)
474 {
475 return (y[i] > 0)? Cp : Cn;
476 }
478 {
479 if(alpha[i] >= get_C(i))
481 else if(alpha[i] <= 0)
483 else alpha_status[i] = FREE;
484 }
485 bool is_upper_bound(int i) { return alpha_status[i] == UPPER_BOUND; }
486 bool is_lower_bound(int i) { return alpha_status[i] == LOWER_BOUND; }
487 bool is_free(int i) { return alpha_status[i] == FREE; }
488 void swap_index(int i, int j);
490 virtual int select_working_set(int &i, int &j);
491 virtual double calculate_rho();
492 virtual void do_shrinking();
493private:
494 bool be_shrunk(int i, double Gmax1, double Gmax2);
495};
496
497void Solver::swap_index(int i, int j)
498{
499 Q->swap_index(i,j);
500 swap(y[i],y[j]);
501 swap(G[i],G[j]);
503 swap(alpha[i],alpha[j]);
504 swap(p[i],p[j]);
506 swap(G_bar[i],G_bar[j]);
507}
508
510{
511 // reconstruct inactive elements of G from G_bar and free variables
512
513 if(active_size == l) return;
514
515 int i,j;
516 int nr_free = 0;
517
518 for(j=active_size;j<l;j++)
519 G[j] = G_bar[j] + p[j];
520
521 for(j=0;j<active_size;j++)
522 if(is_free(j))
523 nr_free++;
524
525 if(2*nr_free < active_size)
526 info("\nWARNING: using -h 0 may be faster\n");
527
529 {
530 for(i=active_size;i<l;i++)
531 {
532 const Qfloat *Q_i = Q->get_Q(i,active_size);
533 for(j=0;j<active_size;j++)
534 if(is_free(j))
535 G[i] += alpha[j] * Q_i[j];
536 }
537 }
538 else
539 {
540 for(i=0;i<active_size;i++)
541 if(is_free(i))
542 {
543 const Qfloat *Q_i = Q->get_Q(i,l);
544 double alpha_i = alpha[i];
545 for(j=active_size;j<l;j++)
546 G[j] += alpha_i * Q_i[j];
547 }
548 }
549}
550
551void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
552 double *alpha_, double Cp, double Cn, double eps,
553 SolutionInfo* si, int shrinking)
554{
555 this->l = l;
556 this->Q = &Q;
557 QD=Q.get_QD();
558 clone(p, p_,l);
559 clone(y, y_,l);
561 this->Cp = Cp;
562 this->Cn = Cn;
563 this->eps = eps;
564 unshrink = false;
565
566 // initialize alpha_status
567 {
568 alpha_status = new char[l];
569 for(int i=0;i<l;i++)
571 }
572
573 // initialize active set (for shrinking)
574 {
575 active_set = new int[l];
576 for(int i=0;i<l;i++)
577 active_set[i] = i;
578 active_size = l;
579 }
580
581 // initialize gradient
582 {
583 G = new double[l];
584 G_bar = new double[l];
585 int i;
586 for(i=0;i<l;i++)
587 {
588 G[i] = p[i];
589 G_bar[i] = 0;
590 }
591 for(i=0;i<l;i++)
592 if(!is_lower_bound(i))
593 {
594 const Qfloat *Q_i = Q.get_Q(i,l);
595 double alpha_i = alpha[i];
596 int j;
597 for(j=0;j<l;j++)
598 G[j] += alpha_i*Q_i[j];
599 if(is_upper_bound(i))
600 for(j=0;j<l;j++)
601 G_bar[j] += get_C(i) * Q_i[j];
602 }
603 }
604
605 // optimization step
606
607 int iter = 0;
608 int max_iter = max(10000000, l>INT_MAX/100 ? INT_MAX : 100*l);
609 int counter = min(l,1000)+1;
610
611 while(iter < max_iter)
612 {
613 // show progress and do shrinking
614
615 if(--counter == 0)
616 {
617 counter = min(l,1000);
618 if(shrinking) do_shrinking();
619 info(".");
620 }
621
622 int i,j;
623 if(select_working_set(i,j)!=0)
624 {
625 // reconstruct the whole gradient
627 // reset active set size and check
628 active_size = l;
629 info("*");
630 if(select_working_set(i,j)!=0)
631 break;
632 else
633 counter = 1; // do shrinking next iteration
634 }
635
636 ++iter;
637
638 // update alpha[i] and alpha[j], handle bounds carefully
639
640 const Qfloat *Q_i = Q.get_Q(i,active_size);
641 const Qfloat *Q_j = Q.get_Q(j,active_size);
642
643 double C_i = get_C(i);
644 double C_j = get_C(j);
645
646 double old_alpha_i = alpha[i];
647 double old_alpha_j = alpha[j];
648
649 if(y[i]!=y[j])
650 {
651 double quad_coef = QD[i]+QD[j]+2*Q_i[j];
652 if (quad_coef <= 0)
653 quad_coef = TAU;
654 double delta = (-G[i]-G[j])/quad_coef;
655 double diff = alpha[i] - alpha[j];
656 alpha[i] += delta;
657 alpha[j] += delta;
658
659 if(diff > 0)
660 {
661 if(alpha[j] < 0)
662 {
663 alpha[j] = 0;
664 alpha[i] = diff;
665 }
666 }
667 else
668 {
669 if(alpha[i] < 0)
670 {
671 alpha[i] = 0;
672 alpha[j] = -diff;
673 }
674 }
675 if(diff > C_i - C_j)
676 {
677 if(alpha[i] > C_i)
678 {
679 alpha[i] = C_i;
680 alpha[j] = C_i - diff;
681 }
682 }
683 else
684 {
685 if(alpha[j] > C_j)
686 {
687 alpha[j] = C_j;
688 alpha[i] = C_j + diff;
689 }
690 }
691 }
692 else
693 {
694 double quad_coef = QD[i]+QD[j]-2*Q_i[j];
695 if (quad_coef <= 0)
696 quad_coef = TAU;
697 double delta = (G[i]-G[j])/quad_coef;
698 double sum = alpha[i] + alpha[j];
699 alpha[i] -= delta;
700 alpha[j] += delta;
701
702 if(sum > C_i)
703 {
704 if(alpha[i] > C_i)
705 {
706 alpha[i] = C_i;
707 alpha[j] = sum - C_i;
708 }
709 }
710 else
711 {
712 if(alpha[j] < 0)
713 {
714 alpha[j] = 0;
715 alpha[i] = sum;
716 }
717 }
718 if(sum > C_j)
719 {
720 if(alpha[j] > C_j)
721 {
722 alpha[j] = C_j;
723 alpha[i] = sum - C_j;
724 }
725 }
726 else
727 {
728 if(alpha[i] < 0)
729 {
730 alpha[i] = 0;
731 alpha[j] = sum;
732 }
733 }
734 }
735
736 // update G
737
738 double delta_alpha_i = alpha[i] - old_alpha_i;
739 double delta_alpha_j = alpha[j] - old_alpha_j;
740
741 for(int k=0;k<active_size;k++)
742 {
744 }
745
746 // update alpha_status and G_bar
747
748 {
749 bool ui = is_upper_bound(i);
750 bool uj = is_upper_bound(j);
753 int k;
754 if(ui != is_upper_bound(i))
755 {
756 Q_i = Q.get_Q(i,l);
757 if(ui)
758 for(k=0;k<l;k++)
759 G_bar[k] -= C_i * Q_i[k];
760 else
761 for(k=0;k<l;k++)
762 G_bar[k] += C_i * Q_i[k];
763 }
764
765 if(uj != is_upper_bound(j))
766 {
767 Q_j = Q.get_Q(j,l);
768 if(uj)
769 for(k=0;k<l;k++)
770 G_bar[k] -= C_j * Q_j[k];
771 else
772 for(k=0;k<l;k++)
773 G_bar[k] += C_j * Q_j[k];
774 }
775 }
776 }
777
778 if(iter >= max_iter)
779 {
780 if(active_size < l)
781 {
782 // reconstruct the whole gradient to calculate objective value
784 active_size = l;
785 info("*");
786 }
787 fprintf(stderr,"\nWARNING: reaching max number of iterations\n");
788 }
789
790 // calculate rho
791
792 si->rho = calculate_rho();
793
794 // calculate objective value
795 {
796 double v = 0;
797 int i;
798 for(i=0;i<l;i++)
799 v += alpha[i] * (G[i] + p[i]);
800
801 si->obj = v/2;
802 }
803
804 // put back the solution
805 {
806 for(int i=0;i<l;i++)
808 }
809
810 // juggle everything back
811 /*{
812 for(int i=0;i<l;i++)
813 while(active_set[i] != i)
814 swap_index(i,active_set[i]);
815 // or Q.swap_index(i,active_set[i]);
816 }*/
817
818 si->upper_bound_p = Cp;
819 si->upper_bound_n = Cn;
820
821 info("\noptimization finished, #iter = %d\n",iter);
822
823 delete[] p;
824 delete[] y;
825 delete[] alpha;
826 delete[] alpha_status;
827 delete[] active_set;
828 delete[] G;
829 delete[] G_bar;
830}
831
832// return 1 if already optimal, return 0 otherwise
834{
835 // return i,j such that
836 // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha)
837 // j: minimizes the decrease of obj value
838 // (if quadratic coefficeint <= 0, replace it with tau)
839 // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
840
841 double Gmax = -INF;
842 double Gmax2 = -INF;
843 int Gmax_idx = -1;
844 int Gmin_idx = -1;
845 double obj_diff_min = INF;
846
847 for(int t=0;t<active_size;t++)
848 if(y[t]==+1)
849 {
850 if(!is_upper_bound(t))
851 if(-G[t] >= Gmax)
852 {
853 Gmax = -G[t];
854 Gmax_idx = t;
855 }
856 }
857 else
858 {
859 if(!is_lower_bound(t))
860 if(G[t] >= Gmax)
861 {
862 Gmax = G[t];
863 Gmax_idx = t;
864 }
865 }
866
867 int i = Gmax_idx;
868 const Qfloat *Q_i = NULL;
869 if(i != -1) // NULL Q_i not accessed: Gmax=-INF if i=-1
870 Q_i = Q->get_Q(i,active_size);
871
872 for(int j=0;j<active_size;j++)
873 {
874 if(y[j]==+1)
875 {
876 if (!is_lower_bound(j))
877 {
878 double grad_diff=Gmax+G[j];
879 if (G[j] >= Gmax2)
880 Gmax2 = G[j];
881 if (grad_diff > 0)
882 {
883 double obj_diff;
884 double quad_coef = QD[i]+QD[j]-2.0*y[i]*Q_i[j];
885 if (quad_coef > 0)
887 else
889
890 if (obj_diff <= obj_diff_min)
891 {
892 Gmin_idx=j;
894 }
895 }
896 }
897 }
898 else
899 {
900 if (!is_upper_bound(j))
901 {
902 double grad_diff= Gmax-G[j];
903 if (-G[j] >= Gmax2)
904 Gmax2 = -G[j];
905 if (grad_diff > 0)
906 {
907 double obj_diff;
908 double quad_coef = QD[i]+QD[j]+2.0*y[i]*Q_i[j];
909 if (quad_coef > 0)
911 else
913
914 if (obj_diff <= obj_diff_min)
915 {
916 Gmin_idx=j;
918 }
919 }
920 }
921 }
922 }
923
924 if(Gmax+Gmax2 < eps)
925 return 1;
926
927 out_i = Gmax_idx;
928 out_j = Gmin_idx;
929 return 0;
930}
931
932bool Solver::be_shrunk(int i, double Gmax1, double Gmax2)
933{
934 if(is_upper_bound(i))
935 {
936 if(y[i]==+1)
937 return(-G[i] > Gmax1);
938 else
939 return(-G[i] > Gmax2);
940 }
941 else if(is_lower_bound(i))
942 {
943 if(y[i]==+1)
944 return(G[i] > Gmax2);
945 else
946 return(G[i] > Gmax1);
947 }
948 else
949 return(false);
950}
951
953{
954 int i;
955 double Gmax1 = -INF; // max { -y_i * grad(f)_i | i in I_up(\alpha) }
956 double Gmax2 = -INF; // max { y_i * grad(f)_i | i in I_low(\alpha) }
957
958 // find maximal violating pair first
959 for(i=0;i<active_size;i++)
960 {
961 if(y[i]==+1)
962 {
963 if(!is_upper_bound(i))
964 {
965 if(-G[i] >= Gmax1)
966 Gmax1 = -G[i];
967 }
968 if(!is_lower_bound(i))
969 {
970 if(G[i] >= Gmax2)
971 Gmax2 = G[i];
972 }
973 }
974 else
975 {
976 if(!is_upper_bound(i))
977 {
978 if(-G[i] >= Gmax2)
979 Gmax2 = -G[i];
980 }
981 if(!is_lower_bound(i))
982 {
983 if(G[i] >= Gmax1)
984 Gmax1 = G[i];
985 }
986 }
987 }
988
989 if(unshrink == false && Gmax1 + Gmax2 <= eps*10)
990 {
991 unshrink = true;
993 active_size = l;
994 info("*");
995 }
996
997 for(i=0;i<active_size;i++)
998 if (be_shrunk(i, Gmax1, Gmax2))
999 {
1000 active_size--;
1001 while (active_size > i)
1002 {
1004 {
1006 break;
1007 }
1008 active_size--;
1009 }
1010 }
1011}
1012
1014{
1015 double r;
1016 int nr_free = 0;
1017 double ub = INF, lb = -INF, sum_free = 0;
1018 for(int i=0;i<active_size;i++)
1019 {
1020 double yG = y[i]*G[i];
1021
1022 if(is_upper_bound(i))
1023 {
1024 if(y[i]==-1)
1025 ub = min(ub,yG);
1026 else
1027 lb = max(lb,yG);
1028 }
1029 else if(is_lower_bound(i))
1030 {
1031 if(y[i]==+1)
1032 ub = min(ub,yG);
1033 else
1034 lb = max(lb,yG);
1035 }
1036 else
1037 {
1038 ++nr_free;
1039 sum_free += yG;
1040 }
1041 }
1042
1043 if(nr_free>0)
1044 r = sum_free/nr_free;
1045 else
1046 r = (ub+lb)/2;
1047
1048 return r;
1049}
1050
1051//
1052// Solver for nu-svm classification and regression
1053//
1054// additional constraint: e^T \alpha = constant
1055//
1056class Solver_NU: public Solver
1057{
1058public:
1060 void Solve(int l, const QMatrix& Q, const double *p, const schar *y,
1061 double *alpha, double Cp, double Cn, double eps,
1062 SolutionInfo* si, int shrinking)
1063 {
1064 this->si = si;
1065 Solver::Solve(l,Q,p,y,alpha,Cp,Cn,eps,si,shrinking);
1066 }
1067private:
1069 int select_working_set(int &i, int &j);
1070 double calculate_rho();
1071 bool be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4);
1072 void do_shrinking();
1073};
1074
1075// return 1 if already optimal, return 0 otherwise
1077{
1078 // return i,j such that y_i = y_j and
1079 // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha)
1080 // j: minimizes the decrease of obj value
1081 // (if quadratic coefficeint <= 0, replace it with tau)
1082 // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
1083
1084 double Gmaxp = -INF;
1085 double Gmaxp2 = -INF;
1086 int Gmaxp_idx = -1;
1087
1088 double Gmaxn = -INF;
1089 double Gmaxn2 = -INF;
1090 int Gmaxn_idx = -1;
1091
1092 int Gmin_idx = -1;
1093 double obj_diff_min = INF;
1094
1095 for(int t=0;t<active_size;t++)
1096 if(y[t]==+1)
1097 {
1098 if(!is_upper_bound(t))
1099 if(-G[t] >= Gmaxp)
1100 {
1101 Gmaxp = -G[t];
1102 Gmaxp_idx = t;
1103 }
1104 }
1105 else
1106 {
1107 if(!is_lower_bound(t))
1108 if(G[t] >= Gmaxn)
1109 {
1110 Gmaxn = G[t];
1111 Gmaxn_idx = t;
1112 }
1113 }
1114
1115 int ip = Gmaxp_idx;
1116 int in = Gmaxn_idx;
1117 const Qfloat *Q_ip = NULL;
1118 const Qfloat *Q_in = NULL;
1119 if(ip != -1) // NULL Q_ip not accessed: Gmaxp=-INF if ip=-1
1121 if(in != -1)
1122 Q_in = Q->get_Q(in,active_size);
1123
1124 for(int j=0;j<active_size;j++)
1125 {
1126 if(y[j]==+1)
1127 {
1128 if (!is_lower_bound(j))
1129 {
1130 double grad_diff=Gmaxp+G[j];
1131 if (G[j] >= Gmaxp2)
1132 Gmaxp2 = G[j];
1133 if (grad_diff > 0)
1134 {
1135 double obj_diff;
1136 double quad_coef = QD[ip]+QD[j]-2*Q_ip[j];
1137 if (quad_coef > 0)
1139 else
1141
1142 if (obj_diff <= obj_diff_min)
1143 {
1144 Gmin_idx=j;
1146 }
1147 }
1148 }
1149 }
1150 else
1151 {
1152 if (!is_upper_bound(j))
1153 {
1154 double grad_diff=Gmaxn-G[j];
1155 if (-G[j] >= Gmaxn2)
1156 Gmaxn2 = -G[j];
1157 if (grad_diff > 0)
1158 {
1159 double obj_diff;
1160 double quad_coef = QD[in]+QD[j]-2*Q_in[j];
1161 if (quad_coef > 0)
1163 else
1165
1166 if (obj_diff <= obj_diff_min)
1167 {
1168 Gmin_idx=j;
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1177 return 1;
1178
1179 if (y[Gmin_idx] == +1)
1180 out_i = Gmaxp_idx;
1181 else
1182 out_i = Gmaxn_idx;
1183 out_j = Gmin_idx;
1184
1185 return 0;
1186}
1187
1188bool Solver_NU::be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4)
1189{
1190 if(is_upper_bound(i))
1191 {
1192 if(y[i]==+1)
1193 return(-G[i] > Gmax1);
1194 else
1195 return(-G[i] > Gmax4);
1196 }
1197 else if(is_lower_bound(i))
1198 {
1199 if(y[i]==+1)
1200 return(G[i] > Gmax2);
1201 else
1202 return(G[i] > Gmax3);
1203 }
1204 else
1205 return(false);
1206}
1207
1209{
1210 double Gmax1 = -INF; // max { -y_i * grad(f)_i | y_i = +1, i in I_up(\alpha) }
1211 double Gmax2 = -INF; // max { y_i * grad(f)_i | y_i = +1, i in I_low(\alpha) }
1212 double Gmax3 = -INF; // max { -y_i * grad(f)_i | y_i = -1, i in I_up(\alpha) }
1213 double Gmax4 = -INF; // max { y_i * grad(f)_i | y_i = -1, i in I_low(\alpha) }
1214
1215 // find maximal violating pair first
1216 int i;
1217 for(i=0;i<active_size;i++)
1218 {
1219 if(!is_upper_bound(i))
1220 {
1221 if(y[i]==+1)
1222 {
1223 if(-G[i] > Gmax1) Gmax1 = -G[i];
1224 }
1225 else if(-G[i] > Gmax4) Gmax4 = -G[i];
1226 }
1227 if(!is_lower_bound(i))
1228 {
1229 if(y[i]==+1)
1230 {
1231 if(G[i] > Gmax2) Gmax2 = G[i];
1232 }
1233 else if(G[i] > Gmax3) Gmax3 = G[i];
1234 }
1235 }
1236
1237 if(unshrink == false && max(Gmax1+Gmax2,Gmax3+Gmax4) <= eps*10)
1238 {
1239 unshrink = true;
1241 active_size = l;
1242 }
1243
1244 for(i=0;i<active_size;i++)
1245 if (be_shrunk(i, Gmax1, Gmax2, Gmax3, Gmax4))
1246 {
1247 active_size--;
1248 while (active_size > i)
1249 {
1251 {
1253 break;
1254 }
1255 active_size--;
1256 }
1257 }
1258}
1259
1261{
1262 int nr_free1 = 0,nr_free2 = 0;
1263 double ub1 = INF, ub2 = INF;
1264 double lb1 = -INF, lb2 = -INF;
1265 double sum_free1 = 0, sum_free2 = 0;
1266
1267 for(int i=0;i<active_size;i++)
1268 {
1269 if(y[i]==+1)
1270 {
1271 if(is_upper_bound(i))
1272 lb1 = max(lb1,G[i]);
1273 else if(is_lower_bound(i))
1274 ub1 = min(ub1,G[i]);
1275 else
1276 {
1277 ++nr_free1;
1278 sum_free1 += G[i];
1279 }
1280 }
1281 else
1282 {
1283 if(is_upper_bound(i))
1284 lb2 = max(lb2,G[i]);
1285 else if(is_lower_bound(i))
1286 ub2 = min(ub2,G[i]);
1287 else
1288 {
1289 ++nr_free2;
1290 sum_free2 += G[i];
1291 }
1292 }
1293 }
1294
1295 double r1,r2;
1296 if(nr_free1 > 0)
1297 r1 = sum_free1/nr_free1;
1298 else
1299 r1 = (ub1+lb1)/2;
1300
1301 if(nr_free2 > 0)
1302 r2 = sum_free2/nr_free2;
1303 else
1304 r2 = (ub2+lb2)/2;
1305
1306 si->r = (r1+r2)/2;
1307 return (r1-r2)/2;
1308}
1309
1310//
1311// Q matrices for various formulations
1312//
1313class SVC_Q: public Kernel
1314{
1315public:
1316 SVC_Q(const svm_problem& prob, const svm_parameter& param, const schar *y_)
1317 :Kernel(prob.l, prob.x, param)
1318 {
1319 clone(y,y_,prob.l);
1320 cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20)));
1321 QD = new double[prob.l];
1322 for(int i=0;i<prob.l;i++)
1323 QD[i] = (this->*kernel_function)(i,i);
1324 }
1325
1326 Qfloat *get_Q(int i, int len) const
1327 {
1328 Qfloat *data;
1329 int start;
1330 if((start = cache->get_data(i,&data,len)) < len)
1331 {
1332 for(int j=start;j<len;j++)
1333 data[j] = (Qfloat)(y[i]*y[j]*(this->*kernel_function)(i,j));
1334 }
1335 return data;
1336 }
1337
1338 double *get_QD() const
1339 {
1340 return QD;
1341 }
1342
1343 void swap_index(int i, int j) const
1344 {
1345 cache->swap_index(i,j);
1347 swap(y[i],y[j]);
1348 swap(QD[i],QD[j]);
1349 }
1350
1352 {
1353 delete[] y;
1354 delete cache;
1355 delete[] QD;
1356 }
1357private:
1360 double *QD;
1361};
1362
1363class ONE_CLASS_Q: public Kernel
1364{
1365public:
1367 :Kernel(prob.l, prob.x, param)
1368 {
1369 cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20)));
1370 QD = new double[prob.l];
1371 for(int i=0;i<prob.l;i++)
1372 QD[i] = (this->*kernel_function)(i,i);
1373 }
1374
1375 Qfloat *get_Q(int i, int len) const
1376 {
1377 Qfloat *data;
1378 int start;
1379 if((start = cache->get_data(i,&data,len)) < len)
1380 {
1381 for(int j=start;j<len;j++)
1382 data[j] = (Qfloat)(this->*kernel_function)(i,j);
1383 }
1384 return data;
1385 }
1386
1387 double *get_QD() const
1388 {
1389 return QD;
1390 }
1391
1392 void swap_index(int i, int j) const
1393 {
1394 cache->swap_index(i,j);
1396 swap(QD[i],QD[j]);
1397 }
1398
1400 {
1401 delete cache;
1402 delete[] QD;
1403 }
1404private:
1406 double *QD;
1407};
1408
1409class SVR_Q: public Kernel
1410{
1411public:
1412 SVR_Q(const svm_problem& prob, const svm_parameter& param)
1413 :Kernel(prob.l, prob.x, param)
1414 {
1415 l = prob.l;
1416 cache = new Cache(l,(long int)(param.cache_size*(1<<20)));
1417 QD = new double[2*l];
1418 sign = new schar[2*l];
1419 index = new int[2*l];
1420 for(int k=0;k<l;k++)
1421 {
1422 sign[k] = 1;
1423 sign[k+l] = -1;
1424 index[k] = k;
1425 index[k+l] = k;
1426 QD[k] = (this->*kernel_function)(k,k);
1427 QD[k+l] = QD[k];
1428 }
1429 buffer[0] = new Qfloat[2*l];
1430 buffer[1] = new Qfloat[2*l];
1431 next_buffer = 0;
1432 }
1433
1434 void swap_index(int i, int j) const
1435 {
1436 swap(sign[i],sign[j]);
1437 swap(index[i],index[j]);
1438 swap(QD[i],QD[j]);
1439 }
1440
1441 Qfloat *get_Q(int i, int len) const
1442 {
1443 Qfloat *data;
1444 int j, real_i = index[i];
1445 if(cache->get_data(real_i,&data,l) < l)
1446 {
1447 for(j=0;j<l;j++)
1448 data[j] = (Qfloat)(this->*kernel_function)(real_i,j);
1449 }
1450
1451 // reorder and copy
1454 schar si = sign[i];
1455 for(j=0;j<len;j++)
1456 buf[j] = (Qfloat) si * (Qfloat) sign[j] * data[index[j]];
1457 return buf;
1458 }
1459
1460 double *get_QD() const
1461 {
1462 return QD;
1463 }
1464
1466 {
1467 delete cache;
1468 delete[] sign;
1469 delete[] index;
1470 delete[] buffer[0];
1471 delete[] buffer[1];
1472 delete[] QD;
1473 }
1474private:
1475 int l;
1478 int *index;
1479 mutable int next_buffer;
1481 double *QD;
1482};
1483
1484//
1485// construct and solve various formulations
1486//
1487static void solve_c_svc(
1488 const svm_problem *prob, const svm_parameter* param,
1489 double *alpha, Solver::SolutionInfo* si, double Cp, double Cn)
1490{
1491 int l = prob->l;
1492 double *minus_ones = new double[l];
1493 schar *y = new schar[l];
1494
1495 int i;
1496
1497 for(i=0;i<l;i++)
1498 {
1499 alpha[i] = 0;
1500 minus_ones[i] = -1;
1501 if(prob->y[i] > 0) y[i] = +1; else y[i] = -1;
1502 }
1503
1504 Solver s;
1505 s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y,
1506 alpha, Cp, Cn, param->eps, si, param->shrinking);
1507
1508 double sum_alpha=0;
1509 for(i=0;i<l;i++)
1510 sum_alpha += alpha[i];
1511
1512 if (Cp==Cn)
1513 info("nu = %f\n", sum_alpha/(Cp*prob->l));
1514
1515 for(i=0;i<l;i++)
1516 alpha[i] *= y[i];
1517
1518 delete[] minus_ones;
1519 delete[] y;
1520}
1521
1522static void solve_nu_svc(
1523 const svm_problem *prob, const svm_parameter *param,
1524 double *alpha, Solver::SolutionInfo* si)
1525{
1526 int i;
1527 int l = prob->l;
1528 double nu = param->nu;
1529
1530 schar *y = new schar[l];
1531
1532 for(i=0;i<l;i++)
1533 if(prob->y[i]>0)
1534 y[i] = +1;
1535 else
1536 y[i] = -1;
1537
1538 double sum_pos = nu*l/2;
1539 double sum_neg = nu*l/2;
1540
1541 for(i=0;i<l;i++)
1542 if(y[i] == +1)
1543 {
1544 alpha[i] = min(1.0,sum_pos);
1545 sum_pos -= alpha[i];
1546 }
1547 else
1548 {
1549 alpha[i] = min(1.0,sum_neg);
1550 sum_neg -= alpha[i];
1551 }
1552
1553 double *zeros = new double[l];
1554
1555 for(i=0;i<l;i++)
1556 zeros[i] = 0;
1557
1558 Solver_NU s;
1559 s.Solve(l, SVC_Q(*prob,*param,y), zeros, y,
1560 alpha, 1.0, 1.0, param->eps, si, param->shrinking);
1561 double r = si->r;
1562
1563 info("C = %f\n",1/r);
1564
1565 for(i=0;i<l;i++)
1566 alpha[i] *= y[i]/r;
1567
1568 si->rho /= r;
1569 si->obj /= (r*r);
1570 si->upper_bound_p = 1/r;
1571 si->upper_bound_n = 1/r;
1572
1573 delete[] y;
1574 delete[] zeros;
1575}
1576
1578 const svm_problem *prob, const svm_parameter *param,
1579 double *alpha, Solver::SolutionInfo* si)
1580{
1581 int l = prob->l;
1582 double *zeros = new double[l];
1583 schar *ones = new schar[l];
1584 int i;
1585
1586 int n = (int)(param->nu*prob->l); // # of alpha's at upper bound
1587
1588 for(i=0;i<n;i++)
1589 alpha[i] = 1;
1590 if(n<prob->l)
1591 alpha[n] = param->nu * prob->l - n;
1592 for(i=n+1;i<l;i++)
1593 alpha[i] = 0;
1594
1595 for(i=0;i<l;i++)
1596 {
1597 zeros[i] = 0;
1598 ones[i] = 1;
1599 }
1600
1601 Solver s;
1602 s.Solve(l, ONE_CLASS_Q(*prob,*param), zeros, ones,
1603 alpha, 1.0, 1.0, param->eps, si, param->shrinking);
1604
1605 delete[] zeros;
1606 delete[] ones;
1607}
1608
1610 const svm_problem *prob, const svm_parameter *param,
1611 double *alpha, Solver::SolutionInfo* si)
1612{
1613 int l = prob->l;
1614 double *alpha2 = new double[2*l];
1615 double *linear_term = new double[2*l];
1616 schar *y = new schar[2*l];
1617 int i;
1618
1619 for(i=0;i<l;i++)
1620 {
1621 alpha2[i] = 0;
1622 linear_term[i] = param->p - prob->y[i];
1623 y[i] = 1;
1624
1625 alpha2[i+l] = 0;
1626 linear_term[i+l] = param->p + prob->y[i];
1627 y[i+l] = -1;
1628 }
1629
1630 Solver s;
1631 s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
1632 alpha2, param->C, param->C, param->eps, si, param->shrinking);
1633
1634 double sum_alpha = 0;
1635 for(i=0;i<l;i++)
1636 {
1637 alpha[i] = alpha2[i] - alpha2[i+l];
1638 sum_alpha += fabs(alpha[i]);
1639 }
1640 info("nu = %f\n",sum_alpha/(param->C*l));
1641
1642 delete[] alpha2;
1643 delete[] linear_term;
1644 delete[] y;
1645}
1646
1647static void solve_nu_svr(
1648 const svm_problem *prob, const svm_parameter *param,
1649 double *alpha, Solver::SolutionInfo* si)
1650{
1651 int l = prob->l;
1652 double C = param->C;
1653 double *alpha2 = new double[2*l];
1654 double *linear_term = new double[2*l];
1655 schar *y = new schar[2*l];
1656 int i;
1657
1658 double sum = C * param->nu * l / 2;
1659 for(i=0;i<l;i++)
1660 {
1661 alpha2[i] = alpha2[i+l] = min(sum,C);
1662 sum -= alpha2[i];
1663
1664 linear_term[i] = - prob->y[i];
1665 y[i] = 1;
1666
1667 linear_term[i+l] = prob->y[i];
1668 y[i+l] = -1;
1669 }
1670
1671 Solver_NU s;
1672 s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
1673 alpha2, C, C, param->eps, si, param->shrinking);
1674
1675 info("epsilon = %f\n",-si->r);
1676
1677 for(i=0;i<l;i++)
1678 alpha[i] = alpha2[i] - alpha2[i+l];
1679
1680 delete[] alpha2;
1681 delete[] linear_term;
1682 delete[] y;
1683}
1684
1685//
1686// decision_function
1687//
1689{
1690 double *alpha;
1691 double rho;
1692};
1693
1695 const svm_problem *prob, const svm_parameter *param,
1696 double Cp, double Cn)
1697{
1698 double *alpha = Malloc(double,prob->l);
1700 switch(param->svm_type)
1701 {
1702 case C_SVC:
1703 solve_c_svc(prob,param,alpha,&si,Cp,Cn);
1704 break;
1705 case NU_SVC:
1706 solve_nu_svc(prob,param,alpha,&si);
1707 break;
1708 case ONE_CLASS:
1709 solve_one_class(prob,param,alpha,&si);
1710 break;
1711 case EPSILON_SVR:
1712 solve_epsilon_svr(prob,param,alpha,&si);
1713 break;
1714 case NU_SVR:
1715 solve_nu_svr(prob,param,alpha,&si);
1716 break;
1717 }
1718
1719 info("obj = %f, rho = %f\n",si.obj,si.rho);
1720
1721 // output SVs
1722
1723 int nSV = 0;
1724 int nBSV = 0;
1725 for(int i=0;i<prob->l;i++)
1726 {
1727 if(fabs(alpha[i]) > 0)
1728 {
1729 ++nSV;
1730 if(prob->y[i] > 0)
1731 {
1732 if(fabs(alpha[i]) >= si.upper_bound_p)
1733 ++nBSV;
1734 }
1735 else
1736 {
1737 if(fabs(alpha[i]) >= si.upper_bound_n)
1738 ++nBSV;
1739 }
1740 }
1741 }
1742
1743 info("nSV = %d, nBSV = %d\n",nSV,nBSV);
1744
1746 f.alpha = alpha;
1747 f.rho = si.rho;
1748 return f;
1749}
1750
1751// Platt's binary SVM Probablistic Output: an improvement from Lin et al.
1752static void sigmoid_train(
1753 int l, const double *dec_values, const double *labels,
1754 double& A, double& B)
1755{
1756 double prior1=0, prior0 = 0;
1757 int i;
1758
1759 for (i=0;i<l;i++)
1760 if (labels[i] > 0) prior1+=1;
1761 else prior0+=1;
1762
1763 int max_iter=100; // Maximal number of iterations
1764 double min_step=1e-10; // Minimal step taken in line search
1765 double sigma=1e-12; // For numerically strict PD of Hessian
1766 double eps=1e-5;
1767 double hiTarget=(prior1+1.0)/(prior1+2.0);
1768 double loTarget=1/(prior0+2.0);
1769 double *t=Malloc(double,l);
1770 double fApB,p,q;
1771 double newA,newB,newf,d1,d2;
1772 int iter;
1773
1774 // Initial Point and Initial Fun Value
1775 A=0.0; B=log((prior0+1.0)/(prior1+1.0));
1776 double fval = 0.0;
1777
1778 for (i=0;i<l;i++)
1779 {
1780 if (labels[i]>0) t[i]=hiTarget;
1781 else t[i]=loTarget;
1782 fApB = dec_values[i]*A+B;
1783 if (fApB>=0)
1784 fval += t[i]*fApB + log1p(exp(-fApB));
1785 else
1786 fval += (t[i] - 1)*fApB +log1p(exp(fApB));
1787 }
1788 for (iter=0;iter<max_iter;iter++)
1789 {
1790 // Update Gradient and Hessian (use H' = H + sigma I)
1791 double h11=sigma; // numerically ensures strict PD
1792 double h22=sigma;
1793 double h21=0.0;
1794 double g1=0.0;
1795 double g2=0.0;
1796 for (i=0;i<l;i++)
1797 {
1798 fApB = dec_values[i]*A+B;
1799 if (fApB >= 0)
1800 {
1801 p=exp(-fApB)/(1.0+exp(-fApB));
1802 q=1.0/(1.0+exp(-fApB));
1803 }
1804 else
1805 {
1806 p=1.0/(1.0+exp(fApB));
1807 q=exp(fApB)/(1.0+exp(fApB));
1808 }
1809 d2=p*q;
1811 h22+=d2;
1812 h21+=dec_values[i]*d2;
1813 d1=t[i]-p;
1814 g1+=dec_values[i]*d1;
1815 g2+=d1;
1816 }
1817
1818 // Stopping Criteria
1819 if (fabs(g1)<eps && fabs(g2)<eps)
1820 break;
1821
1822 // Finding Newton direction: -inv(H') * g
1823 const double det=h11*h22-h21*h21;
1824 const double dA=-(h22*g1 - h21 * g2) / det;
1825 const double dB=-(-h21*g1+ h11 * g2) / det;
1826 const double gd=g1*dA+g2*dB;
1827
1828
1829 double stepsize = 1; // Line Search
1830 while (stepsize >= min_step)
1831 {
1832 newA = A + stepsize * dA;
1833 newB = B + stepsize * dB;
1834
1835 // New function value
1836 newf = 0.0;
1837 for (i=0;i<l;i++)
1838 {
1840 if (fApB >= 0)
1841 newf += t[i]*fApB + log1p(exp(-fApB));
1842 else
1843 newf += (t[i] - 1)*fApB +log1p(exp(fApB));
1844 }
1845 // Check sufficient decrease
1846 if (newf<fval+0.0001*stepsize*gd)
1847 {
1848 A=newA;B=newB;fval=newf;
1849 break;
1850 }
1851 else
1852 stepsize = stepsize / 2.0;
1853 }
1854
1855 if (stepsize < min_step)
1856 {
1857 info("Line search fails in two-class probability estimates\n");
1858 break;
1859 }
1860 }
1861
1862 if (iter>=max_iter)
1863 info("Reaching maximal iterations in two-class probability estimates\n");
1864 free(t);
1865}
1866
1867static double sigmoid_predict(double decision_value, double A, double B)
1868{
1869 double fApB = decision_value*A+B;
1870 // 1-p used later; avoid catastrophic cancellation
1871 if (fApB >= 0)
1872 return exp(-fApB)/(1.0+exp(-fApB));
1873 else
1874 return 1.0/(1+exp(fApB)) ;
1875}
1876
1877// Method 2 from the multiclass_prob paper by Wu, Lin, and Weng
1878static void multiclass_probability(int k, double **r, double *p)
1879{
1880 int t,j;
1881 int iter = 0, max_iter=max(100,k);
1882 double **Q=Malloc(double *,k);
1883 double *Qp=Malloc(double,k);
1884 double eps=0.005/k;
1885
1886 for (t=0;t<k;t++)
1887 {
1888 p[t]=1.0/k; // Valid if k = 1
1889 Q[t]=Malloc(double,k);
1890 Q[t][t]=0;
1891 for (j=0;j<t;j++)
1892 {
1893 Q[t][t]+=r[j][t]*r[j][t];
1894 Q[t][j]=Q[j][t];
1895 }
1896 for (j=t+1;j<k;j++)
1897 {
1898 Q[t][t]+=r[j][t]*r[j][t];
1899 Q[t][j]=-r[j][t]*r[t][j];
1900 }
1901 }
1902 for (iter=0;iter<max_iter;iter++)
1903 {
1904 // stopping condition, recalculate QP,pQP for numerical accuracy
1905 double pQp=0;
1906 for (t=0;t<k;t++)
1907 {
1908 Qp[t]=0;
1909 for (j=0;j<k;j++)
1910 Qp[t]+=Q[t][j]*p[j];
1911 pQp+=p[t]*Qp[t];
1912 }
1913 double max_error=0;
1914 for (t=0;t<k;t++)
1915 {
1916 double error=fabs(Qp[t]-pQp);
1917 if (error>max_error)
1918 max_error=error;
1919 }
1920 if (max_error<eps) break;
1921
1922 for (t=0;t<k;t++)
1923 {
1924 double diff=(-Qp[t]+pQp)/Q[t][t];
1925 p[t]+=diff;
1926 pQp=(pQp+diff*(diff*Q[t][t]+2*Qp[t]))/(1+diff)/(1+diff);
1927 for (j=0;j<k;j++)
1928 {
1929 Qp[j]=(Qp[j]+diff*Q[t][j])/(1+diff);
1930 p[j]/=(1+diff);
1931 }
1932 }
1933 }
1934 if (iter>=max_iter)
1935 info("Exceeds max_iter in multiclass_prob\n");
1936 for(t=0;t<k;t++) free(Q[t]);
1937 free(Q);
1938 free(Qp);
1939}
1940
1941// Cross-validation decision values for probability estimates
1943 const svm_problem *prob, const svm_parameter *param,
1944 double Cp, double Cn, double& probA, double& probB)
1945{
1946 int i;
1947 int nr_fold = 5;
1948 int *perm = Malloc(int,prob->l);
1949 double *dec_values = Malloc(double,prob->l);
1950
1951 // random shuffle
1952 for(i=0;i<prob->l;i++) perm[i]=i;
1953 for(i=0;i<prob->l;i++)
1954 {
1955 int j = i+rand()%(prob->l-i);
1956 swap(perm[i],perm[j]);
1957 }
1958 for(i=0;i<nr_fold;i++)
1959 {
1960 int begin = i*prob->l/nr_fold;
1961 int end = (i+1)*prob->l/nr_fold;
1962 int j,k;
1963 struct svm_problem subprob;
1964
1965 subprob.l = prob->l-(end-begin);
1966 subprob.x = Malloc(struct svm_node*,subprob.l);
1967 subprob.y = Malloc(double,subprob.l);
1968
1969 k=0;
1970 for(j=0;j<begin;j++)
1971 {
1972 subprob.x[k] = prob->x[perm[j]];
1973 subprob.y[k] = prob->y[perm[j]];
1974 ++k;
1975 }
1976 for(j=end;j<prob->l;j++)
1977 {
1978 subprob.x[k] = prob->x[perm[j]];
1979 subprob.y[k] = prob->y[perm[j]];
1980 ++k;
1981 }
1982 int p_count=0,n_count=0;
1983 for(j=0;j<k;j++)
1984 if(subprob.y[j]>0)
1985 p_count++;
1986 else
1987 n_count++;
1988
1989 if(p_count==0 && n_count==0)
1990 for(j=begin;j<end;j++)
1991 dec_values[perm[j]] = 0;
1992 else if(p_count > 0 && n_count == 0)
1993 for(j=begin;j<end;j++)
1994 dec_values[perm[j]] = 1;
1995 else if(p_count == 0 && n_count > 0)
1996 for(j=begin;j<end;j++)
1997 dec_values[perm[j]] = -1;
1998 else
1999 {
2000 svm_parameter subparam = *param;
2002 subparam.C=1.0;
2003 subparam.nr_weight=2;
2004 subparam.weight_label = Malloc(int,2);
2005 subparam.weight = Malloc(double,2);
2006 subparam.weight_label[0]=+1;
2007 subparam.weight_label[1]=-1;
2008 subparam.weight[0]=Cp;
2009 subparam.weight[1]=Cn;
2011 for(j=begin;j<end;j++)
2012 {
2014 // ensure +1 -1 order; reason not using CV subroutine
2015 dec_values[perm[j]] *= submodel->label[0];
2016 }
2019 }
2020 free(subprob.x);
2021 free(subprob.y);
2022 }
2023 sigmoid_train(prob->l,dec_values,prob->y,probA,probB);
2025 free(perm);
2026}
2027
2028// Return parameter of a Laplace distribution
2030 const svm_problem *prob, const svm_parameter *param)
2031{
2032 int i;
2033 int nr_fold = 5;
2034 double *ymv = Malloc(double,prob->l);
2035 double mae = 0;
2036
2037 svm_parameter newparam = *param;
2040 for(i=0;i<prob->l;i++)
2041 {
2042 ymv[i]=prob->y[i]-ymv[i];
2043 mae += fabs(ymv[i]);
2044 }
2045 mae /= prob->l;
2046 double std=sqrt(2*mae*mae);
2047 int count=0;
2048 mae=0;
2049 for(i=0;i<prob->l;i++)
2050 if (fabs(ymv[i]) > 5*std)
2051 count=count+1;
2052 else
2053 mae+=fabs(ymv[i]);
2054 mae /= (prob->l-count);
2055 info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma= %g\n",mae);
2056 free(ymv);
2057 return mae;
2058}
2059
2060
2061// label: label name, start: begin of each class, count: #data of classes, perm: indices to the original data
2062// perm, length l, must be allocated before calling this subroutine
2063static void svm_group_classes(const svm_problem *prob, int *nr_class_ret, int **label_ret, int **start_ret, int **count_ret, int *perm)
2064{
2065 int l = prob->l;
2066 int max_nr_class = 16;
2067 int nr_class = 0;
2068 int *label = Malloc(int,max_nr_class);
2069 int *count = Malloc(int,max_nr_class);
2070 int *data_label = Malloc(int,l);
2071 int i;
2072
2073 for(i=0;i<l;i++)
2074 {
2075 int this_label = (int)prob->y[i];
2076 int j;
2077 for(j=0;j<nr_class;j++)
2078 {
2079 if(this_label == label[j])
2080 {
2081 ++count[j];
2082 break;
2083 }
2084 }
2085 data_label[i] = j;
2086 if(j == nr_class)
2087 {
2088 if(nr_class == max_nr_class)
2089 {
2090 max_nr_class *= 2;
2091 label = (int *)realloc(label,max_nr_class*sizeof(int));
2092 count = (int *)realloc(count,max_nr_class*sizeof(int));
2093 }
2094 label[nr_class] = this_label;
2095 count[nr_class] = 1;
2096 ++nr_class;
2097 }
2098 }
2099
2100 //
2101 // Labels are ordered by their first occurrence in the training set.
2102 // However, for two-class sets with -1/+1 labels and -1 appears first,
2103 // we swap labels to ensure that internally the binary SVM has positive data corresponding to the +1 instances.
2104 //
2105 if (nr_class == 2 && label[0] == -1 && label[1] == 1)
2106 {
2107 swap(label[0],label[1]);
2108 swap(count[0],count[1]);
2109 for(i=0;i<l;i++)
2110 {
2111 if(data_label[i] == 0)
2112 data_label[i] = 1;
2113 else
2114 data_label[i] = 0;
2115 }
2116 }
2117
2118 int *start = Malloc(int,nr_class);
2119 start[0] = 0;
2120 for(i=1;i<nr_class;i++)
2121 start[i] = start[i-1]+count[i-1];
2122 for(i=0;i<l;i++)
2123 {
2124 perm[start[data_label[i]]] = i;
2125 ++start[data_label[i]];
2126 }
2127 start[0] = 0;
2128 for(i=1;i<nr_class;i++)
2129 start[i] = start[i-1]+count[i-1];
2130
2131 *nr_class_ret = nr_class;
2132 *label_ret = label;
2133 *start_ret = start;
2134 *count_ret = count;
2136}
2137
2138//
2139// Interface functions
2140//
2142{
2144 model->param = *param;
2145 model->free_sv = 0; // XXX
2146
2147 if(param->svm_type == ONE_CLASS ||
2148 param->svm_type == EPSILON_SVR ||
2149 param->svm_type == NU_SVR)
2150 {
2151 // regression or one-class-svm
2152 model->nr_class = 2;
2153 model->label = NULL;
2154 model->nSV = NULL;
2155 model->probA = NULL; model->probB = NULL;
2156 model->sv_coef = Malloc(double *,1);
2157
2158 if(param->probability &&
2159 (param->svm_type == EPSILON_SVR ||
2160 param->svm_type == NU_SVR))
2161 {
2162 model->probA = Malloc(double,1);
2163 model->probA[0] = svm_svr_probability(prob,param);
2164 }
2165
2166 decision_function f = svm_train_one(prob,param,0,0);
2167 model->rho = Malloc(double,1);
2168 model->rho[0] = f.rho;
2169
2170 int nSV = 0;
2171 int i;
2172 for(i=0;i<prob->l;i++)
2173 if(fabs(f.alpha[i]) > 0) ++nSV;
2174 model->l = nSV;
2175 model->SV = Malloc(svm_node *,nSV);
2176 model->sv_coef[0] = Malloc(double,nSV);
2177 model->sv_indices = Malloc(int,nSV);
2178 int j = 0;
2179 for(i=0;i<prob->l;i++)
2180 if(fabs(f.alpha[i]) > 0)
2181 {
2182 model->SV[j] = prob->x[i];
2183 model->sv_coef[0][j] = f.alpha[i];
2184 model->sv_indices[j] = i+1;
2185 ++j;
2186 }
2187
2188 free(f.alpha);
2189 }
2190 else
2191 {
2192 // classification
2193 int l = prob->l;
2194 int nr_class;
2195 int *label = NULL;
2196 int *start = NULL;
2197 int *count = NULL;
2198 int *perm = Malloc(int,l);
2199
2200 // group training data of the same class
2201 svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
2202 if(nr_class == 1)
2203 info("WARNING: training data in only one class. See README for details.\n");
2204
2205 svm_node **x = Malloc(svm_node *,l);
2206 int i;
2207 for(i=0;i<l;i++)
2208 x[i] = prob->x[perm[i]];
2209
2210 // calculate weighted C
2211
2212 double *weighted_C = Malloc(double, nr_class);
2213 for(i=0;i<nr_class;i++)
2214 weighted_C[i] = param->C;
2215 for(i=0;i<param->nr_weight;i++)
2216 {
2217 int j;
2218 for(j=0;j<nr_class;j++)
2219 if(param->weight_label[i] == label[j])
2220 break;
2221 if(j == nr_class)
2222 fprintf(stderr,"WARNING: class label %d specified in weight is not found\n", param->weight_label[i]);
2223 else
2224 weighted_C[j] *= param->weight[i];
2225 }
2226
2227 // train k*(k-1)/2 models
2228
2229 bool *nonzero = Malloc(bool,l);
2230 for(i=0;i<l;i++)
2231 nonzero[i] = false;
2232 decision_function *f = Malloc(decision_function,nr_class*(nr_class-1)/2);
2233
2234 double *probA=NULL,*probB=NULL;
2235 if (param->probability)
2236 {
2237 probA=Malloc(double,nr_class*(nr_class-1)/2);
2238 probB=Malloc(double,nr_class*(nr_class-1)/2);
2239 }
2240
2241 int p = 0;
2242 for(i=0;i<nr_class;i++)
2243 for(int j=i+1;j<nr_class;j++)
2244 {
2246 int si = start[i], sj = start[j];
2247 int ci = count[i], cj = count[j];
2248 sub_prob.l = ci+cj;
2250 sub_prob.y = Malloc(double,sub_prob.l);
2251 int k;
2252 for(k=0;k<ci;k++)
2253 {
2254 sub_prob.x[k] = x[si+k];
2255 sub_prob.y[k] = +1;
2256 }
2257 for(k=0;k<cj;k++)
2258 {
2259 sub_prob.x[ci+k] = x[sj+k];
2260 sub_prob.y[ci+k] = -1;
2261 }
2262
2263 if(param->probability)
2264 svm_binary_svc_probability(&sub_prob,param,weighted_C[i],weighted_C[j],probA[p],probB[p]);
2265
2266 f[p] = svm_train_one(&sub_prob,param,weighted_C[i],weighted_C[j]);
2267 for(k=0;k<ci;k++)
2268 if(!nonzero[si+k] && fabs(f[p].alpha[k]) > 0)
2269 nonzero[si+k] = true;
2270 for(k=0;k<cj;k++)
2271 if(!nonzero[sj+k] && fabs(f[p].alpha[ci+k]) > 0)
2272 nonzero[sj+k] = true;
2273 free(sub_prob.x);
2274 free(sub_prob.y);
2275 ++p;
2276 }
2277
2278 // build output
2279
2280 model->nr_class = nr_class;
2281
2282 model->label = Malloc(int,nr_class);
2283 for(i=0;i<nr_class;i++)
2284 model->label[i] = label[i];
2285
2286 model->rho = Malloc(double,nr_class*(nr_class-1)/2);
2287 for(i=0;i<nr_class*(nr_class-1)/2;i++)
2288 model->rho[i] = f[i].rho;
2289
2290 if(param->probability)
2291 {
2292 model->probA = Malloc(double,nr_class*(nr_class-1)/2);
2293 model->probB = Malloc(double,nr_class*(nr_class-1)/2);
2294 for(i=0;i<nr_class*(nr_class-1)/2;i++)
2295 {
2296 model->probA[i] = probA[i];
2297 model->probB[i] = probB[i];
2298 }
2299 }
2300 else
2301 {
2302 model->probA=NULL;
2303 model->probB=NULL;
2304 }
2305
2306 int total_sv = 0;
2307 int *nz_count = Malloc(int,nr_class);
2308 model->nSV = Malloc(int,nr_class);
2309 for(i=0;i<nr_class;i++)
2310 {
2311 int nSV = 0;
2312 for(int j=0;j<count[i];j++)
2313 if(nonzero[start[i]+j])
2314 {
2315 ++nSV;
2316 ++total_sv;
2317 }
2318 model->nSV[i] = nSV;
2319 nz_count[i] = nSV;
2320 }
2321
2322 info("Total nSV = %d\n",total_sv);
2323
2324 model->l = total_sv;
2325 model->SV = Malloc(svm_node *,total_sv);
2326 model->sv_indices = Malloc(int,total_sv);
2327 p = 0;
2328 for(i=0;i<l;i++)
2329 if(nonzero[i])
2330 {
2331 model->SV[p] = x[i];
2332 model->sv_indices[p++] = perm[i] + 1;
2333 }
2334
2335 int *nz_start = Malloc(int,nr_class);
2336 nz_start[0] = 0;
2337 for(i=1;i<nr_class;i++)
2338 nz_start[i] = nz_start[i-1]+nz_count[i-1];
2339
2340 model->sv_coef = Malloc(double *,nr_class-1);
2341 for(i=0;i<nr_class-1;i++)
2342 model->sv_coef[i] = Malloc(double,total_sv);
2343
2344 p = 0;
2345 for(i=0;i<nr_class;i++)
2346 for(int j=i+1;j<nr_class;j++)
2347 {
2348 // classifier (i,j): coefficients with
2349 // i are in sv_coef[j-1][nz_start[i]...],
2350 // j are in sv_coef[i][nz_start[j]...]
2351
2352 int si = start[i];
2353 int sj = start[j];
2354 int ci = count[i];
2355 int cj = count[j];
2356
2357 int q = nz_start[i];
2358 int k;
2359 for(k=0;k<ci;k++)
2360 if(nonzero[si+k])
2361 model->sv_coef[j-1][q++] = f[p].alpha[k];
2362 q = nz_start[j];
2363 for(k=0;k<cj;k++)
2364 if(nonzero[sj+k])
2365 model->sv_coef[i][q++] = f[p].alpha[ci+k];
2366 ++p;
2367 }
2368
2369 free(label);
2370 free(probA);
2371 free(probB);
2372 free(count);
2373 free(perm);
2374 free(start);
2375 free(x);
2377 free(nonzero);
2378 for(i=0;i<nr_class*(nr_class-1)/2;i++)
2379 free(f[i].alpha);
2380 free(f);
2381 free(nz_count);
2382 free(nz_start);
2383 }
2384 return model;
2385}
2386
2387// Stratified cross validation
2388void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, int nr_fold, double *target)
2389{
2390 int i;
2391 int *fold_start;
2392 int l = prob->l;
2393 int *perm = Malloc(int,l);
2394 int nr_class;
2395 if (nr_fold > l)
2396 {
2397 nr_fold = l;
2398 fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n");
2399 }
2400 fold_start = Malloc(int,nr_fold+1);
2401 // stratified cv may not give leave-one-out rate
2402 // Each class to l folds -> some folds may have zero elements
2403 if((param->svm_type == C_SVC ||
2404 param->svm_type == NU_SVC) && nr_fold < l)
2405 {
2406 int *start = NULL;
2407 int *label = NULL;
2408 int *count = NULL;
2409 svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
2410
2411 // random shuffle and then data grouped by fold using the array perm
2412 int *fold_count = Malloc(int,nr_fold);
2413 int c;
2414 int *index = Malloc(int,l);
2415 for(i=0;i<l;i++)
2416 index[i]=perm[i];
2417 for (c=0; c<nr_class; c++)
2418 for(i=0;i<count[c];i++)
2419 {
2420 int j = i+rand()%(count[c]-i);
2421 swap(index[start[c]+j],index[start[c]+i]);
2422 }
2423 for(i=0;i<nr_fold;i++)
2424 {
2425 fold_count[i] = 0;
2426 for (c=0; c<nr_class;c++)
2427 fold_count[i]+=(i+1)*count[c]/nr_fold-i*count[c]/nr_fold;
2428 }
2429 fold_start[0]=0;
2430 for (i=1;i<=nr_fold;i++)
2432 for (c=0; c<nr_class;c++)
2433 for(i=0;i<nr_fold;i++)
2434 {
2435 int begin = start[c]+i*count[c]/nr_fold;
2436 int end = start[c]+(i+1)*count[c]/nr_fold;
2437 for(int j=begin;j<end;j++)
2438 {
2439 perm[fold_start[i]] = index[j];
2440 fold_start[i]++;
2441 }
2442 }
2443 fold_start[0]=0;
2444 for (i=1;i<=nr_fold;i++)
2446 free(start);
2447 free(label);
2448 free(count);
2449 free(index);
2451 }
2452 else
2453 {
2454 for(i=0;i<l;i++) perm[i]=i;
2455 for(i=0;i<l;i++)
2456 {
2457 int j = i+rand()%(l-i);
2458 swap(perm[i],perm[j]);
2459 }
2460 for(i=0;i<=nr_fold;i++)
2461 fold_start[i]=i*l/nr_fold;
2462 }
2463
2464 for(i=0;i<nr_fold;i++)
2465 {
2466 int begin = fold_start[i];
2467 int end = fold_start[i+1];
2468 int j,k;
2469 struct svm_problem subprob;
2470
2471 subprob.l = l-(end-begin);
2472 subprob.x = Malloc(struct svm_node*,subprob.l);
2473 subprob.y = Malloc(double,subprob.l);
2474
2475 k=0;
2476 for(j=0;j<begin;j++)
2477 {
2478 subprob.x[k] = prob->x[perm[j]];
2479 subprob.y[k] = prob->y[perm[j]];
2480 ++k;
2481 }
2482 for(j=end;j<l;j++)
2483 {
2484 subprob.x[k] = prob->x[perm[j]];
2485 subprob.y[k] = prob->y[perm[j]];
2486 ++k;
2487 }
2488 struct svm_model *submodel = svm_train(&subprob,param);
2489 if(param->probability &&
2490 (param->svm_type == C_SVC || param->svm_type == NU_SVC))
2491 {
2493 for(j=begin;j<end;j++)
2496 }
2497 else
2498 for(j=begin;j<end;j++)
2499 target[perm[j]] = svm_predict(submodel,prob->x[perm[j]]);
2501 free(subprob.x);
2502 free(subprob.y);
2503 }
2505 free(perm);
2506}
2507
2508
2510{
2511 return model->param.svm_type;
2512}
2513
2515{
2516 return model->nr_class;
2517}
2518
2519void svm_get_labels(const svm_model *model, int* label)
2520{
2521 if (model->label != NULL)
2522 for(int i=0;i<model->nr_class;i++)
2523 label[i] = model->label[i];
2524}
2525
2527{
2528 if (model->sv_indices != NULL)
2529 for(int i=0;i<model->l;i++)
2530 indices[i] = model->sv_indices[i];
2531}
2532
2534{
2535 return model->l;
2536}
2537
2539{
2540 if ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) &&
2541 model->probA!=NULL)
2542 return model->probA[0];
2543 else
2544 {
2545 fprintf(stderr,"Model doesn't contain information for SVR probability inference\n");
2546 return 0;
2547 }
2548}
2549
2550double svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values)
2551{
2552 int i;
2553 if(model->param.svm_type == ONE_CLASS ||
2554 model->param.svm_type == EPSILON_SVR ||
2555 model->param.svm_type == NU_SVR)
2556 {
2557 double *sv_coef = model->sv_coef[0];
2558 double sum = 0;
2559 for(i=0;i<model->l;i++)
2560 sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param);
2561 sum -= model->rho[0];
2562 *dec_values = sum;
2563
2564 if(model->param.svm_type == ONE_CLASS)
2565 return (sum>0)?1:-1;
2566 else
2567 return sum;
2568 }
2569 else
2570 {
2571 int nr_class = model->nr_class;
2572 int l = model->l;
2573
2574 double *kvalue = Malloc(double,l);
2575 for(i=0;i<l;i++)
2576 kvalue[i] = Kernel::k_function(x,model->SV[i],model->param);
2577
2578 int *start = Malloc(int,nr_class);
2579 start[0] = 0;
2580 for(i=1;i<nr_class;i++)
2581 start[i] = start[i-1]+model->nSV[i-1];
2582
2583 int *vote = Malloc(int,nr_class);
2584 for(i=0;i<nr_class;i++)
2585 vote[i] = 0;
2586
2587 int p=0;
2588 for(i=0;i<nr_class;i++)
2589 for(int j=i+1;j<nr_class;j++)
2590 {
2591 double sum = 0;
2592 int si = start[i];
2593 int sj = start[j];
2594 int ci = model->nSV[i];
2595 int cj = model->nSV[j];
2596
2597 int k;
2598 double *coef1 = model->sv_coef[j-1];
2599 double *coef2 = model->sv_coef[i];
2600 for(k=0;k<ci;k++)
2601 sum += coef1[si+k] * kvalue[si+k];
2602 for(k=0;k<cj;k++)
2603 sum += coef2[sj+k] * kvalue[sj+k];
2604 sum -= model->rho[p];
2605 dec_values[p] = sum;
2606
2607 if(dec_values[p] > 0)
2608 ++vote[i];
2609 else
2610 ++vote[j];
2611 p++;
2612 }
2613
2614 int vote_max_idx = 0;
2615 for(i=1;i<nr_class;i++)
2616 if(vote[i] > vote[vote_max_idx])
2617 vote_max_idx = i;
2618
2619 free(kvalue);
2620 free(start);
2621 free(vote);
2622 return model->label[vote_max_idx];
2623 }
2624}
2625
2626double svm_predict(const svm_model *model, const svm_node *x)
2627{
2628 int nr_class = model->nr_class;
2629 double *dec_values;
2630 if(model->param.svm_type == ONE_CLASS ||
2631 model->param.svm_type == EPSILON_SVR ||
2632 model->param.svm_type == NU_SVR)
2633 dec_values = Malloc(double, 1);
2634 else
2635 dec_values = Malloc(double, nr_class*(nr_class-1)/2);
2638 return pred_result;
2639}
2640
2642 const svm_model *model, const svm_node *x, double *prob_estimates)
2643{
2644 if ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) &&
2645 model->probA!=NULL && model->probB!=NULL)
2646 {
2647 int i;
2648 int nr_class = model->nr_class;
2649 double *dec_values = Malloc(double, nr_class*(nr_class-1)/2);
2651
2652 double min_prob=1e-7;
2653 double **pairwise_prob=Malloc(double *,nr_class);
2654 for(i=0;i<nr_class;i++)
2655 pairwise_prob[i]=Malloc(double,nr_class);
2656 int k=0;
2657 for(i=0;i<nr_class;i++)
2658 for(int j=i+1;j<nr_class;j++)
2659 {
2662 k++;
2663 }
2665
2666 int prob_max_idx = 0;
2667 for(i=1;i<nr_class;i++)
2669 prob_max_idx = i;
2670 for(i=0;i<nr_class;i++)
2674 return model->label[prob_max_idx];
2675 }
2676 else
2677 return svm_predict(model, x);
2678}
2679
2680static const char *svm_type_table[] =
2681{
2682 "c_svc","nu_svc","one_class","epsilon_svr","nu_svr",NULL
2683};
2684
2685static const char *kernel_type_table[]=
2686{
2687 "linear","polynomial","rbf","sigmoid","precomputed",NULL
2688};
2689
2691{
2692 FILE *fp = fopen(model_file_name,"w");
2693 if(fp==NULL) return -1;
2694
2696 setlocale(LC_ALL, "C");
2697
2698 const svm_parameter& param = model->param;
2699
2700 fprintf(fp,"svm_type %s\n", svm_type_table[param.svm_type]);
2701 fprintf(fp,"kernel_type %s\n", kernel_type_table[param.kernel_type]);
2702
2703 if(param.kernel_type == POLY)
2704 fprintf(fp,"degree %d\n", param.degree);
2705
2706 if(param.kernel_type == POLY || param.kernel_type == RBF || param.kernel_type == SIGMOID)
2707 fprintf(fp,"gamma %g\n", param.gamma);
2708
2709 if(param.kernel_type == POLY || param.kernel_type == SIGMOID)
2710 fprintf(fp,"coef0 %g\n", param.coef0);
2711
2712 int nr_class = model->nr_class;
2713 int l = model->l;
2714 fprintf(fp, "nr_class %d\n", nr_class);
2715 fprintf(fp, "total_sv %d\n",l);
2716
2717 {
2718 fprintf(fp, "rho");
2719 for(int i=0;i<nr_class*(nr_class-1)/2;i++)
2720 fprintf(fp," %g",model->rho[i]);
2721 fprintf(fp, "\n");
2722 }
2723
2724 if(model->label)
2725 {
2726 fprintf(fp, "label");
2727 for(int i=0;i<nr_class;i++)
2728 fprintf(fp," %d",model->label[i]);
2729 fprintf(fp, "\n");
2730 }
2731
2732 if(model->probA) // regression has probA only
2733 {
2734 fprintf(fp, "probA");
2735 for(int i=0;i<nr_class*(nr_class-1)/2;i++)
2736 fprintf(fp," %g",model->probA[i]);
2737 fprintf(fp, "\n");
2738 }
2739 if(model->probB)
2740 {
2741 fprintf(fp, "probB");
2742 for(int i=0;i<nr_class*(nr_class-1)/2;i++)
2743 fprintf(fp," %g",model->probB[i]);
2744 fprintf(fp, "\n");
2745 }
2746
2747 if(model->nSV)
2748 {
2749 fprintf(fp, "nr_sv");
2750 for(int i=0;i<nr_class;i++)
2751 fprintf(fp," %d",model->nSV[i]);
2752 fprintf(fp, "\n");
2753 }
2754
2755 fprintf(fp, "SV\n");
2756 const double * const *sv_coef = model->sv_coef;
2757 const svm_node * const *SV = model->SV;
2758
2759 for(int i=0;i<l;i++)
2760 {
2761 for(int j=0;j<nr_class-1;j++)
2762 fprintf(fp, "%.16g ",sv_coef[j][i]);
2763
2764 const svm_node *p = SV[i];
2765
2766 if(param.kernel_type == PRECOMPUTED)
2767 fprintf(fp,"0:%d ",(int)(p->value));
2768 else
2769 while(p->index != -1)
2770 {
2771 fprintf(fp,"%d:%.8g ",p->index,p->value);
2772 p++;
2773 }
2774 fprintf(fp, "\n");
2775 }
2776
2779
2780 if (ferror(fp) != 0 || fclose(fp) != 0) return -1;
2781 else return 0;
2782}
2783
2784static char *line = NULL;
2785static int max_line_len;
2786
2787static char* readline(FILE *input)
2788{
2790 return NULL;
2791
2792 while(strrchr(line,'\n') == NULL)
2793 {
2794 max_line_len *= 2;
2795 line = (char *) realloc(line,max_line_len);
2796 int len = (int) strlen(line);
2797 if(fgets(line+len,max_line_len-len,input) == NULL)
2798 break;
2799 }
2800 return line;
2801}
2802
2803//
2804// FSCANF helps to handle fscanf failures.
2805// Its do-while block avoids the ambiguity when
2806// if (...)
2807// FSCANF();
2808// is used
2809//
2810#define FSCANF(_stream, _format, _var) do{ if (fscanf(_stream, _format, _var) != 1) return false; }while(0)
2812{
2813 svm_parameter& param = model->param;
2814 char cmd[101];
2815 while(1)
2816 {
2817 FSCANF(fp,"%100s",cmd);
2818
2819 if(strcmp(cmd,"svm_type")==0)
2820 {
2821 FSCANF(fp,"%100s",cmd);
2822 int i;
2823 for(i=0;svm_type_table[i];i++)
2824 {
2825 if(strcmp(svm_type_table[i],cmd)==0)
2826 {
2827 param.svm_type=i;
2828 break;
2829 }
2830 }
2831 if(svm_type_table[i] == NULL)
2832 {
2833 fprintf(stderr,"unknown svm type.\n");
2834 return false;
2835 }
2836 }
2837 else if(strcmp(cmd,"kernel_type")==0)
2838 {
2839 FSCANF(fp,"%100s",cmd);
2840 int i;
2841 for(i=0;kernel_type_table[i];i++)
2842 {
2843 if(strcmp(kernel_type_table[i],cmd)==0)
2844 {
2845 param.kernel_type=i;
2846 break;
2847 }
2848 }
2849 if(kernel_type_table[i] == NULL)
2850 {
2851 fprintf(stderr,"unknown kernel function.\n");
2852 return false;
2853 }
2854 }
2855 else if(strcmp(cmd,"degree")==0)
2856 FSCANF(fp,"%d",&param.degree);
2857 else if(strcmp(cmd,"gamma")==0)
2858 FSCANF(fp,"%lf",&param.gamma);
2859 else if(strcmp(cmd,"coef0")==0)
2860 FSCANF(fp,"%lf",&param.coef0);
2861 else if(strcmp(cmd,"nr_class")==0)
2862 {
2863 FSCANF(fp,"%d",&model->nr_class);
2864 if (model->nr_class > 128)
2865 {
2866 fprintf(stderr, "nr_class too big");
2867 return false;
2868 };
2869 }
2870 else if(strcmp(cmd,"total_sv")==0)
2871 FSCANF(fp,"%d",&model->l);
2872 else if(strcmp(cmd,"rho")==0)
2873 {
2874 int n = model->nr_class * (model->nr_class-1)/2;
2875 model->rho = Malloc(double,n);
2876 for(int i=0;i<n;i++)
2877 FSCANF(fp,"%lf",&model->rho[i]);
2878 }
2879 else if(strcmp(cmd,"label")==0)
2880 {
2881 int n = model->nr_class;
2882 model->label = Malloc(int,n);
2883 for(int i=0;i<n;i++)
2884 FSCANF(fp,"%d",&model->label[i]);
2885 }
2886 else if(strcmp(cmd,"probA")==0)
2887 {
2888 int n = model->nr_class * (model->nr_class-1)/2;
2889 model->probA = Malloc(double,n);
2890 for(int i=0;i<n;i++)
2891 FSCANF(fp,"%lf",&model->probA[i]);
2892 }
2893 else if(strcmp(cmd,"probB")==0)
2894 {
2895 int n = model->nr_class * (model->nr_class-1)/2;
2896 model->probB = Malloc(double,n);
2897 for(int i=0;i<n;i++)
2898 FSCANF(fp,"%lf",&model->probB[i]);
2899 }
2900 else if(strcmp(cmd,"nr_sv")==0)
2901 {
2902 int n = model->nr_class;
2903 model->nSV = Malloc(int,n);
2904 for(int i=0;i<n;i++)
2905 FSCANF(fp,"%d",&model->nSV[i]);
2906 }
2907 else if(strcmp(cmd,"license")==0)
2908 {
2909 FSCANF(fp,"%100s",cmd);
2910 //std::cout << "License: " << cmd << std::endl;
2911
2912 }
2913 else if(strcmp(cmd,"SV")==0)
2914 {
2915 while(1)
2916 {
2917 int c = getc(fp);
2918 if(c==EOF || c=='\n') break;
2919 }
2920 break;
2921 }
2922 else
2923 {
2924 fprintf(stderr,"unknown text in model file: [%s]\n",cmd);
2925 return false;
2926 }
2927 }
2928
2929 return true;
2930
2931}
2932
2934{
2935 FILE *fp = fopen(model_file_name,"rb");
2936 if(fp==NULL) return NULL;
2937
2939 setlocale(LC_ALL, "C");
2940
2941 // read parameters
2942
2944 model->rho = NULL;
2945 model->probA = NULL;
2946 model->probB = NULL;
2947 model->sv_indices = NULL;
2948 model->label = NULL;
2949 model->nSV = NULL;
2950
2951 // read header
2952 if (!read_model_header(fp, model))
2953 {
2954 fprintf(stderr, "ERROR: fscanf failed to read model\n");
2957 free(model->rho);
2958 free(model->label);
2959 free(model->nSV);
2960 free(model);
2961 return NULL;
2962 }
2963
2964 // read sv_coef and SV
2965
2966 int elements = 0;
2967 long pos = ftell(fp);
2968
2969 max_line_len = 1024;
2970 line = Malloc(char,max_line_len);
2971 char *p,*endptr,*idx,*val;
2972
2973 while(readline(fp)!=NULL)
2974 {
2975 p = strtok(line,":");
2976 while(1)
2977 {
2978 p = strtok(NULL,":");
2979 if(p == NULL)
2980 break;
2981 ++elements;
2982 }
2983 }
2984 elements += model->l;
2985
2987
2988 int m = model->nr_class - 1;
2989 int l = model->l;
2990 model->sv_coef = Malloc(double *,m);
2991 int i;
2992 for(i=0;i<m;i++)
2993 model->sv_coef[i] = Malloc(double,l);
2994 model->SV = Malloc(svm_node*,l);
2996 if(l>0) x_space = Malloc(svm_node,elements);
2997
2998 int j=0;
2999 for(i=0;i<l;i++)
3000 {
3001 readline(fp);
3002 model->SV[i] = &x_space[j];
3003
3004 p = strtok(line, " \t");
3005 model->sv_coef[0][i] = strtod(p,&endptr);
3006 for(int k=1;k<m;k++)
3007 {
3008 p = strtok(NULL, " \t");
3009 model->sv_coef[k][i] = strtod(p,&endptr);
3010 }
3011
3012 while(1)
3013 {
3014 idx = strtok(NULL, ":");
3015 val = strtok(NULL, " \t");
3016
3017 if(val == NULL)
3018 break;
3019 x_space[j].index = (int) strtol(idx,&endptr,10);
3020 x_space[j].value = strtod(val,&endptr);
3021
3022 ++j;
3023 }
3024 x_space[j++].index = -1;
3025 }
3026 free(line);
3027
3030
3031 if (ferror(fp) != 0 || fclose(fp) != 0)
3032 return NULL;
3033
3034 model->free_sv = 1; // XXX
3035 return model;
3036}
3037
3039{
3040 if(model_ptr->free_sv && model_ptr->l > 0 && model_ptr->SV != NULL)
3041 free((void *)(model_ptr->SV[0]));
3042 if(model_ptr->sv_coef)
3043 {
3044 for(int i=0;i<model_ptr->nr_class-1;i++)
3045 free(model_ptr->sv_coef[i]);
3046 }
3047
3048 free(model_ptr->SV);
3049 model_ptr->SV = NULL;
3050
3051 free(model_ptr->sv_coef);
3052 model_ptr->sv_coef = NULL;
3053
3054 free(model_ptr->rho);
3055 model_ptr->rho = NULL;
3056
3057 free(model_ptr->label);
3058 model_ptr->label= NULL;
3059
3060 free(model_ptr->probA);
3061 model_ptr->probA = NULL;
3062
3063 free(model_ptr->probB);
3064 model_ptr->probB= NULL;
3065
3066 free(model_ptr->sv_indices);
3067 model_ptr->sv_indices = NULL;
3068
3069 free(model_ptr->nSV);
3070 model_ptr->nSV = NULL;
3071}
3072
3082
3084{
3085 free(param->weight_label);
3086 free(param->weight);
3087}
3088
3089const char *svm_check_parameter(const svm_problem *prob, const svm_parameter *param)
3090{
3091 // svm_type
3092
3093 int svm_type = param->svm_type;
3094 if(svm_type != C_SVC &&
3095 svm_type != NU_SVC &&
3096 svm_type != ONE_CLASS &&
3097 svm_type != EPSILON_SVR &&
3098 svm_type != NU_SVR)
3099 return "unknown svm type";
3100
3101 // kernel_type, degree
3102
3103 int kernel_type = param->kernel_type;
3104 if(kernel_type != LINEAR &&
3105 kernel_type != POLY &&
3106 kernel_type != RBF &&
3107 kernel_type != SIGMOID &&
3108 kernel_type != PRECOMPUTED)
3109 return "unknown kernel type";
3110
3111 if(param->gamma < 0)
3112 return "gamma < 0";
3113
3114 if(param->degree < 0)
3115 return "degree of polynomial kernel < 0";
3116
3117 // cache_size,eps,C,nu,p,shrinking
3118
3119 if(param->cache_size <= 0)
3120 return "cache_size <= 0";
3121
3122 if(param->eps <= 0)
3123 return "eps <= 0";
3124
3125 if(svm_type == C_SVC ||
3126 svm_type == EPSILON_SVR ||
3127 svm_type == NU_SVR)
3128 if(param->C <= 0)
3129 return "C <= 0";
3130
3131 if(svm_type == NU_SVC ||
3132 svm_type == ONE_CLASS ||
3133 svm_type == NU_SVR)
3134 if(param->nu <= 0 || param->nu > 1)
3135 return "nu <= 0 or nu > 1";
3136
3137 if(svm_type == EPSILON_SVR)
3138 if(param->p < 0)
3139 return "p < 0";
3140
3141 if(param->shrinking != 0 &&
3142 param->shrinking != 1)
3143 return "shrinking != 0 and shrinking != 1";
3144
3145 if(param->probability != 0 &&
3146 param->probability != 1)
3147 return "probability != 0 and probability != 1";
3148
3149 if(param->probability == 1 &&
3150 svm_type == ONE_CLASS)
3151 return "one-class SVM probability output not supported yet";
3152
3153
3154 // check whether nu-svc is feasible
3155
3156 if(svm_type == NU_SVC)
3157 {
3158 int l = prob->l;
3159 int max_nr_class = 16;
3160 int nr_class = 0;
3161 int *label = Malloc(int,max_nr_class);
3162 int *count = Malloc(int,max_nr_class);
3163
3164 int i;
3165 for(i=0;i<l;i++)
3166 {
3167 int this_label = (int)prob->y[i];
3168 int j;
3169 for(j=0;j<nr_class;j++)
3170 if(this_label == label[j])
3171 {
3172 ++count[j];
3173 break;
3174 }
3175 if(j == nr_class)
3176 {
3177 if(nr_class == max_nr_class)
3178 {
3179 max_nr_class *= 2;
3180 label = (int *)realloc(label,max_nr_class*sizeof(int));
3181 count = (int *)realloc(count,max_nr_class*sizeof(int));
3182 }
3183 label[nr_class] = this_label;
3184 count[nr_class] = 1;
3185 ++nr_class;
3186 }
3187 }
3188
3189 for(i=0;i<nr_class;i++)
3190 {
3191 int n1 = count[i];
3192 for(int j=i+1;j<nr_class;j++)
3193 {
3194 int n2 = count[j];
3195 if(param->nu*(n1+n2)/2 > min(n1,n2))
3196 {
3197 free(label);
3198 free(count);
3199 return "specified nu is infeasible";
3200 }
3201 }
3202 }
3203 free(label);
3204 free(count);
3205 }
3206
3207 return NULL;
3208}
3209
3211{
3212 return ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) &&
3213 model->probA!=NULL && model->probB!=NULL) ||
3214 ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) &&
3215 model->probA!=NULL);
3216}
3217
3219{
3220 if(print_func == NULL)
3222 else
3224}
3225
3226}; // namespace
void lru_insert(head_t *h)
Definition svm.cpp:164
int get_data(const int index, Qfloat **data, int len)
Definition svm.cpp:173
void lru_delete(head_t *h)
Definition svm.cpp:157
head_t lru_head
Definition svm.cpp:136
long int size
Definition svm.cpp:127
Cache(int l, long int size)
Definition svm.cpp:141
void swap_index(int i, int j)
Definition svm.cpp:203
head_t * head
Definition svm.cpp:135
const double gamma
Definition svm.cpp:274
double kernel_precomputed(int i, int j) const
Definition svm.cpp:294
const int degree
Definition svm.cpp:273
const int kernel_type
Definition svm.cpp:272
virtual ~Kernel()
Definition svm.cpp:335
double kernel_rbf(int i, int j) const
Definition svm.cpp:286
static double dot(const svm_node *px, const svm_node *py)
Definition svm.cpp:341
virtual Qfloat * get_Q(int column, int len) const =0
double(Kernel::* kernel_function)(int i, int j) const
Definition svm.cpp:265
double kernel_sigmoid(int i, int j) const
Definition svm.cpp:290
const svm_node ** x
Definition svm.cpp:268
virtual double * get_QD() const =0
Kernel(int l, svm_node *const *x, const svm_parameter &param)
Definition svm.cpp:300
virtual void swap_index(int i, int j) const
Definition svm.cpp:258
const double coef0
Definition svm.cpp:275
double kernel_poly(int i, int j) const
Definition svm.cpp:282
static double k_function(const svm_node *x, const svm_node *y, const svm_parameter &param)
Definition svm.cpp:363
double kernel_linear(int i, int j) const
Definition svm.cpp:278
double * x_square
Definition svm.cpp:269
ONE_CLASS_Q(const svm_problem &prob, const svm_parameter &param)
Definition svm.cpp:1366
double * get_QD() const
Definition svm.cpp:1387
void swap_index(int i, int j) const
Definition svm.cpp:1392
Qfloat * get_Q(int i, int len) const
Definition svm.cpp:1375
virtual double * get_QD() const =0
virtual ~QMatrix()
Definition svm.cpp:246
virtual Qfloat * get_Q(int column, int len) const =0
virtual void swap_index(int i, int j) const =0
void swap_index(int i, int j) const
Definition svm.cpp:1343
Cache * cache
Definition svm.cpp:1359
double * QD
Definition svm.cpp:1360
double * get_QD() const
Definition svm.cpp:1338
SVC_Q(const svm_problem &prob, const svm_parameter &param, const schar *y_)
Definition svm.cpp:1316
schar * y
Definition svm.cpp:1358
Qfloat * get_Q(int i, int len) const
Definition svm.cpp:1326
double * QD
Definition svm.cpp:1481
Qfloat * buffer[2]
Definition svm.cpp:1480
int next_buffer
Definition svm.cpp:1479
SVR_Q(const svm_problem &prob, const svm_parameter &param)
Definition svm.cpp:1412
Cache * cache
Definition svm.cpp:1476
int * index
Definition svm.cpp:1478
Qfloat * get_Q(int i, int len) const
Definition svm.cpp:1441
schar * sign
Definition svm.cpp:1477
double * get_QD() const
Definition svm.cpp:1460
void swap_index(int i, int j) const
Definition svm.cpp:1434
int select_working_set(int &i, int &j)
Definition svm.cpp:1076
void Solve(int l, const QMatrix &Q, const double *p, const schar *y, double *alpha, double Cp, double Cn, double eps, SolutionInfo *si, int shrinking)
Definition svm.cpp:1060
SolutionInfo * si
Definition svm.cpp:1068
double calculate_rho()
Definition svm.cpp:1260
void do_shrinking()
Definition svm.cpp:1208
bool be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4)
Definition svm.cpp:1188
const double * QD
Definition svm.cpp:464
virtual double calculate_rho()
Definition svm.cpp:1013
double * G_bar
Definition svm.cpp:469
bool is_upper_bound(int i)
Definition svm.cpp:485
double Cn
Definition svm.cpp:466
virtual void do_shrinking()
Definition svm.cpp:952
void reconstruct_gradient()
Definition svm.cpp:509
virtual int select_working_set(int &i, int &j)
Definition svm.cpp:833
double eps
Definition svm.cpp:465
void update_alpha_status(int i)
Definition svm.cpp:477
bool unshrink
Definition svm.cpp:471
char * alpha_status
Definition svm.cpp:461
virtual ~Solver()
Definition svm.cpp:443
bool is_free(int i)
Definition svm.cpp:487
const QMatrix * Q
Definition svm.cpp:463
double Cp
Definition svm.cpp:466
bool is_lower_bound(int i)
Definition svm.cpp:486
void swap_index(int i, int j)
Definition svm.cpp:497
double get_C(int i)
Definition svm.cpp:473
double * alpha
Definition svm.cpp:462
void Solve(int l, const QMatrix &Q, const double *p_, const schar *y_, double *alpha_, double Cp, double Cn, double eps, SolutionInfo *si, int shrinking)
Definition svm.cpp:551
bool be_shrunk(int i, double Gmax1, double Gmax2)
Definition svm.cpp:932
double * p
Definition svm.cpp:467
int * active_set
Definition svm.cpp:468
schar * y
Definition svm.cpp:458
int active_size
Definition svm.cpp:457
double * G
Definition svm.cpp:459
static double sigma
int libsvm_version
Definition svm.cpp:58
signed char schar
Definition svm.cpp:60
svm_model * svm_load_model(const char *model_file_name)
Definition svm.cpp:2933
void svm_destroy_param(svm_parameter *param)
Definition svm.cpp:3083
static void multiclass_probability(int k, double **r, double *p)
Definition svm.cpp:1878
const char * svm_check_parameter(const svm_problem *prob, const svm_parameter *param)
Definition svm.cpp:3089
static void solve_one_class(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition svm.cpp:1577
int svm_get_svm_type(const svm_model *model)
Definition svm.cpp:2509
void svm_get_labels(const svm_model *model, int *label)
Definition svm.cpp:2519
static void svm_group_classes(const svm_problem *prob, int *nr_class_ret, int **label_ret, int **start_ret, int **count_ret, int *perm)
Definition svm.cpp:2063
static double powi(double base, int times)
Definition svm.cpp:73
int svm_save_model(const char *model_file_name, const svm_model *model)
Definition svm.cpp:2690
static const char * kernel_type_table[]
Definition svm.cpp:2685
@ LINEAR
Definition svm.h:58
@ SIGMOID
Definition svm.h:58
@ PRECOMPUTED
Definition svm.h:58
@ RBF
Definition svm.h:58
@ POLY
Definition svm.h:58
static double sigmoid_predict(double decision_value, double A, double B)
Definition svm.cpp:1867
void svm_set_print_string_function(void(*print_func)(const char *))
Definition svm.cpp:3218
static void solve_c_svc(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si, double Cp, double Cn)
Definition svm.cpp:1487
static decision_function svm_train_one(const svm_problem *prob, const svm_parameter *param, double Cp, double Cn)
Definition svm.cpp:1694
static void sigmoid_train(int l, const double *dec_values, const double *labels, double &A, double &B)
Definition svm.cpp:1752
void svm_free_and_destroy_model(svm_model **model_ptr_ptr)
Definition svm.cpp:3073
svm_model * svm_train(const svm_problem *prob, const svm_parameter *param)
Definition svm.cpp:2141
int svm_get_nr_sv(const svm_model *model)
Definition svm.cpp:2533
static int max_line_len
Definition svm.cpp:2785
int svm_check_probability_model(const svm_model *model)
Definition svm.cpp:3210
static double svm_svr_probability(const svm_problem *prob, const svm_parameter *param)
Definition svm.cpp:2029
static T min(T x, T y)
Definition svm.cpp:62
double svm_predict_values(const svm_model *model, const svm_node *x, double *dec_values)
Definition svm.cpp:2550
static char * readline(FILE *input)
Definition svm.cpp:2787
double svm_predict_probability(const svm_model *model, const svm_node *x, double *prob_estimates)
Definition svm.cpp:2641
static char * line
Definition svm.cpp:2784
static void solve_epsilon_svr(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition svm.cpp:1609
void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, int nr_fold, double *target)
Definition svm.cpp:2388
static void(* svm_print_string)(const char *)
Definition svm.cpp:93
static void swap(T &x, T &y)
Definition svm.cpp:67
static const char * svm_type_table[]
Definition svm.cpp:2680
static void solve_nu_svr(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition svm.cpp:1647
double svm_predict(const svm_model *model, const svm_node *x)
Definition svm.cpp:2626
double svm_get_svr_probability(const svm_model *model)
Definition svm.cpp:2538
void svm_get_sv_indices(const svm_model *model, int *indices)
Definition svm.cpp:2526
int svm_get_nr_class(const svm_model *model)
Definition svm.cpp:2514
static void svm_binary_svc_probability(const svm_problem *prob, const svm_parameter *param, double Cp, double Cn, double &probA, double &probB)
Definition svm.cpp:1942
static T max(T x, T y)
Definition svm.cpp:65
static void print_string_stdout(const char *s)
Definition svm.cpp:88
static void clone(T *&dst, S *src, int n)
Definition svm.cpp:68
static void info(const char *fmt,...)
Definition svm.cpp:95
bool read_model_header(FILE *fp, svm_model *model)
Definition svm.cpp:2811
void svm_free_model_content(svm_model *model_ptr)
Definition svm.cpp:3038
static void solve_nu_svc(const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo *si)
Definition svm.cpp:1522
float Qfloat
Definition svm.cpp:59
@ NU_SVR
Definition svm.h:57
@ EPSILON_SVR
Definition svm.h:57
@ C_SVC
Definition svm.h:57
@ ONE_CLASS
Definition svm.h:57
@ NU_SVC
Definition svm.h:57
double value
Definition svm.h:47
double cache_size
Definition svm.h:69
double * weight
Definition svm.h:74
#define INF
Definition svm.cpp:84
#define TAU
Definition svm.cpp:85
#define Malloc(type, n)
Definition svm.cpp:86
#define FSCANF(_stream, _format, _var)
Definition svm.cpp:2810
#define log1p(x)
Definition svm.cpp:48
#define LIBSVM_VERSION
Definition svm.h:37
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41