numo-liblinear 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  #ifndef _LIBLINEAR_H
2
2
  #define _LIBLINEAR_H
3
3
 
4
- #define LIBLINEAR_VERSION 230
4
+ #define LIBLINEAR_VERSION 241
5
5
 
6
6
  #ifdef __cplusplus
7
7
  extern "C" {
@@ -23,7 +23,7 @@ struct problem
23
23
  double bias; /* < 0 if no bias term */
24
24
  };
25
25
 
26
- enum { L2R_LR, L2R_L2LOSS_SVC_DUAL, L2R_L2LOSS_SVC, L2R_L1LOSS_SVC_DUAL, MCSVM_CS, L1R_L2LOSS_SVC, L1R_LR, L2R_LR_DUAL, L2R_L2LOSS_SVR = 11, L2R_L2LOSS_SVR_DUAL, L2R_L1LOSS_SVR_DUAL }; /* solver_type */
26
+ enum { L2R_LR, L2R_L2LOSS_SVC_DUAL, L2R_L2LOSS_SVC, L2R_L1LOSS_SVC_DUAL, MCSVM_CS, L1R_L2LOSS_SVC, L1R_LR, L2R_LR_DUAL, L2R_L2LOSS_SVR = 11, L2R_L2LOSS_SVR_DUAL, L2R_L1LOSS_SVR_DUAL, ONECLASS_SVM = 21 }; /* solver_type */
27
27
 
28
28
  struct parameter
29
29
  {
@@ -36,7 +36,9 @@ struct parameter
36
36
  int *weight_label;
37
37
  double* weight;
38
38
  double p;
39
+ double nu;
39
40
  double *init_sol;
41
+ int regularize_bias;
40
42
  };
41
43
 
42
44
  struct model
@@ -47,6 +49,7 @@ struct model
47
49
  double *w;
48
50
  int *label; /* label of each class */
49
51
  double bias;
52
+ double rho; /* one-class SVM only */
50
53
  };
51
54
 
52
55
  struct model* train(const struct problem *prob, const struct parameter *param);
@@ -65,6 +68,7 @@ int get_nr_class(const struct model *model_);
65
68
  void get_labels(const struct model *model_, int* label);
66
69
  double get_decfun_coef(const struct model *model_, int feat_idx, int label_idx);
67
70
  double get_decfun_bias(const struct model *model_, int label_idx);
71
+ double get_decfun_rho(const struct model *model_);
68
72
 
69
73
  void free_model_content(struct model *model_ptr);
70
74
  void free_and_destroy_model(struct model **model_ptr_ptr);
@@ -73,6 +77,7 @@ void destroy_param(struct parameter *param);
73
77
  const char *check_parameter(const struct problem *prob, const struct parameter *param);
74
78
  int check_probability_model(const struct model *model);
75
79
  int check_regression_model(const struct model *model);
80
+ int check_oneclass_model(const struct model *model);
76
81
  void set_print_string_function(void (*print_func) (const char*));
77
82
 
78
83
  #ifdef __cplusplus
