numo-liblinear 0.1.0 → 0.2.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: 7db70ba7431ce52aa9530d3d340a6dce5a616daa
4
- data.tar.gz: ce1a99b9082477922ed35768de8467b514d36541
3
+ metadata.gz: 3bf71a14ccac359b6dffce32a5a5d3c784ef9efa
4
+ data.tar.gz: 6af9f95c6b28c11b06fc0b10628a37e9397564c5
5
5
  SHA512:
6
- metadata.gz: 79e9cbacea54a665ddb971da7b08fd3a43d159a0314715d0aecbf5c19b3b3c95adca6f8b29217c354348d9d8417b9c14742a8d1a5f2debd2db51dd92c32007d5
7
- data.tar.gz: 96a37fde1a15d9a79d7c2bbf374691e8358b42afadf1df58ac1097a6af1bc52ebcd5e6b43601e5ec15582fc79e9b430c20bc39b42503083c0991066b34d9bbbc
6
+ metadata.gz: 18e64c5d487cab2636216425e45fd8eeaefa0f14026068d3678f0d8d643aea00acf867aa64ba510a62d4c343408a9e22bace2a0347a7b7aba7ddd872f2bbc579
7
+ data.tar.gz: 43e16f69a931aab7a45163f1909e307f3334ef88f4e45ed79e5513b288804d5c0dfcbb92ef79642bb7c40e70bcdffe6f47548a2cad10351da3585dd48f0a84db
data/CHANGELOG.md CHANGED
@@ -1,2 +1,6 @@
1
+ # 0.2.0
2
+ - Add valation of method parameters.
3
+ - Several documentation improvements.
4
+
1
5
  # 0.1.0
2
6
  - First release.
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # Numo::Liblinear
2
2
 
