rb-libsvm 1.1.5 → 1.2.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/.travis.yml +0 -1
- data/README.md +5 -4
- data/examples/iris.rb +61 -0
- data/ext/libsvm/extconf.rb +1 -0
- data/ext/libsvm/libsvm.c +8 -0
- data/lib/libsvm/version.rb +1 -1
- data/rb-libsvm.gemspec +3 -3
- data/spec/model_spec.rb +56 -26
- data/spec/node_spec.rb +6 -6
- data/spec/spec_helper.rb +1 -2
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 430498716ebb529469fa73ece0ffe044bac7c04a
|
4
|
+
data.tar.gz: d1effb4c07f3fa77418991d79ddf58ed5887ee8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6546735dc65a8bff5215960cec78755eab7ddd4ecffe047bd1e4a6db485bfbcb970fed54b61581b259478b0451cbcca21b936ed2bc01f3c48af32240bd0be553
|
7
|
+
data.tar.gz: 07c833fd03503d38e4b9a5c0a6ac6958e32b3ffcf8983f6ffe8663dd1914d9de9ee164f8725373d3957b9e264708783811929d49d69fce5bbfa461560d36400d
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -9,7 +9,11 @@ popular free implementation of it, written by Chih-Chung Chang and
|
|
9
9
|
Chih-Jen Lin, of National Taiwan University, Taipei. See the book ["Programming
|
10
10
|
Collective Intelligence,"](http://books.google.com/books?id=fEsZ3Ey-Hq4C) among others, for a usage example.
|
11
11
|
|
12
|
-
|
12
|
+
There is a JRuby implementation of this gem named
|
13
|
+
[jrb-libsvm](https://github.com/sch1zo/jrb-libsvm) by
|
14
|
+
[Andreas Eger](https://github.com/sch1zo).
|
15
|
+
|
16
|
+
Note: There exist some other Ruby bindings for LIBSVM. One is named
|
13
17
|
[Ruby SVM][ruby-svm], written by Rudi Cilibrasi. The other, more
|
14
18
|
actively developed one is [libsvm-ruby-swig][svmrubyswig] by Tom Zeng,
|
15
19
|
which is built using SWIG.
|
@@ -77,9 +81,6 @@ gem 'rb-libsvm', require: 'libsvm'
|
|
77
81
|
This is because the loadable name (`libsvm`) is different from the
|
78
82
|
gem's name (`rb-libsvm`).
|
79
83
|
|
80
|
-
There is a JRuby variant of this gem named
|
81
|
-
[jrb-libsvm](https://github.com/sch1zo/jrb-libsvm) by Andreas Eger.
|
82
|
-
|
83
84
|
## Author
|
84
85
|
|
85
86
|
Written by [C. Florian Ebeling](https://github.com/febeling).
|
data/examples/iris.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'libsvm'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
include Libsvm
|
5
|
+
|
6
|
+
if ARGV.size != 1
|
7
|
+
puts "Usage: ruby examples/iris.rb iris.data"
|
8
|
+
puts
|
9
|
+
puts "Needs the Iris data set"
|
10
|
+
puts " http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
# Read data
|
15
|
+
lines = IO.readlines(ARGV.shift).map(&:strip).shuffle
|
16
|
+
instances = lines.map { |line| line.split(',') }
|
17
|
+
|
18
|
+
# Create array of feature nodes per instance
|
19
|
+
examples = instances.map { |instance|
|
20
|
+
sepal_length, sepal_width, petal_length, petal_width = *instance[0..3].map(&:to_f)
|
21
|
+
Node.features(sepal_length, sepal_width, petal_length, petal_width)
|
22
|
+
}
|
23
|
+
|
24
|
+
# Pluck class property (Iris name)
|
25
|
+
label_names = instances.map(&:last)
|
26
|
+
|
27
|
+
# Deduplicate and assign indexes
|
28
|
+
label_indexes = label_names.to_set.to_a
|
29
|
+
|
30
|
+
# Array of label indexes of instances
|
31
|
+
labels = label_names.map { |label_name| label_indexes.index(label_name) }
|
32
|
+
|
33
|
+
# Create problem traning set
|
34
|
+
problem = Problem.new
|
35
|
+
problem.set_examples(labels, examples)
|
36
|
+
|
37
|
+
# Use various kernel types
|
38
|
+
[:LINEAR, :POLY, :RBF, :SIGMOID].each do |type|
|
39
|
+
|
40
|
+
# Create some parameters
|
41
|
+
parameter = SvmParameter.new
|
42
|
+
parameter.cache_size = 10 # in megabytes
|
43
|
+
parameter.eps = 0.00001
|
44
|
+
parameter.degree = 5
|
45
|
+
parameter.gamma = 0.01
|
46
|
+
parameter.c = 100
|
47
|
+
parameter.kernel_type = KernelType.const_get(type)
|
48
|
+
|
49
|
+
# Different nfold sizes. It's the number of parts the data is
|
50
|
+
# split into.
|
51
|
+
[10, 20].each do |nfold|
|
52
|
+
result = Model.cross_validation(problem, parameter, nfold)
|
53
|
+
predicted_name = result.map { |label| label_indexes[label] }
|
54
|
+
correctness = predicted_name.map.with_index { |p, i| p == label_names[i] }
|
55
|
+
|
56
|
+
correct = correctness.select { |x| x }
|
57
|
+
accuracy = correct.size.to_f / correctness.size
|
58
|
+
acc_str = "%.2f" % accuracy
|
59
|
+
puts "Accuracy[type = #{type}, nfold = #{nfold}] : #{acc_str}"
|
60
|
+
end
|
61
|
+
end
|
data/ext/libsvm/extconf.rb
CHANGED
data/ext/libsvm/libsvm.c
CHANGED
@@ -411,6 +411,13 @@ static VALUE cModel_classes(VALUE obj)
|
|
411
411
|
return INT2NUM(svm_get_nr_class(model));
|
412
412
|
}
|
413
413
|
|
414
|
+
static VALUE cModel_support_vectors(VALUE obj)
|
415
|
+
{
|
416
|
+
const struct svm_model *model;
|
417
|
+
Data_Get_Struct(obj, struct svm_model, model);
|
418
|
+
return INT2NUM(svm_get_nr_sv(model));
|
419
|
+
}
|
420
|
+
|
414
421
|
static VALUE cModel_class_load(VALUE cls, VALUE filename)
|
415
422
|
{
|
416
423
|
struct svm_model *model;
|
@@ -493,6 +500,7 @@ void Init_libsvm_ext() {
|
|
493
500
|
rb_define_method(cModel, "save", cModel_save, 1);
|
494
501
|
rb_define_method(cModel, "svm_type", cModel_svm_type, 0);
|
495
502
|
rb_define_method(cModel, "classes", cModel_classes, 0);
|
503
|
+
rb_define_method(cModel, "support_vectors", cModel_support_vectors, 0);
|
496
504
|
rb_define_method(cModel, "predict", cModel_predict, 1);
|
497
505
|
rb_define_method(cModel, "predict_probability", cModel_predict_probability, 1);
|
498
506
|
|
data/lib/libsvm/version.rb
CHANGED
data/rb-libsvm.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["C. Florian Ebeling", "Rimas Silkaitis"]
|
9
9
|
s.email = ["florian.ebeling@gmail.com", "neovintage@gmail.com"]
|
10
10
|
s.homepage = "https://github.com/febeling/rb-libsvm"
|
11
|
-
s.summary = %q{Ruby
|
12
|
-
s.description = %q{
|
11
|
+
s.summary = %q{Ruby bindings for LIBSVM}
|
12
|
+
s.description = %q{Self-contained LIBSVM package for Ruby (that doesn't use SWIG). LIBSVM is a popular implementation of SVM, a machine learning classifier.}
|
13
13
|
s.required_ruby_version = '>= 1.8.7'
|
14
14
|
|
15
15
|
s.rubyforge_project = "rb-libsvm"
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
22
|
s.add_development_dependency('rake-compiler')
|
23
|
-
s.add_development_dependency('rspec', '>=
|
23
|
+
s.add_development_dependency('rspec', '>= 3.0.0')
|
24
24
|
|
25
25
|
s.extensions << 'ext/libsvm/extconf.rb'
|
26
26
|
end
|
data/spec/model_spec.rb
CHANGED
@@ -9,9 +9,9 @@ module ModelSpecHelper
|
|
9
9
|
def create_problem
|
10
10
|
problem = Problem.new
|
11
11
|
features = [Node.features([0.2,0.3,0.4,0.4]),
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
Node.features([0.1,0.5,0.1,0.9]),
|
13
|
+
Node.features([0.2,0.2,0.6,0.5]),
|
14
|
+
Node.features([0.3,0.1,0.5,0.9])]
|
15
15
|
problem.set_examples([1,2,1,2], features)
|
16
16
|
problem
|
17
17
|
end
|
@@ -39,13 +39,21 @@ describe "The Libsvm::Model class interface" do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
it "results from training on a problem under a certain parameter set" do
|
42
|
-
|
43
|
-
model.should_not be_nil
|
42
|
+
expect(Model.train(@problem, @parameter)).not_to be_nil
|
44
43
|
end
|
45
44
|
|
45
|
+
let(:labels) { Model.cross_validation(@problem, @parameter, fold=2) }
|
46
|
+
|
46
47
|
it "can do cross-validation" do
|
47
|
-
labels
|
48
|
-
|
48
|
+
expect(labels).to contain_exactly(
|
49
|
+
an_instance_of(Float),
|
50
|
+
an_instance_of(Float),
|
51
|
+
an_instance_of(Float),
|
52
|
+
an_instance_of(Float))
|
53
|
+
end
|
54
|
+
|
55
|
+
it "number of labels" do
|
56
|
+
expect(labels.length).to eq(4)
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
@@ -59,8 +67,7 @@ describe "A saved model" do
|
|
59
67
|
end
|
60
68
|
|
61
69
|
it "can be loaded" do
|
62
|
-
|
63
|
-
model.should_not be_nil
|
70
|
+
expect(Model.load(@filename)).to be_an_instance_of(Model)
|
64
71
|
end
|
65
72
|
|
66
73
|
after(:each) do
|
@@ -68,7 +75,7 @@ describe "A saved model" do
|
|
68
75
|
end
|
69
76
|
end
|
70
77
|
|
71
|
-
describe "
|
78
|
+
describe "A Libsvm model" do
|
72
79
|
include ModelSpecHelper
|
73
80
|
|
74
81
|
before(:each) do
|
@@ -79,28 +86,51 @@ describe "An Libsvm model" do
|
|
79
86
|
File.delete(@file_path) if File.exists?(@file_path)
|
80
87
|
end
|
81
88
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
describe "basic operations" do
|
90
|
+
it "can be saved to a file" do
|
91
|
+
expect {
|
92
|
+
@model.save(@file_path)
|
93
|
+
}.to change { File.exist?(@file_path) }.from(false).to(true)
|
94
|
+
end
|
86
95
|
|
87
|
-
|
88
|
-
|
96
|
+
it "can be asked for its svm_type" do
|
97
|
+
expect(@model.svm_type).to eq SvmType::C_SVC
|
98
|
+
end
|
99
|
+
|
100
|
+
it "can be asked for its number of classes (aka. labels)" do
|
101
|
+
expect(@model.classes).to eq(2)
|
102
|
+
end
|
89
103
|
end
|
90
104
|
|
91
|
-
|
92
|
-
|
105
|
+
describe "predict" do
|
106
|
+
it "returns floats" do
|
107
|
+
expect(@model.predict(create_example)).to be_an_instance_of(Float)
|
108
|
+
end
|
93
109
|
end
|
94
110
|
|
95
|
-
|
96
|
-
|
97
|
-
|
111
|
+
describe "support_vectors" do
|
112
|
+
it "returns count" do
|
113
|
+
expect(@model.support_vectors).to eq(3)
|
114
|
+
end
|
98
115
|
end
|
99
116
|
|
100
|
-
|
101
|
-
|
102
|
-
prediction.
|
103
|
-
probabilities.
|
104
|
-
|
117
|
+
describe "predict_probability" do
|
118
|
+
let(:result) { @model.predict_probability(create_example) }
|
119
|
+
let(:prediction) { result.first }
|
120
|
+
let(:probabilities) { result.last }
|
121
|
+
|
122
|
+
it "produces prediction" do
|
123
|
+
expect(prediction).not_to be_nil
|
124
|
+
end
|
125
|
+
|
126
|
+
it "produces probabilities for each class" do
|
127
|
+
expect(probabilities.length).to eq(@model.classes)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "can predict probability" do
|
131
|
+
probabilities.each do |p|
|
132
|
+
expect(p).to be_an_instance_of(Float)
|
133
|
+
end
|
134
|
+
end
|
105
135
|
end
|
106
136
|
end
|
data/spec/node_spec.rb
CHANGED
@@ -5,20 +5,20 @@ describe "construction of a Node" do
|
|
5
5
|
n = Node.new
|
6
6
|
n.index = 11
|
7
7
|
n.value = 0.11
|
8
|
-
n.index.
|
9
|
-
n.value.
|
8
|
+
expect(n.index).to eq 11
|
9
|
+
expect(n.value).to be_within(0.0001).of(0.11)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "using the :[] method" do
|
13
13
|
n = Node[12, 0.12]
|
14
|
-
n.index.
|
15
|
-
n.value.
|
14
|
+
expect(n.index).to eq 12
|
15
|
+
expect(n.value).to be_within(0.00001).of(0.12)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "using the constructor parameters" do
|
19
19
|
n = Node.new(14, 0.14)
|
20
|
-
n.index.
|
21
|
-
n.value.
|
20
|
+
expect(n.index).to eq 14
|
21
|
+
expect(n.value).to be_within(0.0001).of(0.14)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/spec/spec_helper.rb
CHANGED
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.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- C. Florian Ebeling
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-11-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|
@@ -31,15 +31,16 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: 3.0.0
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
42
|
-
description:
|
41
|
+
version: 3.0.0
|
42
|
+
description: Self-contained LIBSVM package for Ruby (that doesn't use SWIG). LIBSVM
|
43
|
+
is a popular implementation of SVM, a machine learning classifier.
|
43
44
|
email:
|
44
45
|
- florian.ebeling@gmail.com
|
45
46
|
- neovintage@gmail.com
|
@@ -57,6 +58,7 @@ files:
|
|
57
58
|
- README.md
|
58
59
|
- Rakefile
|
59
60
|
- TODO.md
|
61
|
+
- examples/iris.rb
|
60
62
|
- examples/text.rb
|
61
63
|
- examples/toy.rb
|
62
64
|
- ext/libsvm/extconf.rb
|
@@ -96,7 +98,7 @@ rubyforge_project: rb-libsvm
|
|
96
98
|
rubygems_version: 2.2.2
|
97
99
|
signing_key:
|
98
100
|
specification_version: 4
|
99
|
-
summary: Ruby
|
101
|
+
summary: Ruby bindings for LIBSVM
|
100
102
|
test_files:
|
101
103
|
- spec/model_spec.rb
|
102
104
|
- spec/node_spec.rb
|
@@ -104,4 +106,3 @@ test_files:
|
|
104
106
|
- spec/problem_spec.rb
|
105
107
|
- spec/spec_helper.rb
|
106
108
|
- spec/usage_spec.rb
|
107
|
-
has_rdoc:
|