libsvmffi 0.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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2011 by Robert Berry
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,37 @@
1
+ == Introduction
2
+
3
+ This is alpha grade software.
4
+
5
+ Under development. But simple use cases may be worth checking out.
6
+
7
+ http://www.csie.ntu.edu.tw/~cjlin/libsvm/
8
+
9
+ libsvm version 310
10
+
11
+
12
+ == Installation
13
+
14
+ 1. download (see url above)
15
+ 2. make lib
16
+ 3. place .so in load path
17
+
18
+ gem install libsvmffi
19
+
20
+ == Usage
21
+
22
+ #> require 'libsvmffi'
23
+
24
+ #> m = Libsvmffi::Model.new
25
+ #> m.add :good, {:height => 1, :width => 1, :length => 1}
26
+ #> m.add :bad, {:height => 10, :width => 3, :length => 6}
27
+ #> m.train
28
+
29
+ #> m.classify({:height => 1, :width => 1.1, :length => 1})
30
+ #=> :good
31
+
32
+
33
+ == Source Code
34
+
35
+ https://github.com/bdigital/libsvmffi
36
+
37
+ Assistance developing is welcome.
@@ -0,0 +1,156 @@
1
+ module Libsvmffi
2
+ #
3
+ #
4
+ #
5
+ class Model
6
+
7
+ attr_accessor :parameters, :problem, :svm_model
8
+ attr_accessor :examples
9
+ attr_accessor :labels, :features
10
+ attr_accessor :elements, :x_space
11
+
12
+ attr_accessor :nodes, :x
13
+
14
+ def initialize(options = {})
15
+
16
+ @parameters = Parameters.new
17
+
18
+ # TODO merge defaults options hash.
19
+ @parameters[:svm_type] = C_SVC;
20
+ @parameters[:kernel_type] = RBF;
21
+ @parameters[:degree] = 3;
22
+ @parameters[:gamma] = 0; # 1/num_features
23
+ @parameters[:coef0] = 0;
24
+ @parameters[:nu] = 0.5;
25
+ @parameters[:cache_size] = 100;
26
+ @parameters[:C] = 1;
27
+ @parameters[:eps] = 0.001;
28
+ @parameters[:p] = 0.1;
29
+ @parameters[:shrinking] = 1;
30
+ @parameters[:probability] = 0;
31
+ @parameters[:nr_weight] = 0;
32
+ @parameters[:weight_label] = nil;
33
+ @parameters[:weight] = nil;
34
+
35
+ @elements = 0
36
+ @examples, @labels, @features = [], [], []
37
+
38
+ @nodes = []
39
+ end
40
+
41
+ #
42
+ # Adds an example which will be used upon trainining
43
+ #
44
+ def add(label, features)
45
+ @labels.push label unless @labels.include? label
46
+ indexed_features = {}
47
+ features.each do |k, v|
48
+ @features.push k unless @features.include? k
49
+ indexed_features[@features.index(k)] = v
50
+ end
51
+
52
+ @examples.push({@labels.index(label) => indexed_features})
53
+
54
+ @elements += features.length + 1 # also -1 terminator, see libsvm readme.
55
+ end
56
+
57
+ #
58
+ # Build libsvm model
59
+ #
60
+ def train
61
+
62
+ @problem = Problem.new
63
+ @problem[:l] = @examples.length
64
+ @problem[:y] = FFI::MemoryPointer.new(:double, @problem[:l])
65
+ @x = FFI::MemoryPointer.new(:pointer, @problem[:l])
66
+ @problem[:x] = x.address #FFI::MemoryPointer.new(:pointer, @problem[:l])
67
+ @x_space = FFI::MemoryPointer.new(Node, @elements)
68
+
69
+ y = @examples.map {|e| e.keys.first}
70
+ @problem[:y].put_array_of_double 0, y
71
+
72
+ i = 0
73
+ space_index = 0
74
+ examples.each do |ex| #TODO clean up this hash structure
75
+ ex.each do |e|
76
+ @x[i].write_pointer @x_space[space_index]
77
+ i += 1
78
+
79
+ features = e.last.merge({-1 => 0}) #terminator
80
+ features.each do |k, v|
81
+ n = Node.new @x_space[space_index]
82
+ n[:index] = k
83
+ n[:value] = v
84
+ space_index += 1
85
+
86
+ @nodes.push n
87
+ end
88
+ end
89
+ end
90
+
91
+ @parameters[:gamma] = 1 / @features.length.to_f
92
+
93
+ @svm_model = Libsvmffi.svm_train @problem.pointer, @parameters.pointer
94
+
95
+ end
96
+
97
+ #
98
+ #
99
+ #
100
+ def classify(features)
101
+ nodes = fton(features)
102
+ label_index = Libsvmffi.svm_predict @svm_model, nodes
103
+ @labels[label_index.to_i]
104
+ end
105
+
106
+
107
+ #
108
+ # Save to file
109
+ #
110
+ def save(filename = "model.out")
111
+ Libsvmffi.svm_save_model FFI::MemoryPointer.from_string(filename), @svm_model
112
+ end
113
+
114
+ #
115
+ # Add training examples from a libsvm training format file
116
+ #
117
+ def add_from_file(filename)
118
+ f = File.open filename, 'r'
119
+ f.lines.each do |l|
120
+ tokens = l.split " "
121
+ label = tokens.shift
122
+ features = {}
123
+ tokens.each do |t|
124
+ index, value = t.split(":")
125
+ features[index.to_i] = value.to_f
126
+ end
127
+ self.add label, features
128
+ end
129
+ end
130
+
131
+ #
132
+ # Features to array of node struct (currently factored just for debugging, only used in predict)
133
+ #
134
+ def fton(features)
135
+
136
+ indexed_features = {}
137
+ features.each do |k, v|
138
+ indexed_features[@features.index(k)] = v unless !@features.include? k
139
+ end
140
+
141
+ nodes = FFI::MemoryPointer.new(Node, indexed_features.length + 1)
142
+ indexed_features = indexed_features.merge({-1 => 0}) #terminator
143
+ i = 0
144
+ indexed_features.each do |k, v|
145
+ n = Node.new nodes[i]
146
+ n[:index] = k
147
+ n[:value] = v
148
+ i += 1
149
+ end
150
+
151
+ return nodes
152
+
153
+ end
154
+
155
+ end
156
+ end
@@ -0,0 +1,6 @@
1
+ module Libsvmffi
2
+ class Node < FFI::Struct
3
+ layout :index, :int,
4
+ :value, :double
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ module Libsvmffi
2
+ class Parameters < FFI::Struct
3
+ layout :svm_type, :int,
4
+ :kernel_type, :int,
5
+ :degree, :int, # for poly
6
+ :gamma, :double, # for poly/rbf/sigmoid
7
+ :coef0, :double, # for poly/sigmoid
8
+ :cache_size, :double , # in MB
9
+ :eps, :double, # stopping criteria
10
+ :C, :double, # for C_SVC, EPSILON_SVR and NU_SVR
11
+ :nr_weight, :int, # for C_SVC
12
+ :weight_label, :pointer, # int for C_SVC
13
+ :weight, :pointer, # double for C_SVC
14
+ :nu, :double, # for NU_SVC, ONE_CLASS, and NU_SVR
15
+ :p, :double, # for EPSILON_SVR
16
+ :shrinking, :int, # use the shrinking heuristics
17
+ :probability, :int # do probability estimates
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Libsvmffi
2
+ class Problem < FFI::Struct
3
+ layout :l, :int,
4
+ :y, :pointer,
5
+ :x, :pointer # svm_node
6
+ end
7
+ end
data/lib/libsvmffi.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'ffi'
2
+ require 'libsvmffi/problem'
3
+ require 'libsvmffi/parameters'
4
+ require 'libsvmffi/node'
5
+ require 'libsvmffi/model'
6
+
7
+
8
+ module Libsvmffi
9
+
10
+ extend FFI::Library
11
+ ffi_lib 'svm' # REVIEW
12
+
13
+ C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR = 0, 1, 2, 3, 4 # SVM Type
14
+ LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED = 0, 1, 2, 3, 4 # Kernel Type
15
+
16
+ attach_function 'svm_train', [:pointer, :pointer], :pointer
17
+
18
+ attach_function 'svm_cross_validation', [:pointer, :pointer, :int, :pointer], :void
19
+
20
+ attach_function 'svm_save_model', [:pointer, :pointer], :int
21
+ attach_function 'svm_load_model', [:pointer], :pointer
22
+
23
+ attach_function 'svm_get_svm_type', [:pointer], :int
24
+ attach_function 'svm_get_nr_class', [:pointer], :int
25
+ attach_function 'svm_get_labels', [:pointer, :pointer], :void
26
+ attach_function 'svm_get_svr_probability', [:pointer], :double
27
+
28
+ attach_function 'svm_predict', [:pointer, :pointer], :double
29
+ attach_function 'svm_predict_values', [:pointer, :pointer, :pointer], :void
30
+ attach_function 'svm_predict_probability', [:pointer, :pointer, :pointer], :double
31
+
32
+ attach_function 'svm_free_and_destroy_model', [:pointer], :void
33
+ attach_function 'svm_destroy_param', [:pointer], :void
34
+
35
+ attach_function 'svm_check_parameter', [:pointer, :pointer], :pointer
36
+ attach_function 'svm_check_probability_model', [:pointer], :int
37
+
38
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libsvmffi
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Robert Berry
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-01 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: SVM operations.
17
+ email: berrydigital@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/libsvmffi.rb
26
+ - lib/libsvmffi/problem.rb
27
+ - lib/libsvmffi/node.rb
28
+ - lib/libsvmffi/parameters.rb
29
+ - lib/libsvmffi/model.rb
30
+ - README
31
+ - LICENSE
32
+ homepage: http://github.com/bdigital/libsvmffi
33
+ licenses: []
34
+
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ requirements: []
53
+
54
+ rubyforge_project:
55
+ rubygems_version: 1.7.2
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Libsvm ffi bindings
59
+ test_files: []
60
+
61
+ has_rdoc: false