@@ -0,0 +1,245 @@
1
+ #include <math.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+ #include <stdarg.h>
5
+ #include "newton.h"
6
+
7
+ #ifndef min
8
+ template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }
9
+ #endif
10
+
11
+ #ifndef max
12
+ template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }
13
+ #endif
14
+
15
+ #ifdef __cplusplus
16
+ extern "C" {
17
+ #endif
18
+
19
+ extern double dnrm2_(int *, double *, int *);
20
+ extern double ddot_(int *, double *, int *, double *, int *);
21
+ extern int daxpy_(int *, double *, double *, int *, double *, int *);
22
+ extern int dscal_(int *, double *, double *, int *);
23
+
24
+ #ifdef __cplusplus
25
+ }
26
+ #endif
27
+
28
+ static void default_print(const char *buf)
29
+ {
30
+ fputs(buf,stdout);
31
+ fflush(stdout);
32
+ }
33
+
34
+ // On entry *f must be the function value of w
35
+ // On exit w is updated and *f is the new function value
36
+ double function::linesearch_and_update(double *w, double *s, double *f, double *g, double alpha)
37
+ {
38
+ double gTs = 0;
39
+ double eta = 0.01;
40
+ int n = get_nr_variable();
41
+ int max_num_linesearch = 20;
42
+ double *w_new = new double[n];
43
+ double fold = *f;
44
+
45
+ for (int i=0;i<n;i++)
46
+ gTs += s[i] * g[i];
47
+
48
+ int num_linesearch = 0;
49
+ for(num_linesearch=0; num_linesearch < max_num_linesearch; num_linesearch++)
50
+ {
51
+ for (int i=0;i<n;i++)
52
+ w_new[i] = w[i] + alpha*s[i];
53
+ *f = fun(w_new);
54
+ if (*f - fold <= eta * alpha * gTs)
55
+ break;
56
+ else
57
+ alpha *= 0.5;
58
+ }
59
+
60
+ if (num_linesearch >= max_num_linesearch)
61
+ {
62
+ *f = fold;
63
+ return 0;
64
+ }
65
+ else
66
+ memcpy(w, w_new, sizeof(double)*n);
67
+
68
+ delete [] w_new;
69
+ return alpha;
70
+ }
71
+
72
+ void NEWTON::info(const char *fmt,...)
73
+ {
74
+ char buf[BUFSIZ];
75
+ va_list ap;
76
+ va_start(ap,fmt);
77
+ vsprintf(buf,fmt,ap);
78
+ va_end(ap);
79
+ (*newton_print_string)(buf);
80
+ }
81
+
82
+ NEWTON::NEWTON(const function *fun_obj, double eps, double eps_cg, int max_iter)
83
+ {
84
+ this->fun_obj=const_cast<function *>(fun_obj);
85
+ this->eps=eps;
86
+ this->eps_cg=eps_cg;
87
+ this->max_iter=max_iter;
88
+ newton_print_string = default_print;
89
+ }
90
+
91
+ NEWTON::~NEWTON()
92
+ {
93
+ }
94
+
95
+ void NEWTON::newton(double *w)
96
+ {
97
+ int n = fun_obj->get_nr_variable();
98
+ int i, cg_iter;
99
+ double step_size;
100
+ double f, fold, actred;
101
+ double init_step_size = 1;
102
+ int search = 1, iter = 1, inc = 1;
103
+ double *s = new double[n];
104
+ double *r = new double[n];
105
+ double *g = new double[n];
106
+
107
+ const double alpha_pcg = 0.01;
108
+ double *M = new double[n];
109
+
110
+ // calculate gradient norm at w=0 for stopping condition.
111
+ double *w0 = new double[n];
112
+ for (i=0; i<n; i++)
113
+ w0[i] = 0;
114
+ fun_obj->fun(w0);
115
+ fun_obj->grad(w0, g);
116
+ double gnorm0 = dnrm2_(&n, g, &inc);
117
+ delete [] w0;
118
+
119
+ f = fun_obj->fun(w);
120
+ info("init f %5.3e\n", f);
121
+ fun_obj->grad(w, g);
122
+ double gnorm = dnrm2_(&n, g, &inc);
123
+
124
+ if (gnorm <= eps*gnorm0)
125
+ search = 0;
126
+
127
+ double *w_new = new double[n];
128
+ while (iter <= max_iter && search)
129
+ {
130
+ fun_obj->get_diag_preconditioner(M);
131
+ for(i=0; i<n; i++)
132
+ M[i] = (1-alpha_pcg) + alpha_pcg*M[i];
133
+ cg_iter = pcg(g, M, s, r);
134
+
135
+ fold = f;
136
+ step_size = fun_obj->linesearch_and_update(w, s, & f, g, init_step_size);
137
+
138
+ if (step_size == 0)
139
+ {
140
+ info("WARNING: line search fails\n");
141
+ break;
142
+ }
143
+
144
+ info("iter %2d f %5.3e |g| %5.3e CG %3d step_size %4.2e \n", iter, f, gnorm, cg_iter, step_size);
145
+
146
+ actred = fold - f;
147
+ iter++;
148
+
149
+ fun_obj->grad(w, g);
150
+
151
+ gnorm = dnrm2_(&n, g, &inc);
152
+ if (gnorm <= eps*gnorm0)
153
+ break;
154
+ if (f < -1.0e+32)
155
+ {
156
+ info("WARNING: f < -1.0e+32\n");
157
+ break;
158
+ }
159
+ if (fabs(actred) <= 1.0e-12*fabs(f))
160
+ {
161
+ info("WARNING: actred too small\n");
162
+ break;
163
+ }
164
+ }
165
+
166
+ delete[] g;
167
+ delete[] r;
168
+ delete[] w_new;
169
+ delete[] s;
170
+ delete[] M;
171
+ }
172
+
173
+ int NEWTON::pcg(double *g, double *M, double *s, double *r)
174
+ {
175
+ int i, inc = 1;
176
+ int n = fun_obj->get_nr_variable();
177
+ double one = 1;
178
+ double *d = new double[n];
179
+ double *Hd = new double[n];
180
+ double zTr, znewTrnew, alpha, beta, cgtol;
181
+ double *z = new double[n];
182
+ double Q = 0, newQ, Qdiff;
183
+
184
+ for (i=0; i<n; i++)
185
+ {
186
+ s[i] = 0;
187
+ r[i] = -g[i];
188
+ z[i] = r[i] / M[i];
189
+ d[i] = z[i];
190
+ }
191
+
192
+ zTr = ddot_(&n, z, &inc, r, &inc);
193
+ double gMinv_norm = sqrt(zTr);
194
+ cgtol = min(eps_cg, sqrt(gMinv_norm));
195
+ int cg_iter = 0;
196
+ int max_cg_iter = max(n, 5);
197
+
198
+ while (cg_iter < max_cg_iter)
199
+ {
200
+ cg_iter++;
201
+ fun_obj->Hv(d, Hd);
202
+
203
+ alpha = zTr/ddot_(&n, d, &inc, Hd, &inc);
204
+ daxpy_(&n, &alpha, d, &inc, s, &inc);
205
+ alpha = -alpha;
206
+ daxpy_(&n, &alpha, Hd, &inc, r, &inc);
207
+
208
+ // Using quadratic approximation as CG stopping criterion
209
+ newQ = -0.5*(ddot_(&n, s, &inc, r, &inc) - ddot_(&n, s, &inc, g, &inc));
210
+ Qdiff = newQ - Q;
211
+ if (newQ <= 0 && Qdiff <= 0)
212
+ {
213
+ if (cg_iter * Qdiff >= cgtol * newQ)
214
+ break;
215
+ }
216
+ else
217
+ {
218
+ info("WARNING: quadratic approximation > 0 or increasing in CG\n");
219
+ break;
220
+ }
221
+ Q = newQ;
222
+
223
+ for (i=0; i<n; i++)
224
+ z[i] = r[i] / M[i];
225
+ znewTrnew = ddot_(&n, z, &inc, r, &inc);
226
+ beta = znewTrnew/zTr;
227
+ dscal_(&n, &beta, d, &inc);
228
+ daxpy_(&n, &one, z, &inc, d, &inc);
229
+ zTr = znewTrnew;
230
+ }
231
+
232
+ if (cg_iter == max_cg_iter)
233
+ info("WARNING: reaching maximal number of CG steps\n");
234
+
235
+ delete[] d;
236
+ delete[] Hd;
237
+ delete[] z;
238
+
239
+ return(cg_iter);
240
+ }
241
+
242
+ void NEWTON::set_print_string(void (*print_string) (const char *buf))
243
+ {
244
+ newton_print_string = print_string;
245
+ }
@@ -1,5 +1,5 @@
1
- #ifndef _TRON_H
2
- #define _TRON_H
1
+ #ifndef _NEWTON_H
2
+ #define _NEWTON_H
3
3
 
