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.
@@ -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
- }