numo-liblinear 1.0.0 → 1.1.0

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.
@@ -3,6 +3,6 @@
3
3
  module Numo
4
4
  module Liblinear
5
5
  # The version of Numo::Liblienar you are using.
6
- VERSION = '1.0.0'
6
+ VERSION = '1.1.0'
7
7
  end
8
8
  end
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
  gem_dir = File.expand_path(__dir__) + '/'
32
32
  submodule_path = `git submodule --quiet foreach pwd`.split($OUTPUT_RECORD_SEPARATOR).first
33
33
  submodule_relative_path = submodule_path.sub gem_dir, ''
34
- liblinear_files = %w[linear.cpp linear.h tron.cpp tron.h blas/blas.h blas/blasp.h blas/daxpy.c blas/ddot.c blas/dnrm2.c blas/dscal.c]
34
+ liblinear_files = %w[linear.cpp linear.h newton.cpp newton.h blas/blas.h blas/blasp.h blas/daxpy.c blas/ddot.c blas/dnrm2.c blas/dscal.c]
35
35
  liblinear_files.each { |liblinf| spec.files << "#{submodule_relative_path}/#{liblinf}" }
36
36
 
37
37
  spec.bindir = 'exe'
@@ -48,7 +48,7 @@ Gem::Specification.new do |spec|
48
48
  spec.add_runtime_dependency 'numo-narray', '~> 0.9.1'
49
49
 
50
50
  spec.add_development_dependency 'bundler', '~> 2.0'
51
- spec.add_development_dependency 'rake', '~> 10.0'
51
+ spec.add_development_dependency 'rake', '~> 12.0'
52
52
  spec.add_development_dependency 'rake-compiler', '~> 1.0'
53
53
  spec.add_development_dependency 'rspec', '~> 3.0'
54
54
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-liblinear
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-12 00:00:00.000000000 Z
11
+ date: 2020-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '12.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '12.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake-compiler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -112,8 +112,8 @@ files:
112
112
  - ext/numo/liblinear/liblinear/blas/dscal.c
113
113
  - ext/numo/liblinear/liblinear/linear.cpp
114
114
  - ext/numo/liblinear/liblinear/linear.h
115
- - ext/numo/liblinear/liblinear/tron.cpp
116
- - ext/numo/liblinear/liblinear/tron.h
115
+ - ext/numo/liblinear/liblinear/newton.cpp
116
+ - ext/numo/liblinear/liblinear/newton.h
117
117
  - ext/numo/liblinear/liblinearext.c
118
118
  - ext/numo/liblinear/liblinearext.h
119
119
  - ext/numo/liblinear/model.c
@@ -134,7 +134,7 @@ metadata:
134
134
  homepage_uri: https://github.com/yoshoku/numo-liblinear
135
135
  source_code_uri: https://github.com/yoshoku/numo-liblinear
136
136
  documentation_uri: https://yoshoku.github.io/numo-liblinear/doc/
137
- post_install_message:
137
+ post_install_message:
138
138
  rdoc_options: []
139
139
  require_paths:
140
140
  - lib
@@ -149,9 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  - !ruby/object:Gem::Version
150
150
  version: '0'
151
151
  requirements: []
152
- rubyforge_project:
153
- rubygems_version: 2.6.14.4
154
- signing_key:
152
+ rubygems_version: 3.1.2
153
+ signing_key:
155
154
  specification_version: 4
156
155
  summary: Numo::Liblinear is a Ruby gem binding to the LIBLINEAR library. Numo::Liblinear
157
156
  makes to use the LIBLINEAR functions with dataset represented by Numo::NArray.
