numo-liblinear 1.0.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -85,5 +85,8 @@ struct problem* dataset_to_problem(VALUE x_val, VALUE y_val)
85
85
  problem->y[i] = y_pt[i];
86
86
  }
87
87
 
88
+ RB_GC_GUARD(x_val);
89
+ RB_GC_GUARD(y_val);
90
+
88
91
  return problem;
89
92
  }
@@ -17,18 +17,20 @@ void rb_init_solver_type_module()
17
17
  rb_define_const(mSolverType, "L2R_L2LOSS_SVC", INT2NUM(L2R_L2LOSS_SVC));
18
18
  /* L2-regularized L1-loss support vector classification (dual) */
19
19
  rb_define_const(mSolverType, "L2R_L1LOSS_SVC_DUAL", INT2NUM(L2R_L1LOSS_SVC_DUAL));
20
- /* support vector classification by Crammer and Singer */
20
+ /* support vector classification by Crammer and Singer */
21
21
  rb_define_const(mSolverType, "MCSVM_CS", INT2NUM(MCSVM_CS));
22
- /* L1-regularized L2-loss support vector classification */
22
+ /* L1-regularized L2-loss support vector classification */
23
23
  rb_define_const(mSolverType, "L1R_L2LOSS_SVC", INT2NUM(L1R_L2LOSS_SVC));
24
- /* L1-regularized logistic regression */
24
+ /* L1-regularized logistic regression */
25
25
  rb_define_const(mSolverType, "L1R_LR", INT2NUM(L1R_LR));
26
26
  /* L2-regularized logistic regression (dual) */
27
27
  rb_define_const(mSolverType, "L2R_LR_DUAL", INT2NUM(L2R_LR_DUAL));
28
- /* L2-regularized L2-loss support vector regression (primal) */
28
+ /* L2-regularized L2-loss support vector regression (primal) */
29
29
  rb_define_const(mSolverType, "L2R_L2LOSS_SVR", INT2NUM(L2R_L2LOSS_SVR));
30
- /* L2-regularized L2-loss support vector regression (dual) */
30
+ /* L2-regularized L2-loss support vector regression (dual) */
31
31
  rb_define_const(mSolverType, "L2R_L2LOSS_SVR_DUAL", INT2NUM(L2R_L2LOSS_SVR_DUAL));
32
- /* L2-regularized L1-loss support vector regression (dual) */
32
+ /* L2-regularized L1-loss support vector regression (dual) */
33
33
  rb_define_const(mSolverType, "L2R_L1LOSS_SVR_DUAL", INT2NUM(L2R_L1LOSS_SVR_DUAL));
34
+ /* one-class support vector machine (dual) */
35
+ rb_define_const(mSolverType, "ONECLASS_SVM", INT2NUM(ONECLASS_SVM));
34
36
  }
@@ -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.2.1'
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'
@@ -45,10 +45,5 @@ Gem::Specification.new do |spec|
45
45
  'documentation_uri' => 'https://yoshoku.github.io/numo-liblinear/doc/'
46
46
  }
47
47
 
48
- spec.add_runtime_dependency 'numo-narray', '~> 0.9.1'
49
-
50
- spec.add_development_dependency 'bundler', '~> 2.0'
51
- spec.add_development_dependency 'rake', '~> 10.0'
52
- spec.add_development_dependency 'rake-compiler', '~> 1.0'
53
- spec.add_development_dependency 'rspec', '~> 3.0'
48
+ spec.add_runtime_dependency 'numo-narray', '>= 0.9.1'
54
49
  end
@@ -0,0 +1,52 @@
1
+ module Numo
2
+ module Liblinear
3
+ module SolverType
4
+ L2R_LR: Integer
5
+ L2R_L2LOSS_SVC_DUAL: Integer
6
+ L2R_L2LOSS_SVC: Integer
7
+ L2R_L1LOSS_SVC_DUAL: Integer
8
+ MCSVM_CS: Integer
9
+ L1R_L2LOSS_SVC: Integer
10
+ L1R_LR: Integer
11
+ L2R_LR_DUAL: Integer
12
+ L2R_L2LOSS_SVR: Integer
13
+ L2R_L2LOSS_SVR_DUAL: Integer
14
+ L2R_L1LOSS_SVR_DUAL: Integer
15
+ ONECLASS_SVM: Integer
16
+ end
17
+
18
+ LIBLINEAR_VERSION: Integer
19
+ VERSION: String
20
+
21
+ type model = {
22
+ nr_class: Integer,
23
+ nr_feature: Integer,
24
+ w: Numo::DFloat,
25
+ label: Numo::Int32,
26
+ bias: Float,
27
+ rho: Float
28
+ }
29
+
30
+ type param = {
31
+ solver_type: Integer?,
32
+ eps: Float?,
33
+ C: Float?,
34
+ nr_weight: Integer?,
35
+ weight_label: Numo::Int32?,
36
+ weight: Numo::DFloat?,
37
+ p: Float?,
38
+ nu: Float?,
39
+ verbose: bool?,
40
+ random_seed: Integer?
41
+ }
42
+
43
+ def self?.cv: (Numo::DFloat x, Numo::DFloat y, param, Integer n_folds) -> Numo::DFloat
44
+ def self?.train: (Numo::DFloat x, Numo::DFloat y, param) -> model
45
+ def self?.predict: (Numo::DFloat x, param, model) -> Numo::DFloat
46
+ def self?.predict_proba: (Numo::DFloat x, param, model) -> Numo::DFloat
47
+ def self?.decision_function: (Numo::DFloat x, param, model) -> Numo::DFloat
48
+ def self?.save_model: (String filename, param, model) -> bool
49
+ def self?.load_model: (String filename) -> [param, model]
50
+ end
51
+ end
52
+
data/sig/patch.rbs ADDED
@@ -0,0 +1,8 @@
1
+ module Numo
2
+ class NArray
3
+ end
4
+ class DFloat < NArray
5
+ end
6
+ class Int32 < NArray
7
+ end
8
+ end
metadata CHANGED
@@ -1,85 +1,29 @@
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.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-12 00:00:00.000000000 Z
11
+ date: 2021-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.9.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.9.1
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '2.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '2.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '10.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '10.0'
55
- - !ruby/object:Gem::Dependency
56
- name: rake-compiler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '3.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '3.0'
83
27
  description: |
84
28
  Numo::Liblinear is a Ruby gem binding to the LIBLINEAR library.
85
29
  LIBLINEAR is one of the famous libraries for large-scale regularized linear classification and regression.
@@ -91,16 +35,17 @@ extensions:
91
35
  - ext/numo/liblinear/extconf.rb
92
36
  extra_rdoc_files: []
93
37
  files:
38
+ - ".github/workflows/build.yml"
94
39
  - ".gitignore"
95
40
  - ".gitmodules"
96
41
  - ".rspec"
97
- - ".travis.yml"
98
42
  - CHANGELOG.md
99
43
  - CODE_OF_CONDUCT.md
100
44
  - Gemfile
101
45
  - LICENSE.txt
102
46
  - README.md
103
47
  - Rakefile
48
+ - Steepfile
104
49
  - ext/numo/liblinear/converter.c
105
50
  - ext/numo/liblinear/converter.h
106
51
  - ext/numo/liblinear/extconf.rb
@@ -112,8 +57,8 @@ files:
112
57
  - ext/numo/liblinear/liblinear/blas/dscal.c
113
58
  - ext/numo/liblinear/liblinear/linear.cpp
114
59
  - ext/numo/liblinear/liblinear/linear.h
115
- - ext/numo/liblinear/liblinear/tron.cpp
116
- - ext/numo/liblinear/liblinear/tron.h
60
+ - ext/numo/liblinear/liblinear/newton.cpp
61
+ - ext/numo/liblinear/liblinear/newton.h
117
62
  - ext/numo/liblinear/liblinearext.c
118
63
  - ext/numo/liblinear/liblinearext.h
119
64
  - ext/numo/liblinear/model.c
@@ -127,6 +72,8 @@ files:
127
72
  - lib/numo/liblinear.rb
128
73
  - lib/numo/liblinear/version.rb
129
74
  - numo-liblinear.gemspec
75
+ - sig/numo/liblinear.rbs
76
+ - sig/patch.rbs
130
77
  homepage: https://github.com/yoshoku/numo-liblinear
131
78
  licenses:
132
79
  - BSD-3-Clause
@@ -149,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
96
  - !ruby/object:Gem::Version
150
97
  version: '0'
151
98
  requirements: []
152
- rubyforge_project:
153
- rubygems_version: 2.6.14.4
99
+ rubygems_version: 3.2.21
154
100
  signing_key:
155
101
  specification_version: 4
156
102
  summary: Numo::Liblinear is a Ruby gem binding to the LIBLINEAR library. Numo::Liblinear
data/.travis.yml DELETED
@@ -1,13 +0,0 @@
1
- ---
2
- sudo: true
3
- os: linux
4
- dist: bionic
5
- language: ruby
6
- cache: bundler
7
- rvm:
8
- - '2.4'
9
- - '2.5'
10
- - '2.6'
11
-
12
- before_install:
13
- - gem install bundler -v 2.0.2
@@ -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
- }