numo-libsvm 0.4.0 → 0.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '098e529149ba06f54fc8c4949afa2051dd62f856'
4
- data.tar.gz: b86c22820135dff7f95c34dfe6517f89d451156f
3
+ metadata.gz: 4366bf85268dddd0d9717790646f16ba73bfcc5f
4
+ data.tar.gz: 8bb7e4a8a79b86f4f60c73f7087af628e3d9751f
5
5
  SHA512:
6
- metadata.gz: 8d3ed02591f622d50203c6552671ebcfa26ead1cf86816e0ae166548981409ef8b6b14bce2a0123e9d3f1abcaf121b52c49e7ee4110ebc3e4a0f4224902c388a
7
- data.tar.gz: 56595713d0dccca3f953ee7583f90ca6fb63d83eedb0d6f2878caaacf6c8db859628f82c88e95b5062eabb85316bbe034fa716b86aebd07fc5f414a5f1ccda77
6
+ metadata.gz: 3beb968e572a1750522d85081feddd124464b4961e03578635b68afab00e69c9003323f5d7e1f983865ceb14842ec733bbe082b3f58fc630b45812a6b4a81692
7
+ data.tar.gz: a07ff40e86e815fbe11445a7919c8350dd51471e152dcc783e0e71cb641635e8d7dd9e6476c40ee8a60acfe85adfc1125731359b3bf72d7a4222d9dd8ee1def9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # 0.5.0
2
+ - Fix to use LIBSVM sparce vector representation for internal processing.
3
+
1
4
  # 0.4.0
2
5
  - Add verbose parameter to output learning process messages.
3
6
  - Several documentation improvements.
@@ -132,31 +132,65 @@ VALUE svm_nodes_to_nary(struct svm_node** const support_vecs, const int n_suppor
132
132
  return v;
133
133
  }
134
134
 
135
- struct svm_node** nary_to_svm_nodes(VALUE model_val)
135
+ struct svm_node** nary_to_svm_nodes(VALUE nary_val)
136
136
  {
137
- int i, j;
138
- int n_rows, n_cols;
139
- narray_t* model_nary;
140
- double* model_pt;
137
+ int i, j, k;
138
+ int n_rows, n_cols, n_nonzero_cols;
139
+ narray_t* nary;
140
+ double* nary_pt;
141
141
  struct svm_node** support_vecs;
142
142
 
143
- if (model_val == Qnil) return NULL;
143
+ if (nary_val == Qnil) return NULL;
144
144
 
145
- GetNArray(model_val, model_nary);
146
- n_rows = (int)NA_SHAPE(model_nary)[0];
147
- n_cols = (int)NA_SHAPE(model_nary)[1];
145
+ GetNArray(nary_val, nary);
146
+ n_rows = (int)NA_SHAPE(nary)[0];
147
+ n_cols = (int)NA_SHAPE(nary)[1];
148
148
 
149
- model_pt = (double*)na_get_pointer_for_read(model_val);
149
+ nary_pt = (double*)na_get_pointer_for_read(nary_val);
150
150
  support_vecs = ALLOC_N(struct svm_node*, n_rows);
151
151
  for (i = 0; i < n_rows; i++) {
152
- support_vecs[i] = ALLOC_N(struct svm_node, n_cols + 1);
152
+ n_nonzero_cols = 0;
153
153
  for (j = 0; j < n_cols; j++) {
154
- support_vecs[i][j].index = j + 1;
155
- support_vecs[i][j].value = model_pt[i * n_cols + j];
154
+ if (nary_pt[i * n_cols + j] != 0) {
155
+ n_nonzero_cols++;
156
+ }
157
+ }
158
+ support_vecs[i] = ALLOC_N(struct svm_node, n_nonzero_cols + 1);
159
+ for (j = 0, k = 0; j < n_cols; j++) {
160
+ if (nary_pt[i * n_cols + j] != 0) {
161
+ support_vecs[i][k].index = j + 1;
162
+ support_vecs[i][k].value = nary_pt[i * n_cols + j];
163
+ k++;
164
+ }
156
165
  }
157
- support_vecs[i][n_cols].index = -1;
158
- support_vecs[i][n_cols].value = 0.0;
166
+ support_vecs[i][n_nonzero_cols].index = -1;
167
+ support_vecs[i][n_nonzero_cols].value = 0.0;
159
168
  }
160
169
 
161
170
  return support_vecs;
162
171
  }