@@ -1,288 +0,0 @@
1
- #include <math.h>
2
- #include <stdio.h>
3
- #include <string.h>
4
- #include <stdarg.h>
5
- #include "tron.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
- 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
-
47
- void TRON::info(const char *fmt,...)
48
- {
49
- char buf[BUFSIZ];
50
- va_list ap;
51
- va_start(ap,fmt);
52
- vsprintf(buf,fmt,ap);
53
- va_end(ap);
54
- (*tron_print_string)(buf);
55
- }
56
-
57
- TRON::TRON(const function *fun_obj, double eps, double eps_cg, int max_iter)
58
- {
59
- this->fun_obj=const_cast<function *>(fun_obj);
60
- this->eps=eps;
61
- this->eps_cg=eps_cg;
62
- this->max_iter=max_iter;
63
- tron_print_string = default_print;
64
- }
65
-
66
- TRON::~TRON()
67
- {
68
- }
69
-
70
- void TRON::tron(double *w)
71
- {
72
- // Parameters for updating the iterates.
73
- double eta0 = 1e-4, eta1 = 0.25, eta2 = 0.75;
74
-
75
- // Parameters for updating the trust region size delta.
76
- double sigma1 = 0.25, sigma2 = 0.5, sigma3 = 4;
77
-
78
- int n = fun_obj->get_nr_variable();
79
- int i, cg_iter;
80
- double delta=0, sMnorm, one=1.0;
81
- double alpha, f, fnew, prered, actred, gs;
82
- int search = 1, iter = 1, inc = 1;
83
- double *s = new double[n];
84
- double *r = new double[n];
85
- double *g = new double[n];
86
-
87
- const double alpha_pcg = 0.01;
88
- double *M = new double[n];
89
-
90
- // calculate gradient norm at w=0 for stopping condition.
91
- double *w0 = new double[n];
92
- for (i=0; i<n; i++)
93
- w0[i] = 0;
94
- fun_obj->fun(w0);
95
- fun_obj->grad(w0, g);
96
- double gnorm0 = dnrm2_(&n, g, &inc);
97
- delete [] w0;
98
-
99
- f = fun_obj->fun(w);
100
- fun_obj->grad(w, g);
101
- double gnorm = dnrm2_(&n, g, &inc);
102
-
103
- if (gnorm <= eps*gnorm0)
104
- search = 0;
105
-
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));
110
-
111
- double *w_new = new double[n];
112
- bool reach_boundary;
113
- bool delta_adjusted = false;
114
- while (iter <= max_iter && search)
115
- {
116
- cg_iter = trpcg(delta, g, M, s, r, &reach_boundary);
117
-
118
- memcpy(w_new, w, sizeof(double)*n);
119
- daxpy_(&n, &one, s, &inc, w_new, &inc);
120
-
121
- gs = ddot_(&n, g, &inc, s, &inc);
122
- prered = -0.5*(gs-ddot_(&n, s, &inc, r, &inc));
123
- fnew = fun_obj->fun(w_new);
124
-
125
- // Compute the actual reduction.
126
- actred = f - fnew;
127
-
128
- // On the first iteration, adjust the initial step bound.
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
- }
135
-
136
- // Compute prediction alpha*sMnorm of the step.
137
- if (fnew - f - gs <= 0)
138
- alpha = sigma3;
139
- else
140
- alpha = max(sigma1, -0.5*(gs/(fnew - f - gs)));
141
-
142
- // Update the trust region bound according to the ratio of actual to predicted reduction.
143
- if (actred < eta0*prered)
144
- delta = min(alpha*sMnorm, sigma2*delta);
145
- else if (actred < eta1*prered)
146
- delta = max(sigma1*delta, min(alpha*sMnorm, sigma2*delta));
147
- else if (actred < eta2*prered)
148
- delta = max(sigma1*delta, min(alpha*sMnorm, sigma3*delta));
149
- else
150
- {
151
- if (reach_boundary)
152
- delta = sigma3*delta;
153
- else
154
- delta = max(delta, min(alpha*sMnorm, sigma3*delta));
155
- }
156
-
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);
158
-
159
- if (actred > eta0*prered)
160
- {
161
- iter++;
162
- memcpy(w, w_new, sizeof(double)*n);
163
- f = fnew;
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];
168
-
169
- gnorm = dnrm2_(&n, g, &inc);
170
- if (gnorm <= eps*gnorm0)
171
- break;
172
- }
173
- if (f < -1.0e+32)
174
- {
175
- info("WARNING: f < -1.0e+32\n");
176
- break;
177
- }
178
- if (prered <= 0)
179
- {
180
- info("WARNING: prered <= 0\n");
181
- break;
182
- }
183
- if (fabs(actred) <= 1.0e-12*fabs(f) &&
184
- fabs(prered) <= 1.0e-12*fabs(f))
185
- {
186
- info("WARNING: actred and prered too small\n");
187
- break;
188
- }
189
- }
190
-
191
- delete[] g;
192
- delete[] r;
193
- delete[] w_new;
194
- delete[] s;
195
- delete[] M;
196
- }
197
-
198
- int TRON::trpcg(double delta, double *g, double *M, double *s, double *r, bool *reach_boundary)
199
- {
200
- int i, inc = 1;
201
- int n = fun_obj->get_nr_variable();
202
- double one = 1;
203
- double *d = new double[n];
204
- double *Hd = new double[n];
205
- double zTr, znewTrnew, alpha, beta, cgtol;
206
- double *z = new double[n];
207
-
208
- *reach_boundary = false;
209
- for (i=0; i<n; i++)
210
- {
211
- s[i] = 0;
212
- r[i] = -g[i];
213
- z[i] = r[i] / M[i];
214
- d[i] = z[i];
215
- }
216
-
217
- zTr = ddot_(&n, z, &inc, r, &inc);
218
- cgtol = eps_cg*sqrt(zTr);
219
- int cg_iter = 0;
220
- int max_cg_iter = max(n, 5);
221
-
222
- while (cg_iter < max_cg_iter)
223
- {
224
- if (sqrt(zTr) <= cgtol)
225
- break;
226
- cg_iter++;
227
- fun_obj->Hv(d, Hd);
228
-
229
- alpha = zTr/ddot_(&n, d, &inc, Hd, &inc);
230
- daxpy_(&n, &alpha, d, &inc, s, &inc);
231
-
232
- double sMnorm = sqrt(uTMv(n, s, M, s));
233
- if (sMnorm > delta)
234
- {
235
- info("cg reaches trust region boundary\n");
236
- *reach_boundary = true;
237
- alpha = -alpha;
238
- daxpy_(&n, &alpha, d, &inc, s, &inc);
239
-
240
- double sTMd = uTMv(n, s, M, d);
241
- double sTMs = uTMv(n, s, M, s);
242
- double dTMd = uTMv(n, d, M, d);
243
- double dsq = delta*delta;
244
- double rad = sqrt(sTMd*sTMd + dTMd*(dsq-sTMs));
245
- if (sTMd >= 0)
246
- alpha = (dsq - sTMs)/(sTMd + rad);
247
- else
248
- alpha = (rad - sTMd)/dTMd;
249
- daxpy_(&n, &alpha, d, &inc, s, &inc);
250
- alpha = -alpha;
251
- daxpy_(&n, &alpha, Hd, &inc, r, &inc);
252
- break;
253
- }
254
- alpha = -alpha;
255
- daxpy_(&n, &alpha, Hd, &inc, r, &inc);
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;
261
- dscal_(&n, &beta, d, &inc);
262
- daxpy_(&n, &one, z, &inc, d, &inc);
263
- zTr = znewTrnew;
264
- }
265
-
266
- if (cg_iter == max_cg_iter)
267
- info("WARNING: reaching maximal number of CG steps\n");
268
-
269
- delete[] d;
270
- delete[] Hd;
271
- delete[] z;
272
-
273
- return(cg_iter);
274
- }
275
-
276
- double TRON::norm_inf(int n, double *x)
277
- {
278
- double dmax = fabs(x[0]);
279
- for (int i=1; i<n; i++)
280
- if (fabs(x[i]) >= dmax)
281
- dmax = fabs(x[i]);
282
- return(dmax);
283
- }
284
-
285
- void TRON::set_print_string(void (*print_string) (const char *buf))
286
- {
287
- tron_print_string = print_string;
288
- }