numo-libsvm 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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: