malife-libsvm-ruby-swig 0.3.3

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.
@@ -0,0 +1,76 @@
1
+ #ifndef _LIBSVM_H
2
+ #define _LIBSVM_H
3
+
4
+ #define LIBSVM_VERSION 289
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ extern int libsvm_version;
11
+
12
+ struct svm_node
13
+ {
14
+ int index;
15
+ double value;
16
+ };
17
+
18
+ struct svm_problem
19
+ {
20
+ int l;
21
+ double *y;
22
+ struct svm_node **x;
23
+ };
24
+
25
+ enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR }; /* svm_type */
26
+ enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED }; /* kernel_type */
27
+
28
+ struct svm_parameter
29
+ {
30
+ int svm_type;
31
+ int kernel_type;
32
+ int degree; /* for poly */
33
+ double gamma; /* for poly/rbf/sigmoid */
34
+ double coef0; /* for poly/sigmoid */
35
+
36
+ /* these are for training only */
37
+ double cache_size; /* in MB */
38
+ double eps; /* stopping criteria */
39
+ double C; /* for C_SVC, EPSILON_SVR and NU_SVR */
40
+ int nr_weight; /* for C_SVC */
41
+ int *weight_label; /* for C_SVC */
42
+ double* weight; /* for C_SVC */
43
+ double nu; /* for NU_SVC, ONE_CLASS, and NU_SVR */
44
+ double p; /* for EPSILON_SVR */
45
+ int shrinking; /* use the shrinking heuristics */
46
+ int probability; /* do probability estimates */
47
+ };
48
+
49
+ struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);
50
+ void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter *param, int nr_fold, double *target);
51
+
52
+ int svm_save_model(const char *model_file_name, const struct svm_model *model);
53
+ struct svm_model *svm_load_model(const char *model_file_name);
54
+
55
+ int svm_get_svm_type(const struct svm_model *model);
56
+ int svm_get_nr_class(const struct svm_model *model);
57
+ void svm_get_labels(const struct svm_model *model, int *label);
58
+ double svm_get_svr_probability(const struct svm_model *model);
59
+
60
+ void svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values);
61
+ double svm_predict(const struct svm_model *model, const struct svm_node *x);
62
+ double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);
63
+
64
+ void svm_destroy_model(struct svm_model *model);
65
+ void svm_destroy_param(struct svm_parameter *param);
66
+
67
+ const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param);
68
+ int svm_check_probability_model(const struct svm_model *model);
69
+
70
+ extern void (*svm_print_string) (const char *);
71
+
72
+ #ifdef __cplusplus
73
+ }
74
+ #endif
75
+
76
+ #endif /* _LIBSVM_H */
@@ -0,0 +1,356 @@
1
+ require 'libsvm'
2
+ include Libsvm
3
+
4
+ def _int_array(seq)
5
+ size = seq.size
6
+ array = new_int(size)
7
+ i = 0
8
+ for item in seq
9
+ int_setitem(array,i,item)
10
+ i = i + 1
11
+ end
12
+ return array
13
+ end
14
+
15
+ def _double_array(seq)
16
+ size = seq.size
17
+ array = new_double(size)
18
+ i = 0
19
+ for item in seq
20
+ double_setitem(array,i,item)
21
+ i = i + 1
22
+ end
23
+ return array
24
+ end
25
+
26
+ def _free_int_array(x)
27
+ if !x.nil? and !x.empty?
28
+ delete_int(x)
29
+ end
30
+ end
31
+
32
+ def _free_double_array(x)
33
+ if !x.nil? and !x.empty?
34
+ delete_double(x)
35
+ end
36
+ end
37
+
38
+ def _int_array_to_list(x,n)
39
+ list = []
40
+ (0..n-1).each {|i| list << int_getitem(x,i) }
41
+ return list
42
+ end
43
+
44
+ def _double_array_to_list(x,n)
45
+ list = []
46
+ (0..n-1).each {|i| list << double_getitem(x,i) }
47
+ return list
48
+ end
49
+
50
+ class Parameter
51
+ attr_accessor :param
52
+
53
+ def initialize(*args)
54
+ @param = Svm_parameter.new
55
+ @param.svm_type = C_SVC
56
+ @param.kernel_type = RBF
57
+ @param.degree = 3
58
+ @param.gamma = 0 # 1/k
59
+ @param.coef0 = 0
60
+ @param.nu = 0.5
61
+ @param.cache_size = 100
62
+ @param.C = 1
63
+ @param.eps = 1e-3
64
+ @param.p = 0.1
65
+ @param.shrinking = 1
66
+ @param.nr_weight = 0
67
+ #@param.weight_label = _int_array([])
68
+ #@param.weight = _double_array([])
69
+ @param.probability = 0
70
+
71
+ args[0].each {|k,v|
72
+ self.send("#{k}=",v)
73
+ } if !args[0].nil?
74
+ end
75
+
76
+ def method_missing(m, *args)
77
+ if m.to_s == 'weight_label='
78
+ @weight_label_len = args[0].size
79
+ pargs = _int_array(args[0])
80
+ _free_int_array(@param.weight_label)
81
+ elsif m.to_s == 'weight='
82
+ @weight_len = args[0].size
83
+ pargs = _double_array(args[0])
84
+ _free_double_array(@param.weight)
85
+ else
86
+ pargs = args[0]
87
+ end
88
+
89
+ if m.to_s.index('=')
90
+ @param.send("#{m}",pargs)
91
+ else
92
+ @param.send("#{m}")
93
+ end
94
+
95
+ end
96
+
97
+ def destroy
98
+ _free_int_array(@param.weight_label)
99
+ _free_double_array(@param.weight)
100
+ #delete_svm_parameter(@param)
101
+ @param = nil
102
+ end
103
+ end
104
+
105
+ def _convert_to_svm_node_array(x)
106
+ # convert a hash or array to an svm_node array
107
+
108
+ # Find non zero elements
109
+ iter_range = []
110
+ if x.class == Hash
111
+ x.each {|k, v|
112
+ # all zeros kept due to the precomputed kernel; no good solution yet
113
+ iter_range << k # if v != 0
114
+ }
115
+ elsif x.class == Array
116
+ x.each_index {|j|
117
+ iter_range << j #if x[j] != 0
118
+ }
119
+ else
120
+ raise TypeError,"data must be a hash or an array"
121
+ end
122
+
123
+ iter_range.sort!
124
+ data = svm_node_array(iter_range.size+1)
125
+ svm_node_array_set(data,iter_range.size,-1,0)
126
+
127
+ j = 0
128
+ for k in iter_range
129
+ svm_node_array_set(data,j,k,x[k])
130
+ j = j + 1
131
+ end
132
+ return data
133
+ end
134
+
135
+ class Problem
136
+ attr_accessor :prob, :maxlen, :size
137
+
138
+ def initialize(y,x)
139
+ #assert y.size == x.size
140
+ @prob = prob = Svm_problem.new
141
+ @size = size = y.size
142
+
143
+ @y_array = y_array = new_double(size)
144
+ for i in (0..size-1)
145
+ double_setitem(@y_array,i,y[i])
146
+ end
147
+
148
+ @x_matrix = x_matrix = svm_node_matrix(size)
149
+ @data = []
150
+ @maxlen = 0
151
+ for i in (0..size-1)
152
+ data = _convert_to_svm_node_array(x[i])
153
+ @data << data
154
+ svm_node_matrix_set(x_matrix,i,data)
155
+ if x[i].class == Hash
156
+ if x[i].size > 0
157
+ @maxlen = [@maxlen,x[i].keys.max].max
158
+ end
159
+ else
160
+ @maxlen = [@maxlen,x[i].size].max
161
+ end
162
+ end
163
+
164
+ prob.l = size
165
+ prob.y = y_array
166
+ prob.x = x_matrix
167
+ end
168
+
169
+ def inspect
170
+ return "Problem: size = #{size}"
171
+ end
172
+
173
+ def destroy
174
+ delete_svm_problem(@prob)
175
+ delete_double(@y_array)
176
+ for i in (0..size-1)
177
+ svm_node_array_destroy(@data[i])
178
+ end
179
+ svm_node_matrix_destroy(@x_matrix)
180
+ end
181
+ end
182
+
183
+ class Model
184
+ attr_accessor :model
185
+
186
+ def initialize(arg1,arg2=nil)
187
+ if arg2 == nil
188
+ # create model from file
189
+ filename = arg1
190
+ @model = svm_load_model(filename)
191
+ else
192
+ # create model from problem and parameter
193
+ prob,param = arg1,arg2
194
+ @prob = prob
195
+ if param.gamma == 0
196
+ param.gamma = 1.0/prob.maxlen
197
+ end
198
+ msg = svm_check_parameter(prob.prob,param.param)
199
+ raise ::ArgumentError, msg if msg
200
+ @model = svm_train(prob.prob,param.param)
201
+ end
202
+
203
+ #setup some classwide variables
204
+ @nr_class = svm_get_nr_class(@model)
205
+ @svm_type = svm_get_svm_type(@model)
206
+ #create labels(classes)
207
+ intarr = new_int(@nr_class)
208
+ svm_get_labels(@model,intarr)
209
+ @labels = _int_array_to_list(intarr, @nr_class)
210
+ delete_int(intarr)
211
+ #check if valid probability model
212
+ @probability = svm_check_probability_model(@model)
213
+
214
+ end
215
+
216
+ def predict(x)
217
+ data = _convert_to_svm_node_array(x)
218
+ ret = svm_predict(@model,data)
219
+ svm_node_array_destroy(data)
220
+ return ret
221
+ end
222
+
223
+
224
+ def get_nr_class
225
+ return @nr_class
226
+ end
227
+
228
+ def get_labels
229
+ if @svm_type == NU_SVR or @svm_type == EPSILON_SVR or @svm_type == ONE_CLASS
230
+ raise TypeError, "Unable to get label from a SVR/ONE_CLASS model"
231
+ end
232
+ return @labels
233
+ end
234
+
235
+ def predict_values_raw(x)
236
+ #convert x into svm_node, allocate a double array for return
237
+ n = (@nr_class*(@nr_class-1)/2).floor
238
+ data = _convert_to_svm_node_array(x)
239
+ dblarr = new_double(n)
240
+ svm_predict_values(@model, data, dblarr)
241
+ ret = _double_array_to_list(dblarr, n)
242
+ delete_double(dblarr)
243
+ svm_node_array_destroy(data)
244
+ return ret
245
+ end
246
+
247
+ def predict_values(x)
248
+ v=predict_values_raw(x)
249
+ #puts v.inspect
250
+ if @svm_type == NU_SVR or @svm_type == EPSILON_SVR or @svm_type == ONE_CLASS
251
+ return v[0]
252
+ else #self.svm_type == C_SVC or self.svm_type == NU_SVC
253
+ count = 0
254
+
255
+ # create a width x height array
256
+ width = @labels.size
257
+ height = @labels.size
258
+ d = Array.new(width)
259
+ d.map! { Array.new(height) }
260
+
261
+ for i in (0..@labels.size-1)
262
+ for j in (i+1..@labels.size-1)
263
+ d[@labels[i]][@labels[j]] = v[count]
264
+ d[@labels[j]][@labels[i]] = -v[count]
265
+ count += 1
266
+ end
267
+ end
268
+ return d
269
+ end
270
+ end
271
+
272
+ def predict_probability(x)
273
+ #c code will do nothing on wrong type, so we have to check ourself
274
+ if @svm_type == NU_SVR or @svm_type == EPSILON_SVR
275
+ raise TypeError, "call get_svr_probability or get_svr_pdf for probability output of regression"
276
+ elsif @svm_type == ONE_CLASS
277
+ raise TypeError, "probability not supported yet for one-class problem"
278
+ end
279
+ #only C_SVC,NU_SVC goes in
280
+ if not @probability
281
+ raise TypeError, "model does not support probabiliy estimates"
282
+ end
283
+
284
+ #convert x into svm_node, alloc a double array to receive probabilities
285
+ data = _convert_to_svm_node_array(x)
286
+ dblarr = new_double(@nr_class)
287
+ pred = svm_predict_probability(@model, data, dblarr)
288
+ pv = _double_array_to_list(dblarr, @nr_class)
289
+ delete_double(dblarr)
290
+ svm_node_array_destroy(data)
291
+ p = {}
292
+ for i in (0..@labels.size-1)
293
+ p[@labels[i]] = pv[i]
294
+ end
295
+ return pred, p
296
+ end
297
+
298
+ def get_svr_probability
299
+ #leave the Error checking to svm.cpp code
300
+ ret = svm_get_svr_probability(@model)
301
+ if ret == 0
302
+ raise TypeError, "not a regression model or probability information not available"
303
+ end
304
+ return ret
305
+ end
306
+
307
+ def get_svr_pdf
308
+ #get_svr_probability will handle error checking
309
+ sigma = get_svr_probability()
310
+ return Proc.new{|z| exp(-z.abs/sigma)/(2*sigma)} # TODO: verify this works
311
+ end
312
+
313
+ def save(filename)
314
+ svm_save_model(filename,@model)
315
+ end
316
+
317
+ def destroy
318
+ svm_destroy_model(@model)
319
+ end
320
+ end
321
+
322
+
323
+ def cross_validation(prob, param, fold)
324
+ if param.gamma == 0
325
+ param.gamma = 1.0/prob.maxlen
326
+ end
327
+ dblarr = new_double(prob.size)
328
+ svm_cross_validation(prob.prob, param.param, fold, dblarr)
329
+ ret = _double_array_to_list(dblarr, prob.size)
330
+ delete_double(dblarr)
331
+ return ret
332
+ end
333
+
334
+ def read_file filename
335
+ labels = []
336
+ samples = []
337
+ max_index = 0
338
+
339
+ f = File.open(filename)
340
+ f.each do |line|
341
+ elems = line.split
342
+ sample = {}
343
+ for e in elems[1..-1]
344
+ points = e.split(":")
345
+ sample[points[0].to_i] = points[1].to_f
346
+ if points[0].to_i < max_index
347
+ max_index = points[0].to_i
348
+ end
349
+ end
350
+ labels << elems[0].to_i
351
+ samples << sample
352
+ end
353
+ puts "#{filename}: #{samples.size} samples loaded."
354
+ return labels,samples
355
+ end
356
+
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: malife-libsvm-ruby-swig
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.3
5
+ platform: ruby
6
+ authors:
7
+ - Tom Zeng
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-08 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.3.3
24
+ version:
25
+ description: Ruby wrapper of LIBSVM using SWIG
26
+ email:
27
+ - tom.z.zeng@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ files:
36
+ - History.txt
37
+ - COPYING
38
+ - AUTHORS
39
+ - Manifest.txt
40
+ - README.rdoc
41
+ - Rakefile
42
+ - lib/svm.rb
43
+ - ext/libsvm_wrap.cxx
44
+ - ext/svm.cpp
45
+ - ext/svm.h
46
+ - ext/extconf.rb
47
+ - ext/Makefile
48
+ has_rdoc: false
49
+ homepage: http://www.tomzconsulting.com
50
+ licenses:
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --main
54
+ - README.rdoc
55
+ require_paths:
56
+ - lib
57
+ - ext
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: This is the Ruby port of the LIBSVM Python SWIG (Simplified Wrapper and Interface Generator) interface
77
+ test_files: []
78
+