liblinear-ruby 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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