4
4
  class function
5
5
  {
@@ -7,30 +7,31 @@ public:
7
7
  virtual double fun(double *w) = 0 ;
8
8
  virtual void grad(double *w, double *g) = 0 ;
9
9
  virtual void Hv(double *s, double *Hs) = 0 ;
10
-
11
10
  virtual int get_nr_variable(void) = 0 ;
12
11
  virtual void get_diag_preconditioner(double *M) = 0 ;
13
12
  virtual ~function(void){}
13
+
14
+ // base implementation in newton.cpp
15
+ virtual double linesearch_and_update(double *w, double *s, double *f, double *g, double alpha);
14
16
  };
15
17
 
16
- class TRON
18
+ class NEWTON
17
19
  {
18
20
  public:
19
- TRON(const function *fun_obj, double eps = 0.1, double eps_cg = 0.1, int max_iter = 1000);
20
- ~TRON();
21
+ NEWTON(const function *fun_obj, double eps = 0.1, double eps_cg = 0.5, int max_iter = 1000);
22
+ ~NEWTON();
21
23
 
22
- void tron(double *w);
24
+ void newton(double *w);
23
25
  void set_print_string(void (*i_print) (const char *buf));
24
26
 
25
27
  private:
26
- int trpcg(double delta, double *g, double *M, double *s, double *r, bool *reach_boundary);
27
- double norm_inf(int n, double *x);
28
+ int pcg(double *g, double *M, double *s, double *r);
28
29
 
29
30
  double eps;
30
31
  double eps_cg;
31
32
  int max_iter;
32
33
  function *fun_obj;
33
34
  void info(const char *fmt,...);
34
- void (*tron_print_string)(const char *buf);
35
+ void (*newton_print_string)(const char *buf);
35
36
  };
