rb-libsvm 1.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ tmp/
2
+ *.bundle
3
+ *.so
4
+ *.dylib
5
+ *.model
6
+ pkg/
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@rblibsvm --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in libsvmr.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rb-libsvm (1.0.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.3)
10
+ rake (0.9.2.2)
11
+ rake-compiler (0.7.9)
12
+ rake
13
+ rspec (2.7.0)
14
+ rspec-core (~> 2.7.0)
15
+ rspec-expectations (~> 2.7.0)
16
+ rspec-mocks (~> 2.7.0)
17
+ rspec-core (2.7.1)
18
+ rspec-expectations (2.7.0)
19
+ diff-lcs (~> 1.1.2)
20
+ rspec-mocks (2.7.0)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ rake-compiler
27
+ rb-libsvm!
28
+ rspec (= 2.7.0)
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2004-2008 Caspar Florian Ebeling
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,37 @@
1
+ h1. rb-libsvm -- Ruby language bindings for LIBSVM
2
+
3
+ This is a module which provides a Ruby API to the LIBSVM [1] library.
4
+ SVM is a machine learning and classification algorithm, and LIBSVM is
5
+ a popular free implementation of it, written by Chih-Chung Chang and
6
+ Chih-Jen Lin, of National Taiwan University, Taipei. See "Programming
7
+ Collective Intelligence," [2] among others, for a usage example.
8
+
9
+ Note: There exists another Ruby binding for LIBSVM, named Ruby SVM,
10
+ [3] written by Rudi Cilibrasi. (That's the one mentioned in the
11
+ libsvm documentation.) This package is not related but written
12
+ independently and from scratch.
13
+
14
+ h2. Dependencies
15
+
16
+ None. Libsvm is bundled with the project. Just clone and go!
17
+
18
+ Currently using libsvm version 3.1
19
+
20
+ h2. Author, License
21
+
22
+ Written by C. Florian Ebeling. This software can be freely used under
23
+ the terms of the MIT license, see file MIT-LICENSE.
24
+
25
+ h2. Contributors
26
+
27
+ Rimas Silkaitis
28
+
29
+ h3. Notes
30
+
31
+ fn1. http://www.csie.ntu.edu.tw/~cjlin/libsvm/
32
+
33
+ fn2. http://books.google.com/books?id=fEsZ3Ey-Hq4C
34
+
35
+ fn3. http://rubysvm.cilibrar.com/
36
+
37
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/extensiontask"
3
+ require 'rspec/core/rake_task'
4
+
5
+ Rake::ExtensionTask.new('rb-libsvm') do |ext|
6
+ ext.lib_dir = File.join('lib', 'rb-libsvm')
7
+ ext.name = 'libsvm'
8
+ end
9
+
10
+ RSpec::Core::RakeTask.new('spec')
11
+ Rake::Task[:spec].prerequisites << :clean
12
+ Rake::Task[:spec].prerequisites << :compile
13
+
@@ -0,0 +1,46 @@
1
+ require 'mkmf'
2
+
3
+ # $CFLAGS << " -save-temps -ggdb3 "
4
+ # $LDFLAGS << " -lstdc++ "
5
+
6
+ # find_header('ruby.h')
7
+ # find_library('svm', 'svm_train', '/opt/local/lib/', '/usr/lib/') || raise("svm library not found.")
8
+ # find_header('svm.h', "/opt/local/include/", "/usr/include/libsvm-2.0/libsvm/")
9
+ # create_makefile('libsvm_ext')
10
+
11
+ LIBDIR = Config::CONFIG['libdir']
12
+ INCLUDEDIR = Config::CONFIG['includedir']
13
+
14
+ HEADER_DIRS = [
15
+ # First search /opt/local for macports
16
+ '/opt/local/include',
17
+
18
+ # Then search /usr/local for people that installed from source
19
+ '/usr/local/include',
20
+
21
+ # Check the ruby install locations
22
+ INCLUDEDIR,
23
+
24
+ # Finally fall back to /usr
25
+ '/usr/include',
26
+ ]
27
+
28
+ LIB_DIRS = [
29
+ # First search /opt/local for macports
30
+ '/opt/local/lib',
31
+
32
+ # Then search /usr/local for people that installed from source
33
+ '/usr/local/lib',
34
+
35
+ # Check the ruby install locations
36
+ LIBDIR,
37
+
38
+ # Finally fall back to /usr
39
+ '/usr/lib',
40
+ ]
41
+
42
+ dir_config('rb-libsvm',HEADER_DIRS,LIB_DIRS)
43
+
44
+ # Don't think I need to search the dirs for the header file
45
+
46
+ create_makefile('rb-libsvm/libsvm')
@@ -0,0 +1,489 @@
1
+ #include "ruby.h"
2
+ #include "svm.h"
3
+ #include "ruby-ext.h"
4
+ #include <string.h>
5
+
6
+ VALUE mLibsvm;
7
+
8
+ VALUE cNode;
9
+ VALUE cProblem;
10
+ VALUE cSvmParameter;
11
+ VALUE cModel;
12
+
13
+ VALUE mKernelType;
14
+ VALUE mSvmType;
15
+
16
+ const struct svm_node TERMINATOR = (struct svm_node) { -1, 0.0 };
17
+
18
+ /* Libsvm::Node */
19
+ static struct svm_node *node_new() {
20
+ struct svm_node *n;
21
+ n = (struct svm_node *) calloc(1,sizeof(struct svm_node));
22
+ if(n == NULL)
23
+ return NULL;
24
+ return n;
25
+ }
26
+
27
+ static void node_free(struct svm_node *n) {
28
+ free(n);
29
+ }
30
+
31
+ static VALUE node_alloc(VALUE cls) {
32
+ struct svm_node *n;
33
+ n = node_new();
34
+ if(n == NULL)
35
+ rb_raise(rb_eNoMemError, "Not enough memory for allocating Node.");
36
+
37
+ return Data_Wrap_Struct(cls, 0, node_free, n);
38
+ }
39
+
40
+ rx_def_accessor(cNode,struct svm_node,int,index);
41
+ rx_def_accessor(cNode,struct svm_node,double,value);
42
+
43
+ /* Libsvm::Problem */
44
+ static struct svm_problem *problem_new() {
45
+ struct svm_problem *n;
46
+ n = (struct svm_problem *) calloc(1,sizeof(struct svm_problem));
47
+ if(n == NULL)
48
+ return NULL;
49
+ return n;
50
+ }
51
+
52
+ static void problem_free(struct svm_problem *n) {
53
+ /*
54
+ Deliberate no-op, because of this note from the README:
55
+
56
+ `*NOTE* Because svm_model contains pointers to svm_problem, you can
57
+ not free the memory used by svm_problem if you are still using the
58
+ svm_model produced by svm_train().'
59
+ */
60
+ }
61
+
62
+ static VALUE problem_alloc(VALUE cls) {
63
+ struct svm_problem *n;
64
+ n = problem_new();
65
+ if(n == NULL)
66
+ rb_raise(rb_eNoMemError, "Not enough memory for allocating Libsvm::Problem.");
67
+ return Data_Wrap_Struct(cls, 0, problem_free, n);
68
+ }
69
+
70
+ rx_def_accessor(cProblem,struct svm_problem,int,l);
71
+
72
+ static struct svm_node *example_to_internal(VALUE example_ary)
73
+ {
74
+ struct svm_node *x, *node_struct;
75
+ int example_ary_len, j;
76
+ VALUE node;
77
+
78
+ /* allocate memory for it */
79
+ example_ary_len = rx_ary_size(example_ary);
80
+ x = (struct svm_node *)calloc(example_ary_len+1,sizeof(struct svm_node));
81
+ if(x == 0) {
82
+ rb_raise(rb_eNoMemError, "on Libsvm::Node allocation" " %s:%i", __FILE__,__LINE__);
83
+ }
84
+ /* loop it's element nodes */
85
+ for(j = 0; j < example_ary_len; ++j) {
86
+ node = rb_ary_entry(example_ary,j);
87
+ Data_Get_Struct(node,struct svm_node,node_struct);
88
+ memcpy(x+j,node_struct,sizeof(struct svm_node));
89
+ }
90
+ /* add terminator */
91
+ memcpy(x+example_ary_len,&TERMINATOR,sizeof(struct svm_node));
92
+
93
+ return x;
94
+ }
95
+
96
+ static struct svm_node **examples_ary_to_internal(VALUE examples_ary)
97
+ {
98
+ struct svm_node **x;
99
+ struct svm_node *node_struct;
100
+ VALUE nodes_ary, node;
101
+ int nodes_ary_len, i;
102
+
103
+ int num = rx_ary_size(examples_ary);
104
+
105
+ x = (struct svm_node **)calloc(num,sizeof(struct svm_node *));
106
+ if(x == 0) {
107
+ rb_raise(rb_eNoMemError, "%s:%i", __FILE__,__LINE__);
108
+ }
109
+
110
+ for(i = 0; i < num; ++i) {
111
+ nodes_ary = rb_ary_entry(examples_ary,i);
112
+ *(x+i) = example_to_internal(nodes_ary);
113
+ }
114
+
115
+ return x;
116
+ }
117
+
118
+ /*
119
+ call-seq:
120
+ problem.set_examples(labels, examples_array)
121
+
122
+ double *y; // class (aka. label) of the example
123
+ struct svm_node **x; // examples
124
+
125
+ This method sets the contents of an SVM Problem, which consists
126
+ of lables (or classifications) and examples (or feature vectors).
127
+ If those 2 don't match in length and ArgumentError is raised.
128
+ */
129
+ static VALUE cProblem_examples_set(VALUE obj,VALUE labels_ary,VALUE examples_ary)
130
+ {
131
+ struct svm_problem *prob;
132
+ struct svm_node *node_struct;
133
+ /* VALUE num;*/
134
+ int i, nodes_ary_len;
135
+ VALUE label, node, nodes_ary;
136
+
137
+ int num = rx_ary_size(labels_ary);
138
+
139
+ if(num != rx_ary_size(examples_ary)) {
140
+ rb_raise(rb_eArgError, "Number of labels (%i) does not match number of features (%i).", num, rx_ary_size(examples_ary));
141
+ }
142
+
143
+ Data_Get_Struct(obj, struct svm_problem, prob);
144
+
145
+ if(prob->l > 0) {
146
+ free(prob->y);
147
+ for(i = 0; i < num; ++i) {
148
+ free(*(prob->x+i));
149
+ }
150
+ free(prob->x);
151
+ }
152
+
153
+ prob->y = (double *)calloc(num,sizeof(double));
154
+ if(prob->y == 0) {
155
+ rb_raise(rb_eNoMemError, "%s:%i", __FILE__,__LINE__);
156
+ }
157
+
158
+ for(i = 0; i < num; ++i) {
159
+ *(prob->y+i) = NUM2DBL(rb_ary_entry(labels_ary,i));
160
+ }
161
+
162
+ prob->x = examples_ary_to_internal(examples_ary);
163
+ prob->l = num;
164
+
165
+ return INT2FIX(num);
166
+ }
167
+
168
+ /*
169
+ call-seq:
170
+ labels, array_of_arrays = problem.examples
171
+
172
+ double *y; // class/label of the example
173
+ struct svm_node **x;
174
+ */
175
+ static VALUE cProblem_examples(VALUE problem) {
176
+ struct svm_problem *prob;
177
+ struct svm_node *node, *node_copy;
178
+ double label;
179
+ struct svm_node *features;
180
+ VALUE labels_ary, examples_ary, example_ary, v_node, result;
181
+ int i,n;
182
+
183
+ Data_Get_Struct(problem, struct svm_problem, prob);
184
+
185
+ labels_ary = rb_ary_new2(prob->l);
186
+ examples_ary = rb_ary_new2(prob->l);
187
+
188
+ features = (struct svm_node *)calloc(prob->l, sizeof(struct svm_node));
189
+ if(features == 0) {
190
+ rb_raise(rb_eNoMemError, "on allocating Libsvm::Node" " %s:%i", __FILE__,__LINE__);
191
+ }
192
+
193
+ for(i = 0; i < prob->l; ++i) {
194
+ label = *(prob->y+i);
195
+ rb_ary_push(labels_ary,rb_float_new(label));
196
+
197
+ node = *(prob->x+i); /* example start pointer */
198
+ example_ary = rb_ary_new();
199
+ while(node->index != -1) {
200
+ node_copy = (struct svm_node *)malloc(sizeof(struct svm_node));
201
+ if(node_copy == 0) {
202
+ rb_raise(rb_eNoMemError, "on allocating Libsvm::Node" " %s:%i", __FILE__,__LINE__);
203
+ }
204
+ memcpy(node_copy,node,sizeof(struct svm_node));
205
+ v_node = Data_Wrap_Struct(cNode,0,node_free,node_copy);
206
+ rb_ary_push(example_ary,v_node);
207
+ ++node;
208
+ }
209
+ rb_ary_push(examples_ary,example_ary);
210
+ }
211
+
212
+ result = rb_ary_new2(2);
213
+ rb_ary_push(result,labels_ary);
214
+ rb_ary_push(result,examples_ary);
215
+
216
+ return result;
217
+ }
218
+
219
+ /* SvmParameter */
220
+
221
+ static struct svm_parameter *parameter_new() {
222
+ struct svm_parameter *n;
223
+ n = (struct svm_parameter *) calloc(1,sizeof(struct svm_parameter));
224
+ if(n == NULL)
225
+ return NULL;
226
+ return n;
227
+ }
228
+
229
+ static void parameter_free(struct svm_parameter *n) {
230
+ // svm_destroy_param(n);
231
+ free(n);
232
+ }
233
+
234
+ static VALUE parameter_alloc(VALUE cls) {
235
+ struct svm_parameter *n;
236
+ n = parameter_new();
237
+ if(n == NULL)
238
+ rb_raise(rb_eNoMemError, "Not enough memory for allocating SvmParameter.");
239
+
240
+ return Data_Wrap_Struct(cls, 0, parameter_free, n);
241
+ }
242
+
243
+ rx_def_accessor(cSvmParameter,struct svm_parameter,int,svm_type)
244
+ rx_def_accessor(cSvmParameter,struct svm_parameter,int,kernel_type);
245
+ rx_def_accessor(cSvmParameter,struct svm_parameter,int,degree);
246
+ rx_def_accessor(cSvmParameter,struct svm_parameter,double,gamma);
247
+ rx_def_accessor(cSvmParameter,struct svm_parameter,double,coef0);
248
+ rx_def_accessor(cSvmParameter,struct svm_parameter,double,cache_size);
249
+ rx_def_accessor(cSvmParameter,struct svm_parameter,double,eps);
250
+ rx_def_accessor_as(cSvmParameter,struct svm_parameter,double,C,c);
251
+
252
+ /* Label weight.
253
+
254
+ nr_weight, weight_label, and weight are used to change the penalty
255
+ for some classes (If the weight for a class is not changed, it is
256
+ set to 1). This is useful for training classifier using unbalanced
257
+ input data or with asymmetric misclassification cost.
258
+
259
+ nr_weight is the number of elements in the array weight_label and
260
+ weight. Each weight[i] corresponds to weight_label[i], meaning that
261
+ the penalty of class weight_label[i] is scaled by a factor of weight[i].
262
+
263
+ If you do not want to change penalty for any of the classes,
264
+ just set nr_weight to 0.
265
+
266
+ */
267
+ static VALUE cSvmParameter_label_weights_set(VALUE obj,VALUE weight_hash) {
268
+ struct svm_parameter *param;
269
+ int i,len,weight_label;
270
+ double weight;
271
+ VALUE keys,key,val;
272
+
273
+ Data_Get_Struct(obj,struct svm_parameter,param);
274
+
275
+ if(param->nr_weight > 0) {
276
+ free(param->weight);
277
+ free(param->weight_label);
278
+ }
279
+
280
+ param->nr_weight = rx_hash_size(weight_hash);
281
+ param->weight = (double *)calloc(param->nr_weight,sizeof(double));
282
+ param->weight_label = (int *)calloc(param->nr_weight,sizeof(int));
283
+
284
+ keys = rb_funcall(weight_hash, rb_intern("keys"),0);
285
+
286
+ for(i = 0; i < param->nr_weight; ++i) {
287
+ key = rb_ary_entry(keys,i);
288
+ val = rb_hash_aref(weight_hash,key);
289
+
290
+ param->weight_label[i] = NUM2INT(key);
291
+ param->weight[i] = NUM2DBL(val);
292
+ }
293
+
294
+ return Qnil;
295
+ }
296
+
297
+ static VALUE cSvmParameter_label_weights(VALUE obj) {
298
+ struct svm_parameter *param;
299
+ int i;
300
+ VALUE hash,key,val;
301
+
302
+ Data_Get_Struct(obj,struct svm_parameter,param);
303
+
304
+ hash = rb_hash_new();
305
+
306
+ for(i = 0; i < param->nr_weight; ++i) {
307
+ key = INT2NUM(param->weight_label[i]);
308
+ val = rb_float_new(param->weight[i]);
309
+ rb_hash_aset(hash,key,val);
310
+ }
311
+
312
+ return hash;
313
+ }
314
+
315
+ rx_def_accessor(cSvmParameter,struct svm_parameter,double,nu);
316
+ rx_def_accessor(cSvmParameter,struct svm_parameter,double,p);
317
+ rx_def_accessor(cSvmParameter,struct svm_parameter,int,shrinking);
318
+ rx_def_accessor(cSvmParameter,struct svm_parameter,int,probability);
319
+
320
+ /* Libsvm::Model */
321
+
322
+ static VALUE cModel_class_train(VALUE obj,VALUE problem,VALUE parameter) {
323
+ const struct svm_problem *prob;
324
+ const struct svm_parameter *param;
325
+ struct svm_model *model;
326
+ const char *check_error;
327
+
328
+ Data_Get_Struct(problem, struct svm_problem, prob);
329
+ Data_Get_Struct(parameter, struct svm_parameter, param);
330
+
331
+ check_error = svm_check_parameter(prob, param);
332
+ if(check_error != NULL) {
333
+ rb_raise(rb_eArgError, "Parameters not valid for Problem: '%s'", check_error);
334
+ }
335
+ model = svm_train(prob,param);
336
+
337
+ return Data_Wrap_Struct(cModel, 0, svm_free_and_destroy_model, model);
338
+ }
339
+
340
+ static VALUE cModel_predict(VALUE obj,VALUE example) {
341
+ struct svm_node *x;
342
+ struct svm_model *model;
343
+ double class;
344
+
345
+ x = example_to_internal(example);
346
+ Data_Get_Struct(obj, struct svm_model, model);
347
+ class = svm_predict(model, x);
348
+
349
+ return rb_float_new(class);
350
+ }
351
+
352
+ static VALUE cModel_save(VALUE obj, VALUE filename)
353
+ {
354
+ const struct svm_model *model;
355
+ const char *path;
356
+ int rc;
357
+
358
+ Data_Get_Struct(obj, struct svm_model, model);
359
+ path = StringValueCStr(filename);
360
+
361
+ if(rc = svm_save_model(path, model)) {
362
+ rb_raise(rb_eStandardError, "Error on saving model, code: %i", rc);
363
+ }
364
+
365
+ return Qnil;
366
+ }
367
+
368
+ static VALUE cModel_svm_type(VALUE obj)
369
+ {
370
+ const struct svm_model *model;
371
+ Data_Get_Struct(obj, struct svm_model, model);
372
+ return INT2NUM(svm_get_svm_type(model));
373
+ }
374
+
375
+ static VALUE cModel_classes(VALUE obj)
376
+ {
377
+ const struct svm_model *model;
378
+ Data_Get_Struct(obj, struct svm_model, model);
379
+ return INT2NUM(svm_get_nr_class(model));
380
+ }
381
+
382
+ static VALUE cModel_class_load(VALUE cls, VALUE filename)
383
+ {
384
+ struct svm_model *model;
385
+ char *path;
386
+ path = StringValueCStr(filename);
387
+ model = svm_load_model(path);
388
+ return Data_Wrap_Struct(cModel, 0, svm_free_and_destroy_model, model);
389
+ }
390
+
391
+ static VALUE cModel_class_cross_validation(VALUE cls, VALUE problem, VALUE parameter, VALUE num_fold)
392
+ {
393
+ const struct svm_problem *prob;
394
+ const struct svm_parameter *param;
395
+ int nr_fold, i;
396
+ double *target_ptr;
397
+ VALUE target;
398
+
399
+ Data_Get_Struct(problem, struct svm_problem, prob);
400
+ Data_Get_Struct(parameter, struct svm_parameter, param);
401
+
402
+ nr_fold = NUM2INT(num_fold);
403
+
404
+ target = rb_ary_new2(prob->l);
405
+ target_ptr = (double *)calloc(prob->l, sizeof(double));
406
+ if(target_ptr == 0) {
407
+ rb_raise(rb_eNoMemError, "on cross-validation result allocation" " %s:%i", __FILE__,__LINE__);
408
+ }
409
+
410
+ svm_cross_validation(prob, param, nr_fold, target_ptr);
411
+
412
+ for(i = 0; i < prob->l; ++i) {
413
+ rb_ary_push(target, rb_float_new(*(target_ptr+i)));
414
+ }
415
+
416
+ free(target_ptr);
417
+
418
+ return target;
419
+ }
420
+
421
+ void Init_libsvm() {
422
+ mLibsvm = rb_define_module("Libsvm");
423
+
424
+ /* Libsvm::Problem */
425
+ cProblem = rb_define_class_under(mLibsvm, "Problem", rb_cObject);
426
+ rb_define_alloc_func(cProblem, problem_alloc);
427
+ rx_reg_accessor(cProblem, l);
428
+ rb_define_method(cProblem, "set_examples", cProblem_examples_set, 2);
429
+ rb_define_method(cProblem, "examples", cProblem_examples, 0);
430
+
431
+ /* Libsvm::SvmParameter */
432
+ cSvmParameter = rb_define_class_under(mLibsvm, "SvmParameter", rb_cObject);
433
+ rb_define_alloc_func(cSvmParameter, parameter_alloc);
434
+ rx_reg_accessor(cSvmParameter,svm_type);
435
+ rx_reg_accessor(cSvmParameter,kernel_type);
436
+ rx_reg_accessor(cSvmParameter,degree);
437
+ rx_reg_accessor(cSvmParameter,gamma);
438
+ rx_reg_accessor(cSvmParameter,coef0);
439
+ rx_reg_accessor(cSvmParameter,cache_size);
440
+ rx_reg_accessor(cSvmParameter,eps);
441
+ rx_reg_accessor_as(cSvmParameter,C,c);
442
+ rb_define_method(cSvmParameter,"label_weights=",cSvmParameter_label_weights_set,1);
443
+ rb_define_method(cSvmParameter,"label_weights",cSvmParameter_label_weights,0);
444
+ rx_reg_accessor(cSvmParameter,nu);
445
+ rx_reg_accessor(cSvmParameter,p);
446
+ rx_reg_accessor(cSvmParameter,shrinking);
447
+ rx_reg_accessor(cSvmParameter,probability);
448
+
449
+ /* Libsvm::Node */
450
+ cNode = rb_define_class_under(mLibsvm, "Node", rb_cObject);
451
+ rb_define_alloc_func(cNode, node_alloc);
452
+ rx_reg_accessor(cNode,index);
453
+ rx_reg_accessor(cNode,value);
454
+
455
+ /* Libsvm::Model */
456
+ cModel = rb_define_class_under(mLibsvm, "Model", rb_cObject);
457
+ // model_alloc not necessary, since we don't ever create, only wrap it.
458
+ rb_define_singleton_method(cModel, "train", cModel_class_train, 2);
459
+ rb_define_singleton_method(cModel, "cross_validation", cModel_class_cross_validation, 3);
460
+ rb_define_singleton_method(cModel, "load", cModel_class_load, 1);
461
+ rb_define_method(cModel, "save", cModel_save, 1);
462
+ rb_define_method(cModel, "svm_type", cModel_svm_type, 0);
463
+ rb_define_method(cModel, "classes", cModel_classes, 0);
464
+ rb_define_method(cModel, "predict", cModel_predict, 1);
465
+
466
+ /*
467
+ Not covered, for various reasons:
468
+ TODO - void svm_get_labels(const struct svm_model *model, int *label);
469
+ SVR? - double svm_get_svr_probability(const struct svm_model *model);
470
+ SVR? - double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);
471
+ Model holds reference to this, so when to use it?
472
+ void svm_destroy_param(struct svm_parameter *param);
473
+ SVR? - int svm_check_probability_model(const struct svm_model *model);
474
+ */
475
+
476
+ mKernelType = rb_define_module_under(mLibsvm, "KernelType");
477
+ rb_define_const(mKernelType, "LINEAR", INT2NUM(LINEAR));
478
+ rb_define_const(mKernelType, "POLY", INT2NUM(POLY));
479
+ rb_define_const(mKernelType, "RBF", INT2NUM(RBF));
480
+ rb_define_const(mKernelType, "SIGMOID", INT2NUM(SIGMOID));
481
+ rb_define_const(mKernelType, "PRECOMPUTED", INT2NUM(PRECOMPUTED));
482
+
483
+ mSvmType = rb_define_module_under(mLibsvm,"SvmType");
484
+ rb_define_const(mSvmType, "C_SVC", INT2NUM(C_SVC));
485
+ rb_define_const(mSvmType, "NU_SVC", INT2NUM(NU_SVC));
486
+ rb_define_const(mSvmType, "ONE_CLASS", INT2NUM(ONE_CLASS));
487
+ rb_define_const(mSvmType, "EPSILON_SVR", INT2NUM(EPSILON_SVR));
488
+ rb_define_const(mSvmType, "NU_SVR", INT2NUM(NU_SVR));
489
+ }