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