36
37
  #endif
@@ -14,6 +14,8 @@ struct model* rb_hash_to_model(VALUE model_hash)
14
14
  model->label = nary_to_int_vec(el);
15
15
  el = rb_hash_aref(model_hash, ID2SYM(rb_intern("bias")));
16
16
  model->bias = NUM2DBL(el);
17
+ el = rb_hash_aref(model_hash, ID2SYM(rb_intern("rho")));
18
+ model->rho = NUM2DBL(el);
17
19
  return model;
18
20
  }
19
21
 
@@ -29,6 +31,7 @@ VALUE model_to_rb_hash(struct model* const model)
29
31
  rb_hash_aset(model_hash, ID2SYM(rb_intern("label")),
30
32
  model->label ? int_vec_to_nary(model->label, model->nr_class) : Qnil);
31
33
  rb_hash_aset(model_hash, ID2SYM(rb_intern("bias")), DBL2NUM(model->bias));
34
+ rb_hash_aset(model_hash, ID2SYM(rb_intern("rho")), DBL2NUM(model->rho));
32
35
  return model_hash;
33
36
  }
34
37
 
@@ -5,36 +5,39 @@ struct parameter* rb_hash_to_parameter(VALUE param_hash)
5
5
  VALUE el;
6
6
  struct parameter* param = ALLOC(struct parameter);
7
7
  el = rb_hash_aref(param_hash, ID2SYM(rb_intern("solver_type")));
8
- param->solver_type = !NIL_P(el) ? NUM2INT(el) : L2R_L2LOSS_SVC_DUAL;
8
+ param->solver_type = !NIL_P(el) ? NUM2INT(el) : L2R_L2LOSS_SVC_DUAL;
9
9
  el = rb_hash_aref(param_hash, ID2SYM(rb_intern("eps")));
10
- if (!NIL_P(el)) {
10
+ if (!NIL_P(el)) {
11
11
  param->eps = NUM2DBL(el);
12
- } else {
13
- switch(param->solver_type)
14
- {
15
- case L2R_LR:
16
- case L2R_L2LOSS_SVC:
17
- param->eps = 0.01;
18
- break;
19
- case L2R_L2LOSS_SVR:
20
- param->eps = 0.0001;
21
- break;
22
- case L2R_L2LOSS_SVC_DUAL:
23
- case L2R_L1LOSS_SVC_DUAL:
24
- case MCSVM_CS:
25
- case L2R_LR_DUAL:
26
- param->eps = 0.1;
27
- break;
28
- case L1R_L2LOSS_SVC:
29
- case L1R_LR:
30
- param->eps = 0.01;
31
- break;
32
- case L2R_L1LOSS_SVR_DUAL:
33
- case L2R_L2LOSS_SVR_DUAL:
34
- param->eps = 0.1;
35
- break;
12
+ } else {
13
+ switch(param->solver_type)
14
+ {
15
+ case L2R_LR:
16
+ case L2R_L2LOSS_SVC:
17
+ param->eps = 0.01;
18
+ break;
19
+ case L2R_L2LOSS_SVR:
20
+ param->eps = 0.0001;
21
+ break;
22
+ case L2R_L2LOSS_SVC_DUAL:
23
+ case L2R_L1LOSS_SVC_DUAL:
24
+ case MCSVM_CS:
25
+ case L2R_LR_DUAL:
26
+ param->eps = 0.1;
27
+ break;
28
+ case L1R_L2LOSS_SVC:
29
+ case L1R_LR:
30
+ param->eps = 0.01;
31
+ break;
32
+ case L2R_L1LOSS_SVR_DUAL:
33
+ case L2R_L2LOSS_SVR_DUAL:
34
+ param->eps = 0.1;
35
+ break;
36
+ case ONECLASS_SVM:
37
+ param->eps = 0.01;
38
+ break;
36
39
  }
37
- }
40
+ }
38
41
  el = rb_hash_aref(param_hash, ID2SYM(rb_intern("C")));
39
42
  param->C = !NIL_P(el) ? NUM2DBL(el) : 1;
40
43
  el = rb_hash_aref(param_hash, ID2SYM(rb_intern("nr_weight")));
@@ -53,11 +56,14 @@ struct parameter* rb_hash_to_parameter(VALUE param_hash)
53
56
  }
