liblinear-ruby 1.0.2 → 1.0.3

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 211
4
+ #define LIBLINEAR_VERSION 230
5
5
 
6
6
  #ifdef __cplusplus
7
7
  extern "C" {
@@ -51,7 +51,7 @@ struct model
51
51
 
52
52
  struct model* train(const struct problem *prob, const struct parameter *param);
53
53
  void cross_validation(const struct problem *prob, const struct parameter *param, int nr_fold, double *target);
54
- void find_parameter_C(const struct problem *prob, const struct parameter *param, int nr_fold, double start_C, double max_C, double *best_C, double *best_rate);
54
+ void find_parameters(const struct problem *prob, const struct parameter *param, int nr_fold, double start_C, double start_p, double *best_C, double *best_p, double *best_score);
55
55
 
56
56
  double predict_values(const struct model *model_, const struct feature_node *x, double* dec_values);
57
57
  double predict(const struct model *model_, const struct feature_node *x);
@@ -31,6 +31,19 @@ static void default_print(const char *buf)
31
31
  fflush(stdout);
32
32
  }
33
33
 
34
+ static double uTMv(int n, double *u, double *M, double *v)
35
+ {
36
+ const int m = n-4;
37
+ double res = 0;
38
+ int i;
39
+ for (i=0; i<m; i+=5)
40
+ res += u[i]*M[i]*v[i]+u[i+1]*M[i+1]*v[i+1]+u[i+2]*M[i+2]*v[i+2]+
41
+ u[i+3]*M[i+3]*v[i+3]+u[i+4]*M[i+4]*v[i+4];
42
+ for (; i<n; i++)
43
+ res += u[i]*M[i]*v[i];
44
+ return res;
45
+ }
46
+
34
47
  void TRON::info(const char *fmt,...)
