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.
- checksums.yaml +5 -5
- data/.travis.yml +1 -0
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/ext/numo/liblinear/extconf.rb +1 -1
- data/ext/numo/liblinear/liblinear/linear.cpp +779 -257
- data/ext/numo/liblinear/liblinear/linear.h +7 -2
- data/ext/numo/liblinear/liblinear/newton.cpp +245 -0
- data/ext/numo/liblinear/liblinear/{tron.h → newton.h} +11 -10
- data/ext/numo/liblinear/model.c +3 -0
- data/ext/numo/liblinear/parameter.c +34 -27
- data/ext/numo/liblinear/solver_type.c +8 -6
- data/lib/numo/liblinear/version.rb +1 -1
- data/numo-liblinear.gemspec +2 -2
- metadata +10 -11
- data/ext/numo/liblinear/liblinear/tron.cpp +0 -288
data/numo-liblinear.gemspec
CHANGED
@@ -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
|
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', '~>
|
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.
|
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:
|
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: '
|
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: '
|
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/
|
116
|
-
- ext/numo/liblinear/liblinear/
|
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
|
-
|
153
|
-
|
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
|
-
}
|