54
57
  el = rb_hash_aref(param_hash, ID2SYM(rb_intern("p")));
55
58
  param->p = !NIL_P(el) ? NUM2DBL(el) : 0.1;
59
+ el = rb_hash_aref(param_hash, ID2SYM(rb_intern("nu")));
60
+ param->nu = !NIL_P(el) ? NUM2DBL(el) : 0.5;
56
61
  el = rb_hash_aref(param_hash, ID2SYM(rb_intern("init_sol")));
57
62
  param->init_sol = NULL;
58
63
  if (!NIL_P(el)) {
59
64
  param->init_sol = nary_to_dbl_vec(el);
60
65
  }
66
+ param->regularize_bias = 1;
61
67
  return param;
62
68
  }
63
69
 
@@ -73,6 +79,7 @@ VALUE parameter_to_rb_hash(struct parameter* const param)
73
79
  rb_hash_aset(param_hash, ID2SYM(rb_intern("weight")),
74
80
  param->weight ? dbl_vec_to_nary(param->weight, param->nr_weight) : Qnil);
75
81
  rb_hash_aset(param_hash, ID2SYM(rb_intern("p")), DBL2NUM(param->p));
82
+ rb_hash_aset(param_hash, ID2SYM(rb_intern("nu")), DBL2NUM(param->nu));
76
83
  rb_hash_aset(param_hash, ID2SYM(rb_intern("init_sol")), Qnil);
77
84
  return param_hash;
78
85
  }
@@ -17,18 +17,20 @@ void rb_init_solver_type_module()
17
17
  rb_define_const(mSolverType, "L2R_L2LOSS_SVC", INT2NUM(L2R_L2LOSS_SVC));
18
18
  /* L2-regularized L1-loss support vector classification (dual) */
19
19
  rb_define_const(mSolverType, "L2R_L1LOSS_SVC_DUAL", INT2NUM(L2R_L1LOSS_SVC_DUAL));
20
- /* support vector classification by Crammer and Singer */
20
+ /* support vector classification by Crammer and Singer */
21
21
  rb_define_const(mSolverType, "MCSVM_CS", INT2NUM(MCSVM_CS));
22
- /* L1-regularized L2-loss support vector classification */
22
+ /* L1-regularized L2-loss support vector classification */
23
23
  rb_define_const(mSolverType, "L1R_L2LOSS_SVC", INT2NUM(L1R_L2LOSS_SVC));
24
- /* L1-regularized logistic regression */
24
+ /* L1-regularized logistic regression */
25
25
  rb_define_const(mSolverType, "L1R_LR", INT2NUM(L1R_LR));
26
26
  /* L2-regularized logistic regression (dual) */
27
27
  rb_define_const(mSolverType, "L2R_LR_DUAL", INT2NUM(L2R_LR_DUAL));
28
- /* L2-regularized L2-loss support vector regression (primal) */
28
+ /* L2-regularized L2-loss support vector regression (primal) */
29
29
  rb_define_const(mSolverType, "L2R_L2LOSS_SVR", INT2NUM(L2R_L2LOSS_SVR));
30
- /* L2-regularized L2-loss support vector regression (dual) */
30
+ /* L2-regularized L2-loss support vector regression (dual) */
31
31
  rb_define_const(mSolverType, "L2R_L2LOSS_SVR_DUAL", INT2NUM(L2R_L2LOSS_SVR_DUAL));
32
- /* L2-regularized L1-loss support vector regression (dual) */
32
+ /* L2-regularized L1-loss support vector regression (dual) */
33
33
  rb_define_const(mSolverType, "L2R_L1LOSS_SVR_DUAL", INT2NUM(L2R_L1LOSS_SVR_DUAL));
34
+ /* one-class support vector machine (dual) */
35
+ rb_define_const(mSolverType, "ONECLASS_SVM", INT2NUM(ONECLASS_SVM));
34
36
  }