rb-libsvm 1.0.11 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/Gemfile +3 -0
- data/README.md +6 -3
- data/TODO.md +14 -0
- data/ext/libsvm/libsvm.c +47 -31
- data/lib/libsvm/version.rb +1 -1
- data/spec/model_spec.rb +8 -0
- metadata +3 -8
data/.gitignore
CHANGED
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# rb-libsvm -- Ruby language bindings for LIBSVM
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rb-libsvm.png)](http://badge.fury.io/rb/rb-libsvm)
|
3
4
|
[![Build Status](https://secure.travis-ci.org/febeling/rb-libsvm.png)](http://travis-ci.org/febeling/rb-libsvm)
|
4
5
|
|
5
6
|
This package provides a Ruby bindings to the [LIBSVM][] library. SVM
|
@@ -17,10 +18,10 @@ LIBSVM includes a number of command line tools for preprocessing
|
|
17
18
|
training data and finding parameters. These tools are not included in
|
18
19
|
this gem. You should install the original package if you need them.
|
19
20
|
|
20
|
-
It is helpful to consult the
|
21
|
+
It is helpful to consult the [README][] of the LIBSVM package for
|
21
22
|
reference when configuring the training parameters.
|
22
23
|
|
23
|
-
Currently this package includes libsvm version 3.
|
24
|
+
Currently this package includes libsvm version 3.14.
|
24
25
|
|
25
26
|
## Dependencies
|
26
27
|
|
@@ -83,8 +84,8 @@ Written by C. Florian Ebeling.
|
|
83
84
|
## Contributors
|
84
85
|
|
85
86
|
[Rimas Silkaitis](https://github.com/neovintage)
|
86
|
-
|
87
87
|
[Aleksander Pohl](https://github.com/apohllo)
|
88
|
+
[Andreas Eger](https://github.com/sch1zo)
|
88
89
|
|
89
90
|
## License
|
90
91
|
|
@@ -105,3 +106,5 @@ http://www.igvita.com/2008/01/07/support-vector-machines-svm-in-ruby/
|
|
105
106
|
[svmrubyswig]: http://github.com/tomz/libsvm-ruby-swig/tree/master
|
106
107
|
|
107
108
|
[ruby-svm]: http://sourceforge.net/projects/rubysvm/
|
109
|
+
|
110
|
+
[README]: https://github.com/febeling/libsvm/blob/master/README
|
data/TODO.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# TODO
|
2
|
+
|
3
|
+
These functions from the library are not bound as ruby methods:
|
4
|
+
|
5
|
+
`void svm_get_labels(const struct svm_model *model, int *label);`
|
6
|
+
|
7
|
+
`double svm_get_svr_probability(const struct svm_model *model);`
|
8
|
+
|
9
|
+
`void svm_destroy_param(struct svm_parameter *param);`
|
10
|
+
|
11
|
+
The model holds reference to the parameters struct, so it's not
|
12
|
+
obvious when it's safe to use.
|
13
|
+
|
14
|
+
`int svm_check_probability_model(const struct svm_model *model);`
|
data/ext/libsvm/libsvm.c
CHANGED
@@ -22,7 +22,7 @@ static void model_free(struct svm_model *model) {
|
|
22
22
|
/* Libsvm::Node */
|
23
23
|
static struct svm_node *node_new() {
|
24
24
|
struct svm_node *n;
|
25
|
-
n =
|
25
|
+
n = calloc(1,sizeof(struct svm_node));
|
26
26
|
if(n == NULL)
|
27
27
|
return NULL;
|
28
28
|
return n;
|
@@ -47,7 +47,7 @@ rx_def_accessor(cNode,struct svm_node,double,value);
|
|
47
47
|
/* Libsvm::Problem */
|
48
48
|
static struct svm_problem *problem_new() {
|
49
49
|
struct svm_problem *n;
|
50
|
-
n =
|
50
|
+
n = calloc(1,sizeof(struct svm_problem));
|
51
51
|
if(n == NULL)
|
52
52
|
return NULL;
|
53
53
|
return n;
|
@@ -81,7 +81,7 @@ static struct svm_node *example_to_internal(VALUE example_ary)
|
|
81
81
|
|
82
82
|
/* allocate memory for it */
|
83
83
|
example_ary_len = rx_ary_size(example_ary);
|
84
|
-
x =
|
84
|
+
x = calloc(example_ary_len+1,sizeof(struct svm_node));
|
85
85
|
if(x == 0) {
|
86
86
|
rb_raise(rb_eNoMemError, "on Libsvm::Node allocation" " %s:%i", __FILE__,__LINE__);
|
87
87
|
}
|
@@ -100,13 +100,12 @@ static struct svm_node *example_to_internal(VALUE example_ary)
|
|
100
100
|
static struct svm_node **examples_ary_to_internal(VALUE examples_ary)
|
101
101
|
{
|
102
102
|
struct svm_node **x;
|
103
|
-
|
104
|
-
|
105
|
-
int nodes_ary_len, i;
|
103
|
+
VALUE nodes_ary;
|
104
|
+
int i;
|
106
105
|
|
107
106
|
int num = rx_ary_size(examples_ary);
|
108
107
|
|
109
|
-
x =
|
108
|
+
x = calloc(num,sizeof(struct svm_node *));
|
110
109
|
if(x == 0) {
|
111
110
|
rb_raise(rb_eNoMemError, "%s:%i", __FILE__,__LINE__);
|
112
111
|
}
|
@@ -133,10 +132,7 @@ static struct svm_node **examples_ary_to_internal(VALUE examples_ary)
|
|
133
132
|
static VALUE cProblem_examples_set(VALUE obj,VALUE labels_ary,VALUE examples_ary)
|
134
133
|
{
|
135
134
|
struct svm_problem *prob;
|
136
|
-
|
137
|
-
/* VALUE num;*/
|
138
|
-
int i, nodes_ary_len;
|
139
|
-
VALUE label, node, nodes_ary;
|
135
|
+
int i;
|
140
136
|
|
141
137
|
int num = rx_ary_size(labels_ary);
|
142
138
|
|
@@ -154,7 +150,7 @@ static VALUE cProblem_examples_set(VALUE obj,VALUE labels_ary,VALUE examples_ary
|
|
154
150
|
free(prob->x);
|
155
151
|
}
|
156
152
|
|
157
|
-
prob->y =
|
153
|
+
prob->y = calloc(num,sizeof(double));
|
158
154
|
if(prob->y == 0) {
|
159
155
|
rb_raise(rb_eNoMemError, "%s:%i", __FILE__,__LINE__);
|
160
156
|
}
|
@@ -182,14 +178,14 @@ static VALUE cProblem_examples(VALUE problem) {
|
|
182
178
|
double label;
|
183
179
|
struct svm_node *features;
|
184
180
|
VALUE labels_ary, examples_ary, example_ary, v_node, result;
|
185
|
-
int i
|
181
|
+
int i;
|
186
182
|
|
187
183
|
Data_Get_Struct(problem, struct svm_problem, prob);
|
188
184
|
|
189
185
|
labels_ary = rb_ary_new2(prob->l);
|
190
186
|
examples_ary = rb_ary_new2(prob->l);
|
191
187
|
|
192
|
-
features =
|
188
|
+
features = calloc(prob->l, sizeof(struct svm_node));
|
193
189
|
if(features == 0) {
|
194
190
|
rb_raise(rb_eNoMemError, "on allocating Libsvm::Node" " %s:%i", __FILE__,__LINE__);
|
195
191
|
}
|
@@ -201,7 +197,7 @@ static VALUE cProblem_examples(VALUE problem) {
|
|
201
197
|
node = *(prob->x+i); /* example start pointer */
|
202
198
|
example_ary = rb_ary_new();
|
203
199
|
while(node->index != -1) {
|
204
|
-
node_copy =
|
200
|
+
node_copy = malloc(sizeof(struct svm_node));
|
205
201
|
if(node_copy == 0) {
|
206
202
|
rb_raise(rb_eNoMemError, "on allocating Libsvm::Node" " %s:%i", __FILE__,__LINE__);
|
207
203
|
}
|
@@ -224,7 +220,7 @@ static VALUE cProblem_examples(VALUE problem) {
|
|
224
220
|
|
225
221
|
static struct svm_parameter *parameter_new() {
|
226
222
|
struct svm_parameter *n;
|
227
|
-
n =
|
223
|
+
n = calloc(1,sizeof(struct svm_parameter));
|
228
224
|
if(n == NULL)
|
229
225
|
return NULL;
|
230
226
|
return n;
|
@@ -270,8 +266,7 @@ rx_def_accessor_as(cSvmParameter,struct svm_parameter,double,C,c);
|
|
270
266
|
*/
|
271
267
|
static VALUE cSvmParameter_label_weights_set(VALUE obj,VALUE weight_hash) {
|
272
268
|
struct svm_parameter *param;
|
273
|
-
int i
|
274
|
-
double weight;
|
269
|
+
int i;
|
275
270
|
VALUE keys,key,val;
|
276
271
|
|
277
272
|
Data_Get_Struct(obj,struct svm_parameter,param);
|
@@ -282,8 +277,8 @@ static VALUE cSvmParameter_label_weights_set(VALUE obj,VALUE weight_hash) {
|
|
282
277
|
}
|
283
278
|
|
284
279
|
param->nr_weight = rx_hash_size(weight_hash);
|
285
|
-
param->weight =
|
286
|
-
param->weight_label =
|
280
|
+
param->weight = calloc(param->nr_weight,sizeof(double));
|
281
|
+
param->weight_label = calloc(param->nr_weight,sizeof(int));
|
287
282
|
|
288
283
|
keys = rb_funcall(weight_hash, rb_intern("keys"),0);
|
289
284
|
|
@@ -353,6 +348,36 @@ static VALUE cModel_predict(VALUE obj,VALUE example) {
|
|
353
348
|
return rb_float_new(class);
|
354
349
|
}
|
355
350
|
|
351
|
+
static VALUE cModel_predict_probability(VALUE obj,VALUE example) {
|
352
|
+
struct svm_node *x;
|
353
|
+
struct svm_model *model;
|
354
|
+
double class;
|
355
|
+
double *c_estimates;
|
356
|
+
VALUE estimates;
|
357
|
+
VALUE target;
|
358
|
+
int i;
|
359
|
+
|
360
|
+
x = example_to_internal(example);
|
361
|
+
Data_Get_Struct(obj, struct svm_model, model);
|
362
|
+
c_estimates = calloc(model->nr_class, sizeof(double));
|
363
|
+
if(c_estimates == 0) {
|
364
|
+
rb_raise(rb_eNoMemError, "on predict probability estimates allocation" " %s:%i", __FILE__,__LINE__);
|
365
|
+
}
|
366
|
+
|
367
|
+
class = svm_predict_probability(model, x, c_estimates);
|
368
|
+
|
369
|
+
estimates = rb_ary_new();
|
370
|
+
for (i = 0; i < model->nr_class; i++)
|
371
|
+
rb_ary_push(estimates, rx_from_double(c_estimates[i]));
|
372
|
+
|
373
|
+
free(c_estimates);
|
374
|
+
|
375
|
+
target = rb_ary_new();
|
376
|
+
rb_ary_push(target, rb_float_new(class));
|
377
|
+
rb_ary_push(target, estimates);
|
378
|
+
return target;
|
379
|
+
}
|
380
|
+
|
356
381
|
static VALUE cModel_save(VALUE obj, VALUE filename)
|
357
382
|
{
|
358
383
|
const struct svm_model *model;
|
@@ -406,7 +431,7 @@ static VALUE cModel_class_cross_validation(VALUE cls, VALUE problem, VALUE param
|
|
406
431
|
nr_fold = NUM2INT(num_fold);
|
407
432
|
|
408
433
|
target = rb_ary_new2(prob->l);
|
409
|
-
target_ptr =
|
434
|
+
target_ptr = calloc(prob->l, sizeof(double));
|
410
435
|
if(target_ptr == 0) {
|
411
436
|
rb_raise(rb_eNoMemError, "on cross-validation result allocation" " %s:%i", __FILE__,__LINE__);
|
412
437
|
}
|
@@ -466,16 +491,7 @@ void Init_libsvm_ext() {
|
|
466
491
|
rb_define_method(cModel, "svm_type", cModel_svm_type, 0);
|
467
492
|
rb_define_method(cModel, "classes", cModel_classes, 0);
|
468
493
|
rb_define_method(cModel, "predict", cModel_predict, 1);
|
469
|
-
|
470
|
-
/*
|
471
|
-
Not covered, for various reasons:
|
472
|
-
TODO - void svm_get_labels(const struct svm_model *model, int *label);
|
473
|
-
SVR? - double svm_get_svr_probability(const struct svm_model *model);
|
474
|
-
SVR? - double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);
|
475
|
-
Model holds reference to this, so when to use it?
|
476
|
-
void svm_destroy_param(struct svm_parameter *param);
|
477
|
-
SVR? - int svm_check_probability_model(const struct svm_model *model);
|
478
|
-
*/
|
494
|
+
rb_define_method(cModel, "predict_probability", cModel_predict_probability, 1);
|
479
495
|
|
480
496
|
mKernelType = rb_define_module_under(mLibsvm, "KernelType");
|
481
497
|
rb_define_const(mKernelType, "LINEAR", INT2NUM(LINEAR));
|
data/lib/libsvm/version.rb
CHANGED
data/spec/model_spec.rb
CHANGED
@@ -21,6 +21,7 @@ module ModelSpecHelper
|
|
21
21
|
parameter.cache_size = 50 # mb
|
22
22
|
parameter.eps = 0.01
|
23
23
|
parameter.c = 10
|
24
|
+
parameter.probability = 1
|
24
25
|
parameter
|
25
26
|
end
|
26
27
|
|
@@ -92,4 +93,11 @@ describe "An Libsvm model" do
|
|
92
93
|
prediction = @model.predict(create_example)
|
93
94
|
prediction.should_not be_nil
|
94
95
|
end
|
96
|
+
|
97
|
+
it "can predict probability" do
|
98
|
+
prediction, probabilities = @model.predict_probability(create_example)
|
99
|
+
prediction.should_not be_nil
|
100
|
+
probabilities.should have(@model.classes).items
|
101
|
+
probabilities.each { |e| e.should_not be_nil }
|
102
|
+
end
|
95
103
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb-libsvm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake-compiler
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- MIT-LICENSE
|
62
62
|
- README.md
|
63
63
|
- Rakefile
|
64
|
+
- TODO.md
|
64
65
|
- examples/text.rb
|
65
66
|
- examples/toy.rb
|
66
67
|
- ext/libsvm/extconf.rb
|
@@ -90,18 +91,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
91
|
- - ! '>='
|
91
92
|
- !ruby/object:Gem::Version
|
92
93
|
version: '0'
|
93
|
-
segments:
|
94
|
-
- 0
|
95
|
-
hash: 859207920834715629
|
96
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
95
|
none: false
|
98
96
|
requirements:
|
99
97
|
- - ! '>='
|
100
98
|
- !ruby/object:Gem::Version
|
101
99
|
version: '0'
|
102
|
-
segments:
|
103
|
-
- 0
|
104
|
-
hash: 859207920834715629
|
105
100
|
requirements: []
|
106
101
|
rubyforge_project: rb-libsvm
|
107
102
|
rubygems_version: 1.8.23
|