hexgnu-libsvm-ruby-swig 0.1.1 → 0.1.2

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/lib/hex-svm.rb CHANGED
@@ -1,7 +1,7 @@
1
- require File.join(File.dirname(__FILE__), 'libsvm')
1
+ require File.join(File.dirname(__FILE__), '../ext/libsvm')
2
2
  include Libsvm
3
3
 
4
- %w[./libsvm/problem ./libsvm/model ./libsvm/parameter].each do |r|
4
+ %w[libsvm/problem libsvm/model libsvm/parameter].each do |r|
5
5
  require File.join(File.dirname(__FILE__), r)
6
6
  end
7
7
 
@@ -0,0 +1,140 @@
1
+ module SVM
2
+ class Model
3
+ attr_accessor :model
4
+
5
+ def initialize(arg1,arg2=nil)
6
+ if arg2 == nil
7
+ # create model from file
8
+ filename = arg1
9
+ @model = svm_load_model(filename)
10
+ else
11
+ # create model from problem and parameter
12
+ prob,param = arg1,arg2
13
+ @prob = prob
14
+ if param.gamma == 0
15
+ param.gamma = 1.0/prob.maxlen
16
+ end
17
+ msg = svm_check_parameter(prob.prob,param.param)
18
+ raise ::ArgumentError, msg if msg
19
+ @model = svm_train(prob.prob,param.param)
20
+ end
21
+
22
+ #setup some classwide variables
23
+ @nr_class = svm_get_nr_class(@model)
24
+ @svm_type = svm_get_svm_type(@model)
25
+ #create labels(classes)
26
+ intarr = new_int(@nr_class)
27
+ svm_get_labels(@model,intarr)
28
+ @labels = _int_array_to_list(intarr, @nr_class)
29
+ delete_int(intarr)
30
+ #check if valid probability model
31
+ @probability = svm_check_probability_model(@model)
32
+
33
+ end
34
+
35
+ def predict(x)
36
+ data = SVM.convert_to_svm_node_array(x)
37
+ ret = svm_predict(@model,data)
38
+ svm_node_array_destroy(data)
39
+ return ret
40
+ end
41
+
42
+
43
+ def get_nr_class
44
+ return @nr_class
45
+ end
46
+
47
+ def get_labels
48
+ if @svm_type == NU_SVR or @svm_type == EPSILON_SVR or @svm_type == ONE_CLASS
49
+ raise TypeError, "Unable to get label from a SVR/ONE_CLASS model"
50
+ end
51
+ return @labels
52
+ end
53
+
54
+ def predict_values_raw(x)
55
+ #convert x into svm_node, allocate a double array for return
56
+ n = (@nr_class*(@nr_class-1)/2).floor
57
+ data = _convert_to_svm_node_array(x)
58
+ dblarr = new_double(n)
59
+ svm_predict_values(@model, data, dblarr)
60
+ ret = _double_array_to_list(dblarr, n)
61
+ delete_double(dblarr)
62
+ svm_node_array_destroy(data)
63
+ return ret
64
+ end
65
+
66
+ def predict_values(x)
67
+ v=predict_values_raw(x)
68
+ #puts v.inspect
69
+ if @svm_type == NU_SVR or @svm_type == EPSILON_SVR or @svm_type == ONE_CLASS
70
+ return v[0]
71
+ else #self.svm_type == C_SVC or self.svm_type == NU_SVC
72
+ count = 0
73
+
74
+ # create a width x height array
75
+ width = @labels.size
76
+ height = @labels.size
77
+ d = Array.new(width)
78
+ d.map! { Array.new(height) }
79
+
80
+ for i in (0..@labels.size-1)
81
+ for j in (i+1..@labels.size-1)
82
+ d[@labels[i]][@labels[j]] = v[count]
83
+ d[@labels[j]][@labels[i]] = -v[count]
84
+ count += 1
85
+ end
86
+ end
87
+ return d
88
+ end
89
+ end
90
+
91
+ def predict_probability(x)
92
+ #c code will do nothing on wrong type, so we have to check ourself
93
+ if @svm_type == NU_SVR or @svm_type == EPSILON_SVR
94
+ raise TypeError, "call get_svr_probability or get_svr_pdf for probability output of regression"
95
+ elsif @svm_type == ONE_CLASS
96
+ raise TypeError, "probability not supported yet for one-class problem"
97
+ end
98
+ #only C_SVC,NU_SVC goes in
99
+ if not @probability
100
+ raise TypeError, "model does not support probabiliy estimates"
101
+ end
102
+
103
+ #convert x into svm_node, alloc a double array to receive probabilities
104
+ data = _convert_to_svm_node_array(x)
105
+ dblarr = new_double(@nr_class)
106
+ pred = svm_predict_probability(@model, data, dblarr)
107
+ pv = _double_array_to_list(dblarr, @nr_class)
108
+ delete_double(dblarr)
109
+ svm_node_array_destroy(data)
110
+ p = {}
111
+ for i in (0..@labels.size-1)
112
+ p[@labels[i]] = pv[i]
113
+ end
114
+ return pred, p
115
+ end
116
+
117
+ def get_svr_probability
118
+ #leave the Error checking to svm.cpp code
119
+ ret = svm_get_svr_probability(@model)
120
+ if ret == 0
121
+ raise TypeError, "not a regression model or probability information not available"
122
+ end
123
+ return ret
124
+ end
125
+
126
+ def get_svr_pdf
127
+ #get_svr_probability will handle error checking
128
+ sigma = get_svr_probability()
129
+ return Proc.new{|z| exp(-z.abs/sigma)/(2*sigma)} # TODO: verify this works
130
+ end
131
+
132
+ def save(filename)
133
+ svm_save_model(filename,@model)
134
+ end
135
+
136
+ def destroy
137
+ svm_destroy_model(@model)
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,56 @@
1
+ module SVM
2
+ class Parameter
3
+ attr_accessor :param
4
+
5
+ def initialize(*args)
6
+ @param = Svm_parameter.new
7
+ @param.svm_type = C_SVC
8
+ @param.kernel_type = RBF
9
+ @param.degree = 3
10
+ @param.gamma = 0 # 1/k
11
+ @param.coef0 = 0
12
+ @param.nu = 0.5
13
+ @param.cache_size = 100
14
+ @param.C = 1
15
+ @param.eps = 1e-3
16
+ @param.p = 0.1
17
+ @param.shrinking = 1
18
+ @param.nr_weight = 0
19
+ #@param.weight_label = _int_array([])
20
+ #@param.weight = _double_array([])
21
+ @param.probability = 0
22
+
23
+ args[0].each {|k,v|
24
+ self.send("#{k}=",v)
25
+ } if !args[0].nil?
26
+ end
27
+
28
+ def method_missing(m, *args)
29
+ if m.to_s == 'weight_label='
30
+ @weight_label_len = args[0].size
31
+ pargs = _int_array(args[0])
32
+ _free_int_array(@param.weight_label)
33
+ elsif m.to_s == 'weight='
34
+ @weight_len = args[0].size
35
+ pargs = _double_array(args[0])
36
+ _free_double_array(@param.weight)
37
+ else
38
+ pargs = args[0]
39
+ end
40
+
41
+ if m.to_s.index('=')
42
+ @param.send("#{m}",pargs)
43
+ else
44
+ @param.send("#{m}")
45
+ end
46
+
47
+ end
48
+
49
+ def destroy
50
+ _free_int_array(@param.weight_label)
51
+ _free_double_array(@param.weight)
52
+ #delete_svm_parameter(@param)
53
+ @param = nil
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ module SVM
2
+ class Problem
3
+ attr_accessor :prob, :maxlen, :size
4
+
5
+ def initialize(y, *x)
6
+ #assert y.size == x.size
7
+ @prob = prob = Svm_problem.new
8
+ @size = size = y.size
9
+
10
+ @y_array = y_array = new_double(size)
11
+ y.each_with_index do |label, i|
12
+ double_setitem(@y_array, i, label)
13
+ end
14
+
15
+ @x_matrix = x_matrix = svm_node_matrix(size)
16
+ @data = []
17
+ @maxlen = 0
18
+ x.each_with_index do |row, i|
19
+ #data = _convert_to_svm_node_array(row)
20
+ data = SVM.convert_to_svm_node_array(row)
21
+ @data << data
22
+ svm_node_matrix_set(x_matrix, i, data)
23
+ @maxlen = [@maxlen, row.size].max
24
+ end
25
+
26
+ prob.l = size
27
+ prob.y = y_array
28
+ prob.x = x_matrix
29
+ end
30
+
31
+ def inspect
32
+ return "Problem: size = #{size}"
33
+ end
34
+
35
+ def destroy
36
+ delete_svm_problem(@prob)
37
+ delete_double(@y_array)
38
+ for i in (0..size-1)
39
+ svm_node_array_destroy(@data[i])
40
+ end
41
+ svm_node_matrix_destroy(@x_matrix)
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexgnu-libsvm-ruby-swig
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tom Zeng
@@ -53,6 +53,9 @@ files:
53
53
  - README.rdoc
54
54
  - Rakefile
55
55
  - lib/hex-svm.rb
56
+ - lib/libsvm/model.rb
57
+ - lib/libsvm/parameter.rb
58
+ - lib/libsvm/problem.rb
56
59
  - ext/libsvm_wrap.cxx
57
60
  - ext/svm.cpp
58
61
  - ext/svm.h