ruby_linear 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe(RubyLinear) do
5
+
6
+ # The data files are the data set from http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass.html#dna
7
+ # The model was created with train -s 5 -e 0.01 -B 1 dna.scale.txt dna.dat
8
+ # the output was created with predict dna.scale.t dna.dat dna.out
9
+
10
+ def parse_line(l)
11
+ h = {}
12
+ l.split(' ').each do |s|
13
+ if s =~ /(\d+):(\d+)/
14
+ h[$1.to_i] = $2.to_i
15
+ end
16
+ end
17
+ h
18
+ end
19
+
20
+ before(:each) do
21
+ problem = RubyLinear::Problem.load_file("spec/fixtures/dna.scale.txt",1)
22
+ @model = RubyLinear::Model.new(problem, :solver => RubyLinear::L1R_L2LOSS_SVC)
23
+ end
24
+
25
+ it 'should produce the same output as the command line tools' do
26
+ @model.should predict_values('spec/fixtures/dna.out').for_input('spec/fixtures/dna.scale.t')
27
+ end
28
+
29
+ RSpec::Matchers.define :predict_values do |output_file|
30
+ match do |model|
31
+ input_lines = File.readlines(@input)
32
+ output_lines = File.readlines(output_file)
33
+ raise "mismatched inputs" unless input_lines.length == output_lines.length
34
+ raise "input empty" if input_lines.length < 1
35
+ input_lines.each_with_index do |line, index|
36
+ sample = parse_line(line)
37
+ if (@predicted = model.predict(sample)) != (@actual = output_lines[index].to_i)
38
+ @failed_line = index + 1
39
+ break
40
+ end
41
+ end
42
+ @failed_line.nil?
43
+ end
44
+
45
+ failure_message_for_should do |actual|
46
+ "Incorrect prediction on line #{@failed_line}, expected #{@actual} got #{@predicted}"
47
+ end
48
+
49
+ chain :for_input do |input|
50
+ @input = input
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe(RubyLinear::Model) do
5
+
6
+ let :test_vector do#first line from dna.scale.t
7
+ {6 => 1, 7 => 1, 11 => 1, 18 => 1, 20 => 1, 24 => 1, 27 => 1, 30 => 1, 33 => 1, 34 => 1, 38 => 1, 42 => 1, 45 => 1, 47 => 1, 53 => 1, 60 => 1, 61 => 1, 65 => 1, 69 => 1, 70 => 1, 75 => 1, 78 => 1, 79 => 1, 84 => 1, 87 => 1, 88 => 1, 92 => 1, 99 => 1, 101 => 1, 103 => 1, 108 => 1, 110 => 1, 112 => 1, 119 => 1, 123 => 1, 124 => 1, 128 => 1, 131 => 1, 134 => 1, 137 => 1, 139 => 1, 142 => 1, 147 => 1, 149 => 1, 156 => 1, 157 => 1, 161 => 1, 164 => 1, 166 => 1, 171 => 1, 173 => 1, 180 => 1}
8
+ end
9
+
10
+ describe('load_file') do
11
+ before(:each) do
12
+ @model = RubyLinear::Model.load_file(File.dirname(__FILE__) + '/fixtures/dna.dat')
13
+ end
14
+
15
+ it 'should load the model from the path' do
16
+ @model.bias.should == 1
17
+ @model.class_count.should == 3
18
+ @model.feature_count.should == 180
19
+ @model.labels.should == [3,1,2]
20
+ end
21
+
22
+ it 'should be able to predict' do
23
+ @model.predict(test_vector).should == 3
24
+ end
25
+ end
26
+
27
+ describe('predict_values') do
28
+ before(:each) do
29
+ @model = RubyLinear::Model.load_file(File.dirname(__FILE__) + '/fixtures/dna.dat')
30
+ end
31
+
32
+ it 'should return the class and a hash of labels to values' do
33
+ label, values = @model.predict_values(test_vector)
34
+
35
+ label.should == 3
36
+ values.keys.should =~ [1,2,3]
37
+ values[3].should be_within(0.001).of(4.178)
38
+ values[2].should be_within(0.001).of(-8.477)
39
+ values[1].should be_within(0.001).of(-3.568)
40
+ end
41
+ end
42
+ describe('new') do
43
+ let(:problem) {RubyLinear::Problem.load_file(File.dirname(__FILE__) + '/fixtures/dna.scale.txt', 1.0)}
44
+ it 'should train the model from the parameters and the problem' do
45
+ m = RubyLinear::Model.new(problem, :solver => RubyLinear::L1R_L2LOSS_SVC)
46
+ m.predict(test_vector).should == 3
47
+ end
48
+
49
+ context 'when unknwon options are presented' do
50
+ it 'should raise argument error' do
51
+ expect { RubyLinear::Model.new(problem, :solver => RubyLinear::L1R_L2LOSS_SVC, :bogus_option => true) }.to raise_error(ArgumentError)
52
+
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe(RubyLinear::Problem) do
5
+
6
+ describe 'load_file' do
7
+ it 'should load a libsvm format file' do
8
+ problem = RubyLinear::Problem.load_file(File.dirname(__FILE__) + '/fixtures/dna.scale.txt', -1)
9
+ problem.bias.should == -1
10
+
11
+ problem.l.should == 2000
12
+ problem.n.should == 180
13
+
14
+ #line 1 from the file
15
+ problem.feature_vector(0).should == [[2,1], [7,1], [12,1], [15,1], [17,1], [23,1], [26,1], [28,1], [33,1], [34,1], [40,1], [45,1], [47,1], [50,1], [52,1], [58,1], [63,1], [64,1], [67,1], [72,1], [73,1], [76,1], [80,1], [83,1], [85,1], [88,1], [91,1], [95,1], [97,1], [101,1], [113,1], [120,1], [122,1], [126,1], [132,1], [138,1], [144,1], [145,1], [150,1], [151,1], [154,1], [160,1], [163,1], [170,1], [172,1], [177,1], [178,1]]
16
+
17
+ problem.labels.length.should == 2000
18
+ end
19
+
20
+ it 'should add 1 to the feature count if the bias is > 0' do
21
+ problem = RubyLinear::Problem.load_file(File.dirname(__FILE__) + '/fixtures/dna.scale.txt', 1)
22
+
23
+ problem.l.should == 2000
24
+ problem.n.should == 181
25
+
26
+ problem.feature_vector(0).should == [[2,1], [7,1], [12,1], [15,1], [17,1], [23,1], [26,1], [28,1], [33,1], [34,1], [40,1], [45,1], [47,1], [50,1], [52,1], [58,1], [63,1], [64,1], [67,1], [72,1], [73,1], [76,1], [80,1], [83,1], [85,1], [88,1], [91,1], [95,1], [97,1], [101,1], [113,1], [120,1], [122,1], [126,1], [132,1], [138,1], [144,1], [145,1], [150,1], [151,1], [154,1], [160,1], [163,1], [170,1], [172,1], [177,1], [178,1],[181,1]]
27
+
28
+ end
29
+ end
30
+
31
+ describe 'destroy' do
32
+
33
+ it 'should release associated memory' do
34
+ problem = RubyLinear::Problem.load_file(File.dirname(__FILE__) + '/fixtures/dna.scale.txt', 1)
35
+ problem.destroyed?.should be_false
36
+ problem.destroy!
37
+ problem.destroyed?.should be_true
38
+ end
39
+
40
+ end
41
+
42
+ describe 'new' do
43
+ before(:each) do
44
+ @samples = [ {2=>0.1,3=>0.3,4=>-1.2},{1=>0.4},{2=>0.1, 4=>1.4,5=>0.5},{1 => -0.1, 2=> -0.2, 3=>0.1,4=>1.1,5=>0.1}]
45
+ @labels = [2,1,2,3]
46
+ @max_feature = 5
47
+ end
48
+
49
+ context 'when max feature is inconsistent with the samples' do
50
+ it 'should raise argument error' do
51
+ expect {RubyLinear::Problem.new(@labels, @samples, -1, 3)}.to raise_error(ArgumentError, /inconsistent/)
52
+ end
53
+ end
54
+
55
+ context 'when samples and labels are of different length' do
56
+ it 'should raise argument error' do
57
+ expect {RubyLinear::Problem.new([1,2,3], @samples, -1, @max_feature)}.to raise_error(ArgumentError, /different length/)
58
+ end
59
+ end
60
+ context 'when the bias is < 0' do
61
+ it 'should create a new problem' do
62
+ problem = RubyLinear::Problem.new(@labels, @samples, -1, @max_feature)
63
+
64
+ problem.l.should == 4
65
+ problem.n.should == 5
66
+ problem.bias.should == -1
67
+ problem.labels.should == [2,1,2,3]
68
+ problem.feature_vector(0).should == [[2,0.1], [3,0.3], [4,-1.2]]
69
+ end
70
+ end
71
+
72
+ context 'when the bias is > 0' do
73
+ it 'should add a bias term to each vextor' do
74
+ problem = RubyLinear::Problem.new(@labels, @samples, 1.0, @max_feature)
75
+ #all the feature vectors should also be padded with
76
+ problem.l.should == 4
77
+ problem.n.should == 6
78
+ problem.bias.should == 1
79
+ problem.feature_vector(0).should == [[2,0.1], [3,0.3], [4,-1.2], [6,1]]
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ $: << File.dirname(__FILE__) + '/../ext'
5
+
6
+ require 'ruby_linear'
7
+
8
+ RSpec.configure do |config|
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_linear
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Frederick Cheung
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-29 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! 'Ruby wrapper for LIBLINEAR, a library for large linear classification '
15
+ email: frederick.cheung@gmail.com
16
+ executables: []
17
+ extensions:
18
+ - ext/extconf.rb
19
+ extra_rdoc_files: []
20
+ files:
21
+ - COPYING
22
+ - AUTHORS
23
+ - README.markdown
24
+ - Rakefile
25
+ - ext/extconf.rb
26
+ - ext/blas.h
27
+ - ext/blasp.h
28
+ - ext/linear.h
29
+ - ext/tron.h
30
+ - ext/linear.cpp
31
+ - ext/rubylinear.cpp
32
+ - ext/tron.cpp
33
+ - ext/daxpy.c
34
+ - ext/ddot.c
35
+ - ext/dnrm2.c
36
+ - ext/dscal.c
37
+ - lib/ruby_linear.rb
38
+ - spec/fixtures/dna.dat
39
+ - spec/fixtures/dna.out
40
+ - spec/fixtures/dna.scale.t
41
+ - spec/fixtures/dna.scale.txt
42
+ - spec/integration_spec.rb
43
+ - spec/model_spec.rb
44
+ - spec/problem_spec.rb
45
+ - spec/spec_helper.rb
46
+ homepage: http://github.com/fcheung/rubylinear
47
+ licenses:
48
+ - MIT
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: 1.9.2
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.10
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Ruby wrapper for LIBLINEAR
71
+ test_files: []