35
48
  {
36
49
  char buf[BUFSIZ];
@@ -64,13 +77,16 @@ void TRON::tron(double *w)
64
77
 
65
78
  int n = fun_obj->get_nr_variable();
66
79
  int i, cg_iter;
67
- double delta, snorm, one=1.0;
80
+ double delta=0, sMnorm, one=1.0;
68
81
  double alpha, f, fnew, prered, actred, gs;
69
82
  int search = 1, iter = 1, inc = 1;
70
83
  double *s = new double[n];
71
84
  double *r = new double[n];
72
85
  double *g = new double[n];
73
86
 
87
+ const double alpha_pcg = 0.01;
88
+ double *M = new double[n];
89
+
74
90
  // calculate gradient norm at w=0 for stopping condition.
75
91
  double *w0 = new double[n];
76
92
  for (i=0; i<n; i++)
@@ -82,19 +98,22 @@ void TRON::tron(double *w)
82
98
 
83
99
  f = fun_obj->fun(w);
84
100
  fun_obj->grad(w, g);
85
- delta = dnrm2_(&n, g, &inc);
86
- double gnorm = delta;
101
+ double gnorm = dnrm2_(&n, g, &inc);
87
102
 
88
103
  if (gnorm <= eps*gnorm0)
89
104
  search = 0;
90
105
 
91
- iter = 1;
106
+ fun_obj->get_diag_preconditioner(M);
107
+ for(i=0; i<n; i++)
108
+ M[i] = (1-alpha_pcg) + alpha_pcg*M[i];
109
+ delta = sqrt(uTMv(n, g, M, g));
92
110
 
93
111
  double *w_new = new double[n];
94
112
  bool reach_boundary;
113
+ bool delta_adjusted = false;
95
114
  while (iter <= max_iter && search)
96
115
  {
97
- cg_iter = trcg(delta, g, s, r, &reach_boundary);
116
+ cg_iter = trpcg(delta, g, M, s, r, &reach_boundary);
98
117
 
99
118
  memcpy(w_new, w, sizeof(double)*n);
100
119
  daxpy_(&n, &one, s, &inc, w_new, &inc);
@@ -107,11 +126,14 @@ void TRON::tron(double *w)
107
126
  actred = f - fnew;
108
127
 
109
128
  // On the first iteration, adjust the initial step bound.
110
- snorm = dnrm2_(&n, s, &inc);
111
- if (iter == 1)
112
- delta = min(delta, snorm);
129
+ sMnorm = sqrt(uTMv(n, s, M, s));
130
+ if (iter == 1 && !delta_adjusted)
131
+ {
132
+ delta = min(delta, sMnorm);
133
+ delta_adjusted = true;
134
+ }
113
135
 
114
- // Compute prediction alpha*snorm of the step.
136
+ // Compute prediction alpha*sMnorm of the step.
115
137
  if (fnew - f - gs <= 0)
116
138
  alpha = sigma3;
117
139
  else
@@ -119,17 +141,17 @@ void TRON::tron(double *w)
119
141
 
120
142
  // Update the trust region bound according to the ratio of actual to predicted reduction.
121
143
  if (actred < eta0*prered)
122
- delta = min(max(alpha, sigma1)*snorm, sigma2*delta);
144
+ delta = min(alpha*sMnorm, sigma2*delta);
123
145
  else if (actred < eta1*prered)
124
- delta = max(sigma1*delta, min(alpha*snorm, sigma2*delta));
146
+ delta = max(sigma1*delta, min(alpha*sMnorm, sigma2*delta));
125
147
  else if (actred < eta2*prered)
126
- delta = max(sigma1*delta, min(alpha*snorm, sigma3*delta));
148
+ delta = max(sigma1*delta, min(alpha*sMnorm, sigma3*delta));
127
149
  else
128
150
  {
129
151
  if (reach_boundary)
130
152
  delta = sigma3*delta;
131
153
  else
132
- delta = max(delta, min(alpha*snorm, sigma3*delta));
154
+ delta = max(delta, min(alpha*sMnorm, sigma3*delta));
133
155
  }
134
156
 
135
157
  info("iter %2d act %5.3e pre %5.3e delta %5.3e f %5.3e |g| %5.3e CG %3d\n", iter, actred, prered, delta, f, gnorm, cg_iter);
@@ -140,6 +162,9 @@ void TRON::tron(double *w)
140
162
  memcpy(w, w_new, sizeof(double)*n);
141
163
  f = fnew;
142
164
  fun_obj->grad(w, g);
165
+ fun_obj->get_diag_preconditioner(M);
166
+ for(i=0; i<n; i++)
167
+ M[i] = (1-alpha_pcg) + alpha_pcg*M[i];
143
168
 
144
169
  gnorm = dnrm2_(&n, g, &inc);
145
170
  if (gnorm <= eps*gnorm0)
@@ -167,53 +192,60 @@ void TRON::tron(double *w)
167
192
  delete[] r;
168
193
  delete[] w_new;
169
194
  delete[] s;
195
+ delete[] M;
170
196
  }
171
197
 
172
- int TRON::trcg(double delta, double *g, double *s, double *r, bool *reach_boundary)
198
+ int TRON::trpcg(double delta, double *g, double *M, double *s, double *r, bool *reach_boundary)
173
199
  {
174
200
  int i, inc = 1;
175
201
  int n = fun_obj->get_nr_variable();
176
202
  double one = 1;
177
203
  double *d = new double[n];
178
204
  double *Hd = new double[n];
179
- double rTr, rnewTrnew, alpha, beta, cgtol;
205
+ double zTr, znewTrnew, alpha, beta, cgtol;
206
+ double *z = new double[n];
180
207
 
181
208
  *reach_boundary = false;
182
209
  for (i=0; i<n; i++)
183
210
  {
184
211
  s[i] = 0;
185
212
  r[i] = -g[i];
186
- d[i] = r[i];
213
+ z[i] = r[i] / M[i];
214
+ d[i] = z[i];
187
215
  }
188
- cgtol = eps_cg*dnrm2_(&n, g, &inc);
189
216
 
217
+ zTr = ddot_(&n, z, &inc, r, &inc);
218
+ cgtol = eps_cg*sqrt(zTr);
190
219
  int cg_iter = 0;
191
- rTr = ddot_(&n, r, &inc, r, &inc);
192
- while (1)
220
+ int max_cg_iter = max(n, 5);
221
+
222
+ while (cg_iter < max_cg_iter)
193
223
  {
194
- if (dnrm2_(&n, r, &inc) <= cgtol)
224
+ if (sqrt(zTr) <= cgtol)
195
225
  break;
196
226
  cg_iter++;
197
227
  fun_obj->Hv(d, Hd);
198
228
 
199
- alpha = rTr/ddot_(&n, d, &inc, Hd, &inc);
229
+ alpha = zTr/ddot_(&n, d, &inc, Hd, &inc);
200
230
  daxpy_(&n, &alpha, d, &inc, s, &inc);
201
- if (dnrm2_(&n, s, &inc) > delta)
231
+
232
+ double sMnorm = sqrt(uTMv(n, s, M, s));
233
+ if (sMnorm > delta)
202
234
  {
203
235
  info("cg reaches trust region boundary\n");
204
236
  *reach_boundary = true;
205
237
  alpha = -alpha;
206
238
  daxpy_(&n, &alpha, d, &inc, s, &inc);
207
239
 
208
- double std = ddot_(&n, s, &inc, d, &inc);
209
- double sts = ddot_(&n, s, &inc, s, &inc);
210
- double dtd = ddot_(&n, d, &inc, d, &inc);
240
+ double sTMd = uTMv(n, s, M, d);
241
+ double sTMs = uTMv(n, s, M, s);
242
+ double dTMd = uTMv(n, d, M, d);
211
243
  double dsq = delta*delta;
212
- double rad = sqrt(std*std + dtd*(dsq-sts));
213
- if (std >= 0)
214
- alpha = (dsq - sts)/(std + rad);
244
+ double rad = sqrt(sTMd*sTMd + dTMd*(dsq-sTMs));
245
+ if (sTMd >= 0)
246
+ alpha = (dsq - sTMs)/(sTMd + rad);
215
247
  else
216
- alpha = (rad - std)/dtd;
248
+ alpha = (rad - sTMd)/dTMd;
217
249
  daxpy_(&n, &alpha, d, &inc, s, &inc);
218
250
  alpha = -alpha;
219
251
  daxpy_(&n, &alpha, Hd, &inc, r, &inc);
@@ -221,15 +253,22 @@ int TRON::trcg(double delta, double *g, double *s, double *r, bool *reach_bounda
221
253
  }
222
254
  alpha = -alpha;
223
255
  daxpy_(&n, &alpha, Hd, &inc, r, &inc);
224
- rnewTrnew = ddot_(&n, r, &inc, r, &inc);
225
- beta = rnewTrnew/rTr;
256
+
257
+ for (i=0; i<n; i++)
258
+ z[i] = r[i] / M[i];
259
+ znewTrnew = ddot_(&n, z, &inc, r, &inc);
260
+ beta = znewTrnew/zTr;
226
261
  dscal_(&n, &beta, d, &inc);
227
- daxpy_(&n, &one, r, &inc, d, &inc);
228
- rTr = rnewTrnew;
262
+ daxpy_(&n, &one, z, &inc, d, &inc);
263
+ zTr = znewTrnew;
229
264
  }
230
265
 
266
+ if (cg_iter == max_cg_iter)
267
+ info("WARNING: reaching maximal number of CG steps\n");
268
+
231
269
  delete[] d;
232
270
  delete[] Hd;
271
+ delete[] z;
233
272
 
234
273
  return(cg_iter);
235
274
  }
data/ext/tron.h CHANGED
@@ -9,6 +9,7 @@ public:
9
9
  virtual void Hv(double *s, double *Hs) = 0 ;
10
10
 
11
11
  virtual int get_nr_variable(void) = 0 ;
12
+ virtual void get_diag_preconditioner(double *M) = 0 ;
12
13
  virtual ~function(void){}
13
14
  };
14
15
 
@@ -22,7 +23,7 @@ public:
22
23
  void set_print_string(void (*i_print) (const char *buf));
23
24
 
24
25
  private:
25
- int trcg(double delta, double *g, double *s, double *r, bool *reach_boundary);
26
+ int trpcg(double delta, double *g, double *M, double *s, double *r, bool *reach_boundary);
26
27
  double norm_inf(int n, double *x);
27
28
 
28
29
  double eps;
@@ -21,7 +21,7 @@ class Liblinear
21
21
  when Liblinear::L2R_LR_DUAL then
22
22
  0.1
23
23
  when Liblinear::L2R_L2LOSS_SVR then
24
- 0.001
24
+ 0.0001
25
25
  when Liblinear::L2R_L2LOSS_SVR_DUAL then
26
26
  0.1
27
27
  when Liblinear::L2R_L1LOSS_SVR_DUAL then
@@ -1,3 +1,3 @@
1
1
  class Liblinear
2
- VERSION = '1.0.2'
2
+ VERSION = '1.0.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: liblinear-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kei Tsuchiya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-22 00:00:00.000000000 Z
11
+ date: 2019-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -104,8 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.5.1
107
+ rubygems_version: 3.0.1
109
108
  signing_key:
110
109
  specification_version: 4
111
110
  summary: Ruby wrapper of LIBLINEAR using SWIG