3
3
  [![Build Status](https://travis-ci.org/yoshoku/numo-liblinear.svg?branch=master)](https://travis-ci.org/yoshoku/numo-liblinear)
4
+ [![Gem Version](https://badge.fury.io/rb/numo-liblinear.svg)](https://badge.fury.io/rb/numo-liblinear)
4
5
  [![BSD 3-Clause License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://github.com/yoshoku/numo-liblinear/blob/master/LICENSE.txt)
6
+ [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](https://www.rubydoc.info/gems/numo-liblinear/0.2.0)
5
7
 
6
8
  Numo::Liblinear is a Ruby gem binding to the [LIBLINEAR](https://www.csie.ntu.edu.tw/~cjlin/liblinear/) library.
7
9
  LIBLINEAR is one of the famous libraries for large-scale regularized linear classification and regression.
@@ -12,10 +12,13 @@ void print_null(const char *s) {}
12
12
  * Train the model according to the given training data.
13
13
  *
14
14
  * @overload train(x, y, param) -> Hash
15
+ * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be used for training the model.
16
+ * @param y [Numo::DFloat] (shape: [n_samples]) The labels or target values for samples.
17
+ * @param param [Hash] The parameters of a model.
15
18
  *
16
- * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be used for training the model.
17
- * @param y [Numo::DFloat] (shape: [n_samples]) The labels or target values for samples.
18
- * @param param [Hash] The parameters of a model.
19
+ * @raise [ArgumentError] If the sample array is not 2-dimensional, the label array is not 1-dimensional,
20
+ * the sample array and label array do not have the same number of samples, or
21
+ * the hyperparameter has an invalid value, this error is raised.
19
22
  * @return [Hash] The model obtained from the training procedure.
20
23
  */
21
24
  static
@@ -24,6 +27,9 @@ VALUE numo_liblinear_train(VALUE self, VALUE x_val, VALUE y_val, VALUE param_has
24
27
  struct problem* problem;
25
28
  struct parameter* param;
26
29
  struct model* model;
30
+ narray_t* x_nary;
31
+ narray_t* y_nary;
32
+ char* err_msg;
27
33
  VALUE model_hash;
28
34
 
29
35
  if (CLASS_OF(x_val) != numo_cDFloat) {
@@ -39,9 +45,32 @@ VALUE numo_liblinear_train(VALUE self, VALUE x_val, VALUE y_val, VALUE param_has
39
45
  y_val = nary_dup(y_val);
40
46
  }
41
47
 
48
+ GetNArray(x_val, x_nary);
49
+ GetNArray(y_val, y_nary);
50
+ if (NA_NDIM(x_nary) != 2) {
51
+ rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
52
+ return Qnil;
53
+ }
54
+ if (NA_NDIM(y_nary) != 1) {
55
+ rb_raise(rb_eArgError, "Expect label or target values to be 1-D arrray.");
56
+ return Qnil;
57
+ }
58
+ if (NA_SHAPE(x_nary)[0] != NA_SHAPE(y_nary)[0]) {
59
+ rb_raise(rb_eArgError, "Expect to have the same number of samples for samples and labels.");
60
+ return Qnil;
61
+ }
62
+
42
63
  param = rb_hash_to_parameter(param_hash);
43
64
  problem = dataset_to_problem(x_val, y_val);
44
65
 
66
+ err_msg = check_parameter(problem, param);
67
+ if (err_msg) {
68
+ xfree_problem(problem);
69
+ xfree_parameter(param);
70
+ rb_raise(rb_eArgError, "Invalid LIBLINEAR parameter is given: %s", err_msg);
71
+ return Qnil;
72
+ }
73
+
45
74
  set_print_string_function(print_null);
46
75
  model = train(problem, param);
47
76
  model_hash = model_to_rb_hash(model);
@@ -58,11 +87,14 @@ VALUE numo_liblinear_train(VALUE self, VALUE x_val, VALUE y_val, VALUE param_has
58
87
  * The predicted labels or values in the validation process are returned.
59
88
  *
60
89
  * @overload cv(x, y, param, n_folds) -> Numo::DFloat
90
+ * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be used for training the model.
91
+ * @param y [Numo::DFloat] (shape: [n_samples]) The labels or target values for samples.
92
+ * @param param [Hash] The parameters of a model.
93
+ * @param n_folds [Integer] The number of folds.
61
94
  *
62
- * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be used for training the model.
63
- * @param y [Numo::DFloat] (shape: [n_samples]) The labels or target values for samples.
64
- * @param param [Hash] The parameters of a model.
65
- * @param n_folds [Integer] The number of folds.
95
+ * @raise [ArgumentError] If the sample array is not 2-dimensional, the label array is not 1-dimensional,
96
+ * the sample array and label array do not have the same number of samples, or
97
+ * the hyperparameter has an invalid value, this error is raised.
66
98
  * @return [Numo::DFloat] (shape: [n_samples]) The predicted class label or value of each sample.
67
99
  */
68
100
  static
@@ -72,6 +104,9 @@ VALUE numo_liblinear_cross_validation(VALUE self, VALUE x_val, VALUE y_val, VALU
72
104
  size_t t_shape[1];
73
105
  VALUE t_val;
74
106
  double* t_pt;
107
+ narray_t* x_nary;
108
+ narray_t* y_nary;
109
+ char* err_msg;
75
110
  struct problem* problem;
76
111
  struct parameter* param;
77
112
 
@@ -88,9 +123,32 @@ VALUE numo_liblinear_cross_validation(VALUE self, VALUE x_val, VALUE y_val, VALU
88
123
  y_val = nary_dup(y_val);
89
124
  }
90
125
 
126
+ GetNArray(x_val, x_nary);
127
+ GetNArray(y_val, y_nary);
128
+ if (NA_NDIM(x_nary) != 2) {
129
+ rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
130
+ return Qnil;
131
+ }
132
+ if (NA_NDIM(y_nary) != 1) {
133
+ rb_raise(rb_eArgError, "Expect label or target values to be 1-D arrray.");
134
+ return Qnil;
135
+ }
136
+ if (NA_SHAPE(x_nary)[0] != NA_SHAPE(y_nary)[0]) {
137
+ rb_raise(rb_eArgError, "Expect to have the same number of samples for samples and labels.");
138
+ return Qnil;
139
+ }
140
+
91
141
  param = rb_hash_to_parameter(param_hash);
92
142
  problem = dataset_to_problem(x_val, y_val);
93
143
 
144
+ err_msg = check_parameter(problem, param);
145
+ if (err_msg) {
146
+ xfree_problem(problem);
147
+ xfree_parameter(param);
148
+ rb_raise(rb_eArgError, "Invalid LIBLINEAR parameter is given: %s", err_msg);
149
+ return Qnil;
150
+ }
151
+
94
152
  t_shape[0] = problem->l;
95
153
  t_val = rb_narray_new(numo_cDFloat, 1, t_shape);
96
154
  t_pt = (double*)na_get_pointer_for_write(t_val);
@@ -109,10 +167,11 @@ VALUE numo_liblinear_cross_validation(VALUE self, VALUE x_val, VALUE y_val, VALU
109
167
  * Predict class labels or values for given samples.
110
168
  *
111
169
  * @overload predict(x, param, model) -> Numo::DFloat
170
+ * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to calculate the scores.
171
+ * @param param [Hash] The parameters of the trained model.
172
+ * @param model [Hash] The model obtained from the training procedure.
112
173
  *
113
- * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to calculate the scores.
114
- * @param param [Hash] The parameters of the trained model.
115
- * @param model [Hash] The model obtained from the training procedure.
174
+ * @raise [ArgumentError] If the sample array is not 2-dimensional, this error is raised.
116
175
  * @return [Numo::DFloat] (shape: [n_samples]) The predicted class label or value of each sample.
117
176
  */
118
177
  static
@@ -137,7 +196,13 @@ VALUE numo_liblinear_predict(VALUE self, VALUE x_val, VALUE param_hash, VALUE mo
137
196
  if (!RTEST(nary_check_contiguous(x_val))) {
138
197
  x_val = nary_dup(x_val);
139
198
  }
199
+
140
200
  GetNArray(x_val, x_nary);
201
+ if (NA_NDIM(x_nary) != 2) {
202
+ rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
203
+ return Qnil;
204
+ }
205
+
141
206
  param = rb_hash_to_parameter(param_hash);
142
207
  model = rb_hash_to_model(model_hash);
143
208
  model->param = *param;
@@ -173,10 +238,11 @@ VALUE numo_liblinear_predict(VALUE self, VALUE x_val, VALUE param_hash, VALUE mo
173
238
  * Calculate decision values for given samples.
174
239
  *
175
240
  * @overload decision_function(x, param, model) -> Numo::DFloat
241
+ * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to calculate the scores.
242
+ * @param param [Hash] The parameters of the trained model.
243
+ * @param model [Hash] The model obtained from the training procedure.
176
244
  *
177
- * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to calculate the scores.
178
- * @param param [Hash] The parameters of the trained model.
179
- * @param model [Hash] The model obtained from the training procedure.
245
+ * @raise [ArgumentError] If the sample array is not 2-dimensional, this error is raised.
180
246
  * @return [Numo::DFloat] (shape: [n_samples, n_classes]) The decision value of each sample.
181
247
  */
182
248
  static
@@ -203,7 +269,13 @@ VALUE numo_liblinear_decision_function(VALUE self, VALUE x_val, VALUE param_hash
203
269
  if (!RTEST(nary_check_contiguous(x_val))) {
204
270
  x_val = nary_dup(x_val);
205
271
  }
272
+
206
273
  GetNArray(x_val, x_nary);
274
+ if (NA_NDIM(x_nary) != 2) {
275
+ rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
276
+ return Qnil;
277
+ }
278
+
207
279
  param = rb_hash_to_parameter(param_hash);
208
280
  model = rb_hash_to_model(model_hash);
209
281
  model->param = *param;
@@ -270,10 +342,11 @@ VALUE numo_liblinear_decision_function(VALUE self, VALUE x_val, VALUE param_hash
270
342
  * The method supports only the logistic regression.
271
343
  *
272
344
  * @overload predict_proba(x, param, model) -> Numo::DFloat
345
+ * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the class probabilities.
346
+ * @param param [Hash] The parameters of the trained Logistic Regression model.
347
+ * @param model [Hash] The model obtained from the training procedure.
273
348
  *
274
- * @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the class probabilities.
275
- * @param param [Hash] The parameters of the trained Logistic Regression model.
276
- * @param model [Hash] The model obtained from the training procedure.
349
+ * @raise [ArgumentError] If the sample array is not 2-dimensional, this error is raised.
277
350
  * @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probablity of each class per sample.
278
351
  */
279
352
  static
@@ -292,6 +365,12 @@ VALUE numo_liblinear_predict_proba(VALUE self, VALUE x_val, VALUE param_hash, VA
292
365
  int n_samples;
293
366
  int n_features;
294
367
 
368
+ GetNArray(x_val, x_nary);
369
+ if (NA_NDIM(x_nary) != 2) {
370
+ rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
371
+ return Qnil;
372
+ }
373
+
295
374
  param = rb_hash_to_parameter(param_hash);
296
375
  model = rb_hash_to_model(model_hash);
297
376
  model->param = *param;
@@ -304,7 +383,6 @@ VALUE numo_liblinear_predict_proba(VALUE self, VALUE x_val, VALUE param_hash, VA
304
383
  if (!RTEST(nary_check_contiguous(x_val))) {
305
384
  x_val = nary_dup(x_val);
306
385
  }
307
- GetNArray(x_val, x_nary);
308
386
 
309
387
  /* Initialize some variables. */
310
388
  n_samples = (int)NA_SHAPE(x_nary)[0];
@@ -343,17 +421,26 @@ VALUE numo_liblinear_predict_proba(VALUE self, VALUE x_val, VALUE param_hash, VA
343
421
  /**
344
422
  * Load the parameters and model from a text file with LIBLINEAR format.
345
423
  *
346
- * @param filename [String] The path to a file to load.
424
+ * @overload load_model(filename) -> Array
425
+ * @param filename [String] The path to a file to load.
426
+ *
427
+ * @raise [IOError] This error raises when failed to load the model file.
347
428
  * @return [Array] Array contains the parameters and model.
348
429
  */
349
430
  static
350
431
  VALUE numo_liblinear_load_model(VALUE self, VALUE filename)
351
432
  {
352
- struct model* model = load_model(StringValuePtr(filename));
433
+ char* filename_ = StringValuePtr(filename);
434
+ struct model* model = load_model(filename_);
353
435
  VALUE res = rb_ary_new2(2);
354
436
  VALUE param_hash = Qnil;
355
437
  VALUE model_hash = Qnil;
356
438
 
439
+ if (model == NULL) {
440
+ rb_raise(rb_eIOError, "Failed to load file '%s'", filename_);
441
+ return Qnil;
442
+ }
443
+
357
444
  if (model) {
358
445
  param_hash = parameter_to_rb_hash(&(model->param));
359
446
  model_hash = model_to_rb_hash(model);
@@ -371,26 +458,33 @@ VALUE numo_liblinear_load_model(VALUE self, VALUE filename)
371
458
  * Note that the save_model saves only the parameters necessary for estimation with the trained model.
372
459
  *
373
460
  * @overload save_model(filename, param, model) -> Boolean
461
+ * @param filename [String] The path to a file to save.
462
+ * @param param [Hash] The parameters of the trained model.
463
+ * @param model [Hash] The model obtained from the training procedure.
374
464
  *
375
- * @param filename [String] The path to a file to save.
376
- * @param param [Hash] The parameters of the trained model.
377
- * @param model [Hash] The model obtained from the training procedure.
465
+ * @raise [IOError] This error raises when failed to save the model file.
378
466
  * @return [Boolean] true on success, or false if an error occurs.
379
467
  */
380
468
  static
381
469
  VALUE numo_liblinear_save_model(VALUE self, VALUE filename, VALUE param_hash, VALUE model_hash)
382
470
  {
471
+ char* filename_ = StringValuePtr(filename);
383
472
  struct parameter* param = rb_hash_to_parameter(param_hash);
384
473
  struct model* model = rb_hash_to_model(model_hash);
385
474
  int res;
386
475
 
387
476
  model->param = *param;
388
- res = save_model(StringValuePtr(filename), model);
477
+ res = save_model(filename_, model);
389
478
 
390
479
  xfree_model(model);
391
480
  xfree_parameter(param);
392
481
 
393
- return res < 0 ? Qfalse : Qtrue;
482
+ if (res < 0) {
483
+ rb_raise(rb_eIOError, "Failed to save file '%s'", filename_);
484
+ return Qfalse;
485
+ }
486
+
487
+ return Qtrue;
394
488
  }
395
489
 
396
490
  void Init_liblinearext()
@@ -3,6 +3,6 @@
3
3
  module Numo
4
4
  module Liblinear
5
5
  # The version of Numo::Liblienar you are using.
6
- VERSION = '0.1.0'
6
+ VERSION = '0.2.0'
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-liblinear
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.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-07-26 00:00:00.000000000 Z
11
+ date: 2019-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray