numo-liblinear 1.0.0 → 1.2.1

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