numo-liblinear 1.2.2 → 2.0.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +1 -1
- data/README.md +0 -5
- data/ext/numo/liblinear/extconf.rb +8 -14
- data/ext/numo/liblinear/liblinearext.cpp +215 -0
- data/ext/numo/liblinear/liblinearext.hpp +636 -0
- data/ext/numo/liblinear/src/COPYRIGHT +31 -0
- data/ext/numo/liblinear/{liblinear → src}/blas/blas.h +0 -0
- data/ext/numo/liblinear/{liblinear → src}/blas/blasp.h +0 -0
- data/ext/numo/liblinear/{liblinear → src}/blas/daxpy.c +0 -0
- data/ext/numo/liblinear/{liblinear → src}/blas/ddot.c +0 -0
- data/ext/numo/liblinear/{liblinear → src}/blas/dnrm2.c +0 -0
- data/ext/numo/liblinear/{liblinear → src}/blas/dscal.c +0 -0
- data/ext/numo/liblinear/{liblinear → src}/linear.cpp +0 -0
- data/ext/numo/liblinear/{liblinear → src}/linear.h +0 -0
- data/ext/numo/liblinear/{liblinear → src}/newton.cpp +0 -0
- data/ext/numo/liblinear/{liblinear → src}/newton.h +0 -0
- data/lib/numo/liblinear/version.rb +1 -1
- metadata +19 -37
- data/.github/workflows/build.yml +0 -29
- data/.gitignore +0 -20
- data/.gitmodules +0 -3
- data/.rspec +0 -3
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -11
- data/Rakefile +0 -15
- data/Steepfile +0 -20
- data/ext/numo/liblinear/converter.c +0 -133
- data/ext/numo/liblinear/converter.h +0 -18
- data/ext/numo/liblinear/liblinearext.c +0 -576
- data/ext/numo/liblinear/liblinearext.h +0 -17
- data/ext/numo/liblinear/model.c +0 -48
- data/ext/numo/liblinear/model.h +0 -15
- data/ext/numo/liblinear/parameter.c +0 -105
- data/ext/numo/liblinear/parameter.h +0 -15
- data/ext/numo/liblinear/problem.c +0 -92
- data/ext/numo/liblinear/problem.h +0 -12
- data/ext/numo/liblinear/solver_type.c +0 -36
- data/ext/numo/liblinear/solver_type.h +0 -9
- data/numo-liblinear.gemspec +0 -47
@@ -1,576 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* LIBLINEAR interface for Numo::NArray
|
3
|
-
*/
|
4
|
-
#include "liblinearext.h"
|
5
|
-
|
6
|
-
VALUE mNumo;
|
7
|
-
VALUE mLiblinear;
|
8
|
-
|
9
|
-
void print_null(const char *s) {}
|
10
|
-
|
11
|
-
/**
|
12
|
-
* Train the model according to the given training data.
|
13
|
-
*
|
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.
|
18
|
-
*
|
19
|
-
* @example
|
20
|
-
* require 'numo/liblinear'
|
21
|
-
*
|
22
|
-
* # Prepare training dataset.
|
23
|
-
* x = Numo::DFloat[[-0.8, 1.0], [-0.5, 0.8], [0.9, -0.8], [0.8, -0.7]]
|
24
|
-
* y = Numo::Int32[-1, -1, 1, 1]
|
25
|
-
*
|
26
|
-
* # Train L2-regularized L2-loss support vector classifier.
|
27
|
-
* param = {
|
28
|
-
* solver_type: Numo::Liblinear::SolverType::L2R_L2LOSS_SVC_DUAL,
|
29
|
-
* C: 0.1,
|
30
|
-
* random_seed: 1
|
31
|
-
* }
|
32
|
-
* model = Numo::Liblinear.train(x, y, param)
|
33
|
-
*
|
34
|
-
* # Predict labels of test data.
|
35
|
-
* x_test = Numo::DFloat[[-0.7, 0.9], [0.5, -0.4]]
|
36
|
-
* result = Numo::Liblinear.predict(x_test, param, model)
|
37
|
-
* p result
|
38
|
-
* # Numo::DFloat#shape=[2]
|
39
|
-
* # [-1, 1]
|
40
|
-
*
|
41
|
-
* @raise [ArgumentError] If the sample array is not 2-dimensional, the label array is not 1-dimensional,
|
42
|
-
* the sample array and label array do not have the same number of samples, or
|
43
|
-
* the hyperparameter has an invalid value, this error is raised.
|
44
|
-
* @return [Hash] The model obtained from the training procedure.
|
45
|
-
*/
|
46
|
-
static
|
47
|
-
VALUE numo_liblinear_train(VALUE self, VALUE x_val, VALUE y_val, VALUE param_hash)
|
48
|
-
{
|
49
|
-
struct problem* problem;
|
50
|
-
struct parameter* param;
|
51
|
-
struct model* model;
|
52
|
-
narray_t* x_nary;
|
53
|
-
narray_t* y_nary;
|
54
|
-
char* err_msg;
|
55
|
-
VALUE random_seed;
|
56
|
-
VALUE verbose;
|
57
|
-
VALUE model_hash;
|
58
|
-
|
59
|
-
if (CLASS_OF(x_val) != numo_cDFloat) {
|
60
|
-
x_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, x_val);
|
61
|
-
}
|
62
|
-
if (CLASS_OF(y_val) != numo_cDFloat) {
|
63
|
-
y_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, y_val);
|
64
|
-
}
|
65
|
-
if (!RTEST(nary_check_contiguous(x_val))) {
|
66
|
-
x_val = nary_dup(x_val);
|
67
|
-
}
|
68
|
-
if (!RTEST(nary_check_contiguous(y_val))) {
|
69
|
-
y_val = nary_dup(y_val);
|
70
|
-
}
|
71
|
-
|
72
|
-
GetNArray(x_val, x_nary);
|
73
|
-
GetNArray(y_val, y_nary);
|
74
|
-
if (NA_NDIM(x_nary) != 2) {
|
75
|
-
rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
|
76
|
-
return Qnil;
|
77
|
-
}
|
78
|
-
if (NA_NDIM(y_nary) != 1) {
|
79
|
-
rb_raise(rb_eArgError, "Expect label or target values to be 1-D arrray.");
|
80
|
-
return Qnil;
|
81
|
-
}
|
82
|
-
if (NA_SHAPE(x_nary)[0] != NA_SHAPE(y_nary)[0]) {
|
83
|
-
rb_raise(rb_eArgError, "Expect to have the same number of samples for samples and labels.");
|
84
|
-
return Qnil;
|
85
|
-
}
|
86
|
-
|
87
|
-
random_seed = rb_hash_aref(param_hash, ID2SYM(rb_intern("random_seed")));
|
88
|
-
if (!NIL_P(random_seed)) {
|
89
|
-
srand(NUM2UINT(random_seed));
|
90
|
-
}
|
91
|
-
|
92
|
-
param = rb_hash_to_parameter(param_hash);
|
93
|
-
problem = dataset_to_problem(x_val, y_val);
|
94
|
-
|
95
|
-
err_msg = check_parameter(problem, param);
|
96
|
-
if (err_msg) {
|
97
|
-
xfree_problem(problem);
|
98
|
-
xfree_parameter(param);
|
99
|
-
rb_raise(rb_eArgError, "Invalid LIBLINEAR parameter is given: %s", err_msg);
|
100
|
-
return Qnil;
|
101
|
-
}
|
102
|
-
|
103
|
-
verbose = rb_hash_aref(param_hash, ID2SYM(rb_intern("verbose")));
|
104
|
-
if (verbose != Qtrue) {
|
105
|
-
set_print_string_function(print_null);
|
106
|
-
}
|
107
|
-
|
108
|
-
model = train(problem, param);
|
109
|
-
model_hash = model_to_rb_hash(model);
|
110
|
-
free_and_destroy_model(&model);
|
111
|
-
|
112
|
-
xfree_problem(problem);
|
113
|
-
xfree_parameter(param);
|
114
|
-
|
115
|
-
RB_GC_GUARD(x_val);
|
116
|
-
RB_GC_GUARD(y_val);
|
117
|
-
|
118
|
-
return model_hash;
|
119
|
-
}
|
120
|
-
|
121
|
-
/**
|
122
|
-
* Perform cross validation under given parameters. The given samples are separated to n_fols folds.
|
123
|
-
* The predicted labels or values in the validation process are returned.
|
124
|
-
*
|
125
|
-
* @overload cv(x, y, param, n_folds) -> Numo::DFloat
|
126
|
-
* @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be used for training the model.
|
127
|
-
* @param y [Numo::DFloat] (shape: [n_samples]) The labels or target values for samples.
|
128
|
-
* @param param [Hash] The parameters of a model.
|
129
|
-
* @param n_folds [Integer] The number of folds.
|
130
|
-
*
|
131
|
-
* @example
|
132
|
-
* require 'numo/liblinear'
|
133
|
-
*
|
134
|
-
* # x: samples
|
135
|
-
* # y: labels
|
136
|
-
*
|
137
|
-
* # Define parameters of L2-regularized L2-loss support vector classification.
|
138
|
-
* param = {
|
139
|
-
* solver_type: Numo::Liblinear::SolverType::L2R_L2LOSS_SVC_DUAL,
|
140
|
-
* C: 1,
|
141
|
-
* random_seed: 1,
|
142
|
-
* verbose: true
|
143
|
-
* }
|
144
|
-
*
|
145
|
-
* # Perform 5-cross validation.
|
146
|
-
* n_folds = 5
|
147
|
-
* res = Numo::Liblinear::cv(x, y, param, n_folds)
|
148
|
-
*
|
149
|
-
* # Print mean accuracy.
|
150
|
-
* mean_accuracy = y.eq(res).count.fdiv(y.size)
|
151
|
-
* puts "Accuracy: %.1f %%" % (100 * mean_accuracy)
|
152
|
-
*
|
153
|
-
* @raise [ArgumentError] If the sample array is not 2-dimensional, the label array is not 1-dimensional,
|
154
|
-
* the sample array and label array do not have the same number of samples, or
|
155
|
-
* the hyperparameter has an invalid value, this error is raised.
|
156
|
-
* @return [Numo::DFloat] (shape: [n_samples]) The predicted class label or value of each sample.
|
157
|
-
*/
|
158
|
-
static
|
159
|
-
VALUE numo_liblinear_cross_validation(VALUE self, VALUE x_val, VALUE y_val, VALUE param_hash, VALUE nr_folds)
|
160
|
-
{
|
161
|
-
const int n_folds = NUM2INT(nr_folds);
|
162
|
-
size_t t_shape[1];
|
163
|
-
VALUE t_val;
|
164
|
-
double* t_pt;
|
165
|
-
narray_t* x_nary;
|
166
|
-
narray_t* y_nary;
|
167
|
-
char* err_msg;
|
168
|
-
VALUE random_seed;
|
169
|
-
VALUE verbose;
|
170
|
-
struct problem* problem;
|
171
|
-
struct parameter* param;
|
172
|
-
|
173
|
-
if (CLASS_OF(x_val) != numo_cDFloat) {
|
174
|
-
x_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, x_val);
|
175
|
-
}
|
176
|
-
if (CLASS_OF(y_val) != numo_cDFloat) {
|
177
|
-
y_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, y_val);
|
178
|
-
}
|
179
|
-
if (!RTEST(nary_check_contiguous(x_val))) {
|
180
|
-
x_val = nary_dup(x_val);
|
181
|
-
}
|
182
|
-
if (!RTEST(nary_check_contiguous(y_val))) {
|
183
|
-
y_val = nary_dup(y_val);
|
184
|
-
}
|
185
|
-
|
186
|
-
GetNArray(x_val, x_nary);
|
187
|
-
GetNArray(y_val, y_nary);
|
188
|
-
if (NA_NDIM(x_nary) != 2) {
|
189
|
-
rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
|
190
|
-
return Qnil;
|
191
|
-
}
|
192
|
-
if (NA_NDIM(y_nary) != 1) {
|
193
|
-
rb_raise(rb_eArgError, "Expect label or target values to be 1-D arrray.");
|
194
|
-
return Qnil;
|
195
|
-
}
|
196
|
-
if (NA_SHAPE(x_nary)[0] != NA_SHAPE(y_nary)[0]) {
|
197
|
-
rb_raise(rb_eArgError, "Expect to have the same number of samples for samples and labels.");
|
198
|
-
return Qnil;
|
199
|
-
}
|
200
|
-
|
201
|
-
random_seed = rb_hash_aref(param_hash, ID2SYM(rb_intern("random_seed")));
|
202
|
-
if (!NIL_P(random_seed)) {
|
203
|
-
srand(NUM2UINT(random_seed));
|
204
|
-
}
|
205
|
-
|
206
|
-
param = rb_hash_to_parameter(param_hash);
|
207
|
-
problem = dataset_to_problem(x_val, y_val);
|
208
|
-
|
209
|
-
err_msg = check_parameter(problem, param);
|
210
|
-
if (err_msg) {
|
211
|
-
xfree_problem(problem);
|
212
|
-
xfree_parameter(param);
|
213
|
-
rb_raise(rb_eArgError, "Invalid LIBLINEAR parameter is given: %s", err_msg);
|
214
|
-
return Qnil;
|
215
|
-
}
|
216
|
-
|
217
|
-
t_shape[0] = problem->l;
|
218
|
-
t_val = rb_narray_new(numo_cDFloat, 1, t_shape);
|
219
|
-
t_pt = (double*)na_get_pointer_for_write(t_val);
|
220
|
-
|
221
|
-
verbose = rb_hash_aref(param_hash, ID2SYM(rb_intern("verbose")));
|
222
|
-
if (verbose != Qtrue) {
|
223
|
-
set_print_string_function(print_null);
|
224
|
-
}
|
225
|
-
|
226
|
-
cross_validation(problem, param, n_folds, t_pt);
|
227
|
-
|
228
|
-
xfree_problem(problem);
|
229
|
-
xfree_parameter(param);
|
230
|
-
|
231
|
-
RB_GC_GUARD(x_val);
|
232
|
-
RB_GC_GUARD(y_val);
|
233
|
-
|
234
|
-
return t_val;
|
235
|
-
}
|
236
|
-
|
237
|
-
|
238
|
-
/**
|
239
|
-
* Predict class labels or values for given samples.
|
240
|
-
*
|
241
|
-
* @overload predict(x, param, model) -> Numo::DFloat
|
242
|
-
* @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to calculate the scores.
|
243
|
-
* @param param [Hash] The parameters of the trained model.
|
244
|
-
* @param model [Hash] The model obtained from the training procedure.
|
245
|
-
*
|
246
|
-
* @raise [ArgumentError] If the sample array is not 2-dimensional, this error is raised.
|
247
|
-
* @return [Numo::DFloat] (shape: [n_samples]) The predicted class label or value of each sample.
|
248
|
-
*/
|
249
|
-
static
|
250
|
-
VALUE numo_liblinear_predict(VALUE self, VALUE x_val, VALUE param_hash, VALUE model_hash)
|
251
|
-
{
|
252
|
-
struct parameter* param;
|
253
|
-
struct model* model;
|
254
|
-
struct feature_node* x_nodes;
|
255
|
-
narray_t* x_nary;
|
256
|
-
double* x_pt;
|
257
|
-
size_t y_shape[1];
|
258
|
-
VALUE y_val;
|
259
|
-
double* y_pt;
|
260
|
-
int i, j;
|
261
|
-
int n_samples;
|
262
|
-
int n_features;
|
263
|
-
|
264
|
-
/* Obtain C data structures. */
|
265
|
-
if (CLASS_OF(x_val) != numo_cDFloat) {
|
266
|
-
x_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, x_val);
|
267
|
-
}
|
268
|
-
if (!RTEST(nary_check_contiguous(x_val))) {
|
269
|
-
x_val = nary_dup(x_val);
|
270
|
-
}
|
271
|
-
|
272
|
-
GetNArray(x_val, x_nary);
|
273
|
-
if (NA_NDIM(x_nary) != 2) {
|
274
|
-
rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
|
275
|
-
return Qnil;
|
276
|
-
}
|
277
|
-
|
278
|
-
param = rb_hash_to_parameter(param_hash);
|
279
|
-
model = rb_hash_to_model(model_hash);
|
280
|
-
model->param = *param;
|
281
|
-
|
282
|
-
/* Initialize some variables. */
|
283
|
-
n_samples = (int)NA_SHAPE(x_nary)[0];
|
284
|
-
n_features = (int)NA_SHAPE(x_nary)[1];
|
285
|
-
y_shape[0] = n_samples;
|
286
|
-
y_val = rb_narray_new(numo_cDFloat, 1, y_shape);
|
287
|
-
y_pt = (double*)na_get_pointer_for_write(y_val);
|
288
|
-
x_pt = (double*)na_get_pointer_for_read(x_val);
|
289
|
-
|
290
|
-
/* Predict values. */
|
291
|
-
for (i = 0; i < n_samples; i++) {
|
292
|
-
x_nodes = dbl_vec_to_node(&x_pt[i * n_features], n_features);
|
293
|
-
y_pt[i] = predict(model, x_nodes);
|
294
|
-
xfree(x_nodes);
|
295
|
-
}
|
296
|
-
|
297
|
-
xfree_model(model);
|
298
|
-
xfree_parameter(param);
|
299
|
-
|
300
|
-
RB_GC_GUARD(x_val);
|
301
|
-
|
302
|
-
return y_val;
|
303
|
-
}
|
304
|
-
|
305
|
-
/**
|
306
|
-
* Calculate decision values for given samples.
|
307
|
-
*
|
308
|
-
* @overload decision_function(x, param, model) -> Numo::DFloat
|
309
|
-
* @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to calculate the scores.
|
310
|
-
* @param param [Hash] The parameters of the trained model.
|
311
|
-
* @param model [Hash] The model obtained from the training procedure.
|
312
|
-
*
|
313
|
-
* @raise [ArgumentError] If the sample array is not 2-dimensional, this error is raised.
|
314
|
-
* @return [Numo::DFloat] (shape: [n_samples, n_classes]) The decision value of each sample.
|
315
|
-
*/
|
316
|
-
static
|
317
|
-
VALUE numo_liblinear_decision_function(VALUE self, VALUE x_val, VALUE param_hash, VALUE model_hash)
|
318
|
-
{
|
319
|
-
struct parameter* param;
|
320
|
-
struct model* model;
|
321
|
-
struct feature_node* x_nodes;
|
322
|
-
narray_t* x_nary;
|
323
|
-
double* x_pt;
|
324
|
-
size_t y_shape[2];
|
325
|
-
VALUE y_val;
|
326
|
-
double* y_pt;
|
327
|
-
double* dec_values;
|
328
|
-
int y_cols;
|
329
|
-
int i, j;
|
330
|
-
int n_samples;
|
331
|
-
int n_features;
|
332
|
-
|
333
|
-
/* Obtain C data structures. */
|
334
|
-
if (CLASS_OF(x_val) != numo_cDFloat) {
|
335
|
-
x_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, x_val);
|
336
|
-
}
|
337
|
-
if (!RTEST(nary_check_contiguous(x_val))) {
|
338
|
-
x_val = nary_dup(x_val);
|
339
|
-
}
|
340
|
-
|
341
|
-
GetNArray(x_val, x_nary);
|
342
|
-
if (NA_NDIM(x_nary) != 2) {
|
343
|
-
rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
|
344
|
-
return Qnil;
|
345
|
-
}
|
346
|
-
|
347
|
-
param = rb_hash_to_parameter(param_hash);
|
348
|
-
model = rb_hash_to_model(model_hash);
|
349
|
-
model->param = *param;
|
350
|
-
|
351
|
-
/* Initialize some variables. */
|
352
|
-
n_samples = (int)NA_SHAPE(x_nary)[0];
|
353
|
-
n_features = (int)NA_SHAPE(x_nary)[1];
|
354
|
-
|
355
|
-
if (model->nr_class == 2 && model->param.solver_type != MCSVM_CS) {
|
356
|
-
y_shape[0] = n_samples;
|
357
|
-
y_shape[1] = 1;
|
358
|
-
y_val = rb_narray_new(numo_cDFloat, 1, y_shape);
|
359
|
-
} else {
|
360
|
-
y_shape[0] = n_samples;
|
361
|
-
y_shape[1] = model->nr_class;
|
362
|
-
y_val = rb_narray_new(numo_cDFloat, 2, y_shape);
|
363
|
-
}
|
364
|
-
|
365
|
-
x_pt = (double*)na_get_pointer_for_read(x_val);
|
366
|
-
y_pt = (double*)na_get_pointer_for_write(y_val);
|
367
|
-
|
368
|
-
/* Predict values. */
|
369
|
-
if (model->nr_class == 2 && model->param.solver_type != MCSVM_CS) {
|
370
|
-
for (i = 0; i < n_samples; i++) {
|
371
|
-
x_nodes = dbl_vec_to_node(&x_pt[i * n_features], n_features);
|
372
|
-
predict_values(model, x_nodes, &y_pt[i]);
|
373
|
-
xfree(x_nodes);
|
374
|
-
}
|
375
|
-
} else {
|
376
|
-
y_cols = (int)y_shape[1];
|
377
|
-
dec_values = ALLOC_N(double, y_cols);
|
378
|
-
for (i = 0; i < n_samples; i++) {
|
379
|
-
x_nodes = dbl_vec_to_node(&x_pt[i * n_features], n_features);
|
380
|
-
predict_values(model, x_nodes, dec_values);
|
381
|
-
xfree(x_nodes);
|
382
|
-
for (j = 0; j < y_cols; j++) {
|
383
|
-
y_pt[i * y_cols + j] = dec_values[j];
|
384
|
-
}
|
385
|
-
}
|
386
|
-
xfree(dec_values);
|
387
|
-
}
|
388
|
-
|
389
|
-
xfree_model(model);
|
390
|
-
xfree_parameter(param);
|
391
|
-
|
392
|
-
RB_GC_GUARD(x_val);
|
393
|
-
|
394
|
-
return y_val;
|
395
|
-
}
|
396
|
-
|
397
|
-
/**
|
398
|
-
* Predict class probability for given samples.
|
399
|
-
* The model must have probability information calcualted in training procedure.
|
400
|
-
* The method supports only the logistic regression.
|
401
|
-
*
|
402
|
-
* @overload predict_proba(x, param, model) -> Numo::DFloat
|
403
|
-
* @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the class probabilities.
|
404
|
-
* @param param [Hash] The parameters of the trained Logistic Regression model.
|
405
|
-
* @param model [Hash] The model obtained from the training procedure.
|
406
|
-
*
|
407
|
-
* @raise [ArgumentError] If the sample array is not 2-dimensional, this error is raised.
|
408
|
-
* @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probablity of each class per sample.
|
409
|
-
*/
|
410
|
-
static
|
411
|
-
VALUE numo_liblinear_predict_proba(VALUE self, VALUE x_val, VALUE param_hash, VALUE model_hash)
|
412
|
-
{
|
413
|
-
struct parameter* param;
|
414
|
-
struct model* model;
|
415
|
-
struct feature_node* x_nodes;
|
416
|
-
narray_t* x_nary;
|
417
|
-
double* x_pt;
|
418
|
-
size_t y_shape[2];
|
419
|
-
VALUE y_val = Qnil;
|
420
|
-
double* y_pt;
|
421
|
-
double* probs;
|
422
|
-
int i, j;
|
423
|
-
int n_samples;
|
424
|
-
int n_features;
|
425
|
-
|
426
|
-
GetNArray(x_val, x_nary);
|
427
|
-
if (NA_NDIM(x_nary) != 2) {
|
428
|
-
rb_raise(rb_eArgError, "Expect samples to be 2-D array.");
|
429
|
-
return Qnil;
|
430
|
-
}
|
431
|
-
|
432
|
-
param = rb_hash_to_parameter(param_hash);
|
433
|
-
model = rb_hash_to_model(model_hash);
|
434
|
-
model->param = *param;
|
435
|
-
|
436
|
-
if (model->param.solver_type == L2R_LR || model->param.solver_type == L1R_LR || model->param.solver_type == L2R_LR_DUAL) {
|
437
|
-
/* Obtain C data structures. */
|
438
|
-
if (CLASS_OF(x_val) != numo_cDFloat) {
|
439
|
-
x_val = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, x_val);
|
440
|
-
}
|
441
|
-
if (!RTEST(nary_check_contiguous(x_val))) {
|
442
|
-
x_val = nary_dup(x_val);
|
443
|
-
}
|
444
|
-
|
445
|
-
/* Initialize some variables. */
|
446
|
-
n_samples = (int)NA_SHAPE(x_nary)[0];
|
447
|
-
n_features = (int)NA_SHAPE(x_nary)[1];
|
448
|
-
y_shape[0] = n_samples;
|
449
|
-
y_shape[1] = model->nr_class;
|
450
|
-
y_val = rb_narray_new(numo_cDFloat, 2, y_shape);
|
451
|
-
x_pt = (double*)na_get_pointer_for_read(x_val);
|
452
|
-
y_pt = (double*)na_get_pointer_for_write(y_val);
|
453
|
-
|
454
|
-
/* Predict values. */
|
455
|
-
probs = ALLOC_N(double, model->nr_class);
|
456
|
-
for (i = 0; i < n_samples; i++) {
|
457
|
-
x_nodes = dbl_vec_to_node(&x_pt[i * n_features], n_features);
|
458
|
-
predict_probability(model, x_nodes, probs);
|
459
|
-
xfree(x_nodes);
|
460
|
-
for (j = 0; j < model->nr_class; j++) {
|
461
|
-
y_pt[i * model->nr_class + j] = probs[j];
|
462
|
-
}
|
463
|
-
}
|
464
|
-
xfree(probs);
|
465
|
-
}
|
466
|
-
|
467
|
-
xfree_model(model);
|
468
|
-
xfree_parameter(param);
|
469
|
-
|
470
|
-
RB_GC_GUARD(x_val);
|
471
|
-
|
472
|
-
return y_val;
|
473
|
-
}
|
474
|
-
|
475
|
-
/**
|
476
|
-
* Load the parameters and model from a text file with LIBLINEAR format.
|
477
|
-
*
|
478
|
-
* @overload load_model(filename) -> Array
|
479
|
-
* @param filename [String] The path to a file to load.
|
480
|
-
*
|
481
|
-
* @raise [IOError] This error raises when failed to load the model file.
|
482
|
-
* @return [Array] Array contains the parameters and model.
|
483
|
-
*/
|
484
|
-
static
|
485
|
-
VALUE numo_liblinear_load_model(VALUE self, VALUE filename)
|
486
|
-
{
|
487
|
-
char* filename_ = StringValuePtr(filename);
|
488
|
-
struct model* model = load_model(filename_);
|
489
|
-
VALUE res = rb_ary_new2(2);
|
490
|
-
VALUE param_hash = Qnil;
|
491
|
-
VALUE model_hash = Qnil;
|
492
|
-
|
493
|
-
if (model == NULL) {
|
494
|
-
rb_raise(rb_eIOError, "Failed to load file '%s'", filename_);
|
495
|
-
return Qnil;
|
496
|
-
}
|
497
|
-
|
498
|
-
if (model) {
|
499
|
-
param_hash = parameter_to_rb_hash(&(model->param));
|
500
|
-
model_hash = model_to_rb_hash(model);
|
501
|
-
free_and_destroy_model(&model);
|
502
|
-
}
|
503
|
-
|
504
|
-
rb_ary_store(res, 0, param_hash);
|
505
|
-
rb_ary_store(res, 1, model_hash);
|
506
|
-
|
507
|
-
RB_GC_GUARD(filename);
|
508
|
-
|
509
|
-
return res;
|
510
|
-
}
|
511
|
-
|
512
|
-
/**
|
513
|
-
* Save the parameters and model as a text file with LIBLINEAR format. The saved file can be used with the liblinear tools.
|
514
|
-
* Note that the save_model saves only the parameters necessary for estimation with the trained model.
|
515
|
-
*
|
516
|
-
* @overload save_model(filename, param, model) -> Boolean
|
517
|
-
* @param filename [String] The path to a file to save.
|
518
|
-
* @param param [Hash] The parameters of the trained model.
|
519
|
-
* @param model [Hash] The model obtained from the training procedure.
|
520
|
-
*
|
521
|
-
* @raise [IOError] This error raises when failed to save the model file.
|
522
|
-
* @return [Boolean] true on success, or false if an error occurs.
|
523
|
-
*/
|
524
|
-
static
|
525
|
-
VALUE numo_liblinear_save_model(VALUE self, VALUE filename, VALUE param_hash, VALUE model_hash)
|
526
|
-
{
|
527
|
-
char* filename_ = StringValuePtr(filename);
|
528
|
-
struct parameter* param = rb_hash_to_parameter(param_hash);
|
529
|
-
struct model* model = rb_hash_to_model(model_hash);
|
530
|
-
int res;
|
531
|
-
|
532
|
-
model->param = *param;
|
533
|
-
res = save_model(filename_, model);
|
534
|
-
|
535
|
-
xfree_model(model);
|
536
|
-
xfree_parameter(param);
|
537
|
-
|
538
|
-
if (res < 0) {
|
539
|
-
rb_raise(rb_eIOError, "Failed to save file '%s'", filename_);
|
540
|
-
return Qfalse;
|
541
|
-
}
|
542
|
-
|
543
|
-
RB_GC_GUARD(filename);
|
544
|
-
|
545
|
-
return Qtrue;
|
546
|
-
}
|
547
|
-
|
548
|
-
void Init_liblinearext()
|
549
|
-
{
|
550
|
-
rb_require("numo/narray");
|
551
|
-
|
552
|
-
/**
|
553
|
-
* Document-module: Numo
|
554
|
-
* Numo is the top level namespace of NUmerical MOdules for Ruby.
|
555
|
-
*/
|
556
|
-
mNumo = rb_define_module("Numo");
|
557
|
-
|
558
|
-
/**
|
559
|
-
* Document-module: Numo::Liblinear
|
560
|
-
* Numo::Liblinear is a binding library for LIBLINEAR that handles dataset with Numo::NArray.
|
561
|
-
*/
|
562
|
-
mLiblinear = rb_define_module_under(mNumo, "Liblinear");
|
563
|
-
|
564
|
-
/* The version of LIBLINEAR used in backgroud library. */
|
565
|
-
rb_define_const(mLiblinear, "LIBLINEAR_VERSION", INT2NUM(LIBLINEAR_VERSION));
|
566
|
-
|
567
|
-
rb_define_module_function(mLiblinear, "train", numo_liblinear_train, 3);
|
568
|
-
rb_define_module_function(mLiblinear, "cv", numo_liblinear_cross_validation, 4);
|
569
|
-
rb_define_module_function(mLiblinear, "predict", numo_liblinear_predict, 3);
|
570
|
-
rb_define_module_function(mLiblinear, "decision_function", numo_liblinear_decision_function, 3);
|
571
|
-
rb_define_module_function(mLiblinear, "predict_proba", numo_liblinear_predict_proba, 3);
|
572
|
-
rb_define_module_function(mLiblinear, "load_model", numo_liblinear_load_model, 1);
|
573
|
-
rb_define_module_function(mLiblinear, "save_model", numo_liblinear_save_model, 3);
|
574
|
-
|
575
|
-
rb_init_solver_type_module();
|
576
|
-
}
|
@@ -1,17 +0,0 @@
|
|
1
|
-
#ifndef NUMO_LIBLINEAREXT_H
|
2
|
-
#define NUMO_LIBLINEAREXT_H 1
|
3
|
-
|
4
|
-
#include <math.h>
|
5
|
-
#include <string.h>
|
6
|
-
#include <linear.h>
|
7
|
-
#include <ruby.h>
|
8
|
-
#include <numo/narray.h>
|
9
|
-
#include <numo/template.h>
|
10
|
-
|
11
|
-
#include "converter.h"
|
12
|
-
#include "parameter.h"
|
13
|
-
#include "model.h"
|
14
|
-
#include "problem.h"
|
15
|
-
#include "solver_type.h"
|
16
|
-
|
17
|
-
#endif /* NUMO_LIBLINEAREXT_H */
|
data/ext/numo/liblinear/model.c
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
#include "model.h"
|
2
|
-
|
3
|
-
struct model* rb_hash_to_model(VALUE model_hash)
|
4
|
-
{
|
5
|
-
VALUE el;
|
6
|
-
struct model* model = ALLOC(struct model);
|
7
|
-
el = rb_hash_aref(model_hash, ID2SYM(rb_intern("nr_class")));
|
8
|
-
model->nr_class = el != Qnil ? NUM2INT(el) : 0;
|
9
|
-
el = rb_hash_aref(model_hash, ID2SYM(rb_intern("nr_feature")));
|
10
|
-
model->nr_feature = el != Qnil ? NUM2INT(el) : 0;
|
11
|
-
el = rb_hash_aref(model_hash, ID2SYM(rb_intern("w")));
|
12
|
-
model->w = nary_to_dbl_vec(el);
|
13
|
-
el = rb_hash_aref(model_hash, ID2SYM(rb_intern("label")));
|
14
|
-
model->label = nary_to_int_vec(el);
|
15
|
-
el = rb_hash_aref(model_hash, ID2SYM(rb_intern("bias")));
|
16
|
-
model->bias = NUM2DBL(el);
|
17
|
-
el = rb_hash_aref(model_hash, ID2SYM(rb_intern("rho")));
|
18
|
-
model->rho = NUM2DBL(el);
|
19
|
-
return model;
|
20
|
-
}
|
21
|
-
|
22
|
-
VALUE model_to_rb_hash(struct model* const model)
|
23
|
-
{
|
24
|
-
int const n_cols = model->nr_class > 2 ? model->nr_class : 1;
|
25
|
-
int const n_rows = model->nr_feature;
|
26
|
-
VALUE model_hash = rb_hash_new();
|
27
|
-
rb_hash_aset(model_hash, ID2SYM(rb_intern("nr_class")), INT2NUM(model->nr_class));
|
28
|
-
rb_hash_aset(model_hash, ID2SYM(rb_intern("nr_feature")), INT2NUM(model->nr_feature));
|
29
|
-
rb_hash_aset(model_hash, ID2SYM(rb_intern("w")),
|
30
|
-
model->w ? dbl_vec_to_nary(model->w, n_rows * n_cols) : Qnil);
|
31
|
-
rb_hash_aset(model_hash, ID2SYM(rb_intern("label")),
|
32
|
-
model->label ? int_vec_to_nary(model->label, model->nr_class) : Qnil);
|
33
|
-
rb_hash_aset(model_hash, ID2SYM(rb_intern("bias")), DBL2NUM(model->bias));
|
34
|
-
rb_hash_aset(model_hash, ID2SYM(rb_intern("rho")), DBL2NUM(model->rho));
|
35
|
-
return model_hash;
|
36
|
-
}
|
37
|
-
|
38
|
-
void xfree_model(struct model* model)
|
39
|
-
{
|
40
|
-
if (model) {
|
41
|
-
xfree(model->w);
|
42
|
-
model->w = NULL;
|
43
|
-
xfree(model->label);
|
44
|
-
model->label = NULL;
|
45
|
-
xfree(model);
|
46
|
-
model = NULL;
|
47
|
-
}
|
48
|
-
}
|
data/ext/numo/liblinear/model.h
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#ifndef NUMO_LIBLINEAR_MODEL_H
|
2
|
-
#define NUMO_LIBLINEAR_MODEL_H 1
|
3
|
-
|
4
|
-
#include <linear.h>
|
5
|
-
#include <ruby.h>
|
6
|
-
#include <numo/narray.h>
|
7
|
-
#include <numo/template.h>
|
8
|
-
|
9
|
-
#include "converter.h"
|
10
|
-
|
11
|
-
struct model* rb_hash_to_model(VALUE model_hash);
|
12
|
-
VALUE model_to_rb_hash(struct model* const model);
|
13
|
-
void xfree_model(struct model* model);
|
14
|
-
|
15
|
-
#endif /* NUMO_LIBLINEAR_MODEL_H */
|