ruby_linear 0.1.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.
@@ -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: []