172
+
173
+ struct svm_node* dbl_vec_to_svm_node(double* const arr, int const size)
174
+ {
175
+ int i, j;
176
+ int n_nonzero_elements;
177
+ struct svm_node* node;
178
+
179
+ n_nonzero_elements = 0;
180
+ for (i = 0; i < size; i++) {
181
+ if (arr[i] != 0.0) n_nonzero_elements++;
182
+ }
183
+
184
+ node = ALLOC_N(struct svm_node, n_nonzero_elements + 1);
185
+ for (i = 0, j = 0; i < size; i++) {
186
+ if (arr[i] != 0.0) {
187
+ node[j].index = i + 1;
188
+ node[j].value = arr[i];
189
+ j++;
190
+ }
191
+ }
192
+ node[n_nonzero_elements].index = -1;
193
+ node[n_nonzero_elements].value = 0.0;
194
+
195
+ return node;
196
+ }
@@ -14,6 +14,7 @@ double* nary_to_dbl_vec(VALUE vec_val);
14
14
  VALUE dbl_mat_to_nary(double** const mat, int const n_rows, int const n_cols);
15
15
  double** nary_to_dbl_mat(VALUE mat_val);
16
16
  VALUE svm_nodes_to_nary(struct svm_node** const support_vecs, const int n_support_vecs);
17
- struct svm_node** nary_to_svm_nodes(VALUE model_val);
17
+ struct svm_node** nary_to_svm_nodes(VALUE nary_val);
18
+ struct svm_node* dbl_vec_to_svm_node(double* const arr, int const size);
18
19
 
19
20
  #endif /* NUMO_LIBSVM_CONVERTER_H */
@@ -254,9 +254,10 @@ VALUE predict(VALUE self, VALUE x_val, VALUE param_hash, VALUE model_hash)
254
254
  size_t y_shape[1];
255
255
  VALUE y_val;
256
256
  double* y_pt;
257
- int i, j;
257
+ int i, j, k;
258
258
  int n_samples;
259
259
  int n_features;
260
+ int n_nonzero_features;
260
261
 
261
262
  /* Obtain C data structures. */
