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.
- checksums.yaml +5 -5
- data/README.md +2 -2
- data/ext/liblinear_wrap.cxx +434 -398
- data/ext/linear.cpp +251 -90
- data/ext/linear.h +2 -2
- data/ext/tron.cpp +72 -33
- data/ext/tron.h +2 -1
- data/lib/liblinear/parameter.rb +1 -1
- data/lib/liblinear/version.rb +1 -1
- metadata +3 -4
data/ext/linear.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#ifndef _LIBLINEAR_H
|
2
2
|
#define _LIBLINEAR_H
|
3
3
|
|
4
|
-
#define LIBLINEAR_VERSION
|
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
|
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);
|
data/ext/tron.cpp
CHANGED
@@ -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,
|
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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
111
|
-
if (iter == 1)
|
112
|
-
|
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*
|
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(
|
144
|
+
delta = min(alpha*sMnorm, sigma2*delta);
|
123
145
|
else if (actred < eta1*prered)
|
124
|
-
delta = max(sigma1*delta, min(alpha*
|
146
|
+
delta = max(sigma1*delta, min(alpha*sMnorm, sigma2*delta));
|
125
147
|
else if (actred < eta2*prered)
|
126
|
-
delta = max(sigma1*delta, min(alpha*
|
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*
|
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::
|
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
|
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
|
-
|
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
|
-
|
192
|
-
|
220
|
+
int max_cg_iter = max(n, 5);
|
221
|
+
|
222
|
+
while (cg_iter < max_cg_iter)
|
193
223
|
{
|
194
|
-
if (
|
224
|
+
if (sqrt(zTr) <= cgtol)
|
195
225
|
break;
|
196
226
|
cg_iter++;
|
197
227
|
fun_obj->Hv(d, Hd);
|
198
228
|
|
199
|
-
alpha =
|
229
|
+
alpha = zTr/ddot_(&n, d, &inc, Hd, &inc);
|
200
230
|
daxpy_(&n, &alpha, d, &inc, s, &inc);
|
201
|
-
|
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
|
209
|
-
double
|
210
|
-
double
|
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(
|
213
|
-
if (
|
214
|
-
alpha = (dsq -
|
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 -
|
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
|
-
|
225
|
-
|
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,
|
228
|
-
|
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
|
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;
|
data/lib/liblinear/parameter.rb
CHANGED
data/lib/liblinear/version.rb
CHANGED
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.
|
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:
|
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
|
-
|
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
|