262
263
  if (CLASS_OF(x_val) != numo_cDFloat) {
@@ -285,18 +286,12 @@ VALUE predict(VALUE self, VALUE x_val, VALUE param_hash, VALUE model_hash)
285
286
  x_pt = (double*)na_get_pointer_for_read(x_val);
286
287
 
287
288
  /* Predict values. */
288
- x_nodes = ALLOC_N(struct svm_node, n_features + 1);
289
- x_nodes[n_features].index = -1;
290
- x_nodes[n_features].value = 0.0;
291
289
  for (i = 0; i < n_samples; i++) {
292
- for (j = 0; j < n_features; j++) {
293
- x_nodes[j].index = j + 1;
294
- x_nodes[j].value = (double)x_pt[i * n_features + j];
295
- }
290
+ x_nodes = dbl_vec_to_svm_node(&x_pt[i * n_features], n_features);
296
291
  y_pt[i] = svm_predict(model, x_nodes);
292
+ xfree(x_nodes);
297
293
  }
298
294
 
299
- xfree(x_nodes);
300
295
  xfree_svm_model(model);
301
296
  xfree_svm_parameter(param);
302
297
 
@@ -368,34 +363,22 @@ VALUE decision_function(VALUE self, VALUE x_val, VALUE param_hash, VALUE model_h
368
363
 
369
364
  /* Predict values. */
370
365
  if (model->param.svm_type == ONE_CLASS || model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) {
371
- x_nodes = ALLOC_N(struct svm_node, n_features + 1);
372
- x_nodes[n_features].index = -1;
373
- x_nodes[n_features].value = 0.0;
374
366
  for (i = 0; i < n_samples; i++) {
375
- for (j = 0; j < n_features; j++) {
376
- x_nodes[j].index = j + 1;
377
- x_nodes[j].value = (double)x_pt[i * n_features + j];
378
- }
367
+ x_nodes = dbl_vec_to_svm_node(&x_pt[i * n_features], n_features);
379
368
  svm_predict_values(model, x_nodes, &y_pt[i]);
369
+ xfree(x_nodes);
380
370
  }
381
- xfree(x_nodes);
382
371
  } else {
383
372
  y_cols = (int)y_shape[1];
384
373
  dec_values = ALLOC_N(double, y_cols);
385
- x_nodes = ALLOC_N(struct svm_node, n_features + 1);
386
- x_nodes[n_features].index = -1;
387
- x_nodes[n_features].value = 0.0;
388
374
  for (i = 0; i < n_samples; i++) {
389
- for (j = 0; j < n_features; j++) {
390
- x_nodes[j].index = j + 1;
391
- x_nodes[j].value = (double)x_pt[i * n_features + j];
392
- }
375
+ x_nodes = dbl_vec_to_svm_node(&x_pt[i * n_features], n_features);
393
376
  svm_predict_values(model, x_nodes, dec_values);
377
+ xfree(x_nodes);
394
378
  for (j = 0; j < y_cols; j++) {
395
379
  y_pt[i * y_cols + j] = dec_values[j];
396
380
  }
397
381
  }
398
- xfree(x_nodes);
399
382
  xfree(dec_values);
400
383
  }
401
384
 
@@ -463,20 +446,14 @@ VALUE predict_proba(VALUE self, VALUE x_val, VALUE param_hash, VALUE model_hash)
463
446
 
464
447
  /* Predict values. */
465
448
  probs = ALLOC_N(double, model->nr_class);
466
- x_nodes = ALLOC_N(struct svm_node, n_features + 1);
467
- x_nodes[n_features].index = -1;
468
- x_nodes[n_features].value = 0.0;
469
449
  for (i = 0; i < n_samples; i++) {
470
- for (j = 0; j < n_features; j++) {
471
- x_nodes[j].index = j + 1;
472
- x_nodes[j].value = (double)x_pt[i * n_features + j];
473
- }
450
+ x_nodes = dbl_vec_to_svm_node(&x_pt[i * n_features], n_features);
474
451
  svm_predict_probability(model, x_nodes, probs);
452
+ xfree(x_nodes);
475
453
  for (j = 0; j < model->nr_class; j++) {
476
454
  y_pt[i * model->nr_class + j] = probs[j];
477
455
  }
478
456
  }
479
- xfree(x_nodes);
480
457
  xfree(probs);
481
458
  }
482
459
 
@@ -29,9 +29,12 @@ struct svm_problem* dataset_to_svm_problem(VALUE x_val, VALUE y_val)
29
29
  narray_t* x_nary;
30
30
  double* x_pt;
31
31
  double* y_pt;
32
- int i, j;
32
+ int i, j, k;
33
33
  int n_samples;
34
34
  int n_features;
35
+ int n_nonzero_features;
36
+ int is_padded;
37
+ int last_feature_id;
35
38
 
36
39
  GetNArray(x_val, x_nary);
37
40
  n_samples = (int)NA_SHAPE(x_nary)[0];
@@ -43,14 +46,40 @@ struct svm_problem* dataset_to_svm_problem(VALUE x_val, VALUE y_val)
43
46
  problem->l = n_samples;
44
47
  problem->x = ALLOC_N(struct svm_node*, n_samples);
45
48
  problem->y = ALLOC_N(double, n_samples);
49
+
50
+ is_padded = 0;
46
51
  for (i = 0; i < n_samples; i++) {
47
- problem->x[i] = ALLOC_N(struct svm_node, n_features + 1);
52
+ n_nonzero_features = 0;
48
53
  for (j = 0; j < n_features; j++) {
49
- problem->x[i][j].index = j + 1;
50
- problem->x[i][j].value = x_pt[i * n_features + j];
54
+ if (x_pt[i * n_features + j] != 0.0) {
55
+ n_nonzero_features += 1;
56
+ last_feature_id = j + 1;
57
+ }
58
+ }
59
+ if (is_padded == 0 && last_feature_id == n_features) {
60
+ is_padded = 1;
61
+ }
62
+ if (is_padded == 1) {
63
+ problem->x[i] = ALLOC_N(struct svm_node, n_nonzero_features + 1);
64
+ } else {
65
+ problem->x[i] = ALLOC_N(struct svm_node, n_nonzero_features + 2);
66
+ }
67
+ for (j = 0, k = 0; j < n_features; j++) {
68
+ if (x_pt[i * n_features + j] != 0.0) {
69
+ problem->x[i][k].index = j + 1;
70
+ problem->x[i][k].value = (double)x_pt[i * n_features + j];
71
+ k++;
72
+ }
73
+ }
74
+ if (is_padded == 1) {
75
+ problem->x[i][n_nonzero_features].index = -1;
76
+ problem->x[i][n_nonzero_features].value = 0.0;
77
+ } else {
78
+ problem->x[i][n_nonzero_features].index = n_features;
79
+ problem->x[i][n_nonzero_features].value = 0.0;
80
+ problem->x[i][n_nonzero_features + 1].index = -1;
81
+ problem->x[i][n_nonzero_features + 1].value = 0.0;
51
82
  }
52
- problem->x[i][n_features].index = -1;
53
- problem->x[i][n_features].value = 0.0;
54
83
  problem->y[i] = y_pt[i];
55
84
  }
56
85
 
@@ -3,6 +3,6 @@
3
3
  module Numo
4
4
  module Libsvm
5
5
  # The version of Numo::Libsvm you are using.
6
- VERSION = '0.4.0'
6
+ VERSION = '0.5.0'
7
7
  end
8
8
  end
data/numo-libsvm.gemspec CHANGED
@@ -33,6 +33,12 @@ Gem::Specification.new do |spec|
33
33
  spec.require_paths = ['lib']
34
34
  spec.extensions = ['ext/numo/libsvm/extconf.rb']
35
35
 
36
+ spec.metadata = {
37
+ 'homepage_uri' => 'https://github.com/yoshoku/numo-libsvm',
38
+ 'source_code_uri' => 'https://github.com/yoshoku/numo-libsvm',
39
+ 'documentation_uri' => 'https://yoshoku.github.io/numo-libsvm/doc/'
40
+ }
41
+
36
42
  spec.add_runtime_dependency 'numo-narray', '~> 0.9.1'
37
43
  spec.add_development_dependency 'bundler', '~> 2.0'
38
44
  spec.add_development_dependency 'rake', '~> 10.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-libsvm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-01 00:00:00.000000000 Z
11
+ date: 2019-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -122,7 +122,10 @@ files:
122
122
  homepage: https://github.com/yoshoku/numo-libsvm
123
123
  licenses:
124
124
  - BSD-3-Clause
125
- metadata: {}
125
+ metadata:
126
+ homepage_uri: https://github.com/yoshoku/numo-libsvm
127
+ source_code_uri: https://github.com/yoshoku/numo-libsvm
128
+ documentation_uri: https://yoshoku.github.io/numo-libsvm/doc/
126
129
  post_install_message:
127
130
  rdoc_options: []
128
131
  require_paths: