-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun.rb
executable file
·164 lines (135 loc) · 4.11 KB
/
run.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/env ruby
require './hacks/backports'
begin
require './hacks/colorize'
rescue
require './hacks/fallback'
end
require 'optparse'
require './lib/cea'
require './data'
# The main runner.
def run
options = parse_args
eval "@data_set = DataSets::#{options[:dataset]}"
case options[:task]
when :train
train (options[:class] || @data_set::DefaultCase), options[:number], options[:pause]
when :classify
classify options[:number]
end
end
def colourise_classification classification
case classification
when :positive
classification.to_s.green
when :unknown
classification.to_s.magenta
when :negative
classification.to_s.red
end
end
def parse_args
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: #{__FILE__} [options]"
options[:task] = :train
options[:number] = nil
options[:class] = nil
options[:dataset] = 'Assignment'
options[:pause] = false
opts.on '-t', '--task TASK', 'Which task to perform (train or classify), default = train' do |task|
options[:task] = task.to_sym
options[:number] = 10 if task == 'classify'
end
opts.on '-n', '--number NUMBER', 'How many examples to use, default = all for training, 10 for classifying' do |number|
options[:number] = number.to_i
end
opts.on '-c', '--class CLASS', 'Which class to train on, only applicable for the training task, default = train' do |klass|
options[:class] = klass.to_sym
end
opts.on '-d', '--dataset DATASET', 'Which dataset to use, default = Assignment' do |dataset|
options[:dataset] = dataset
end
opts.on '-p', '--pause', 'Enable to pause between examples' do
options[:pause] = true
end
opts.on '-h', '--help', 'Display this screen' do
puts opts
exit
end
end.parse!
options
end
def print_algo algo
puts "S:"
puts algo.S.join('').chomp
puts "G:"
puts algo.G.join('').chomp
end
def train correct_case, number, pause
algo = CEA::Algorithm.new(@data_set::Attributes)
print_algo algo
puts
puts "Press enter to step through each example#{ RUBY_VERSION < '1.8.7' ? '' : ', Ctrl+D to continue to end'}" if pause
@data_set::Examples.send(*(number ? [:take, number] : [:+, []])).each do |kase, example|
gets if pause
prior = colourise_classification algo.classify example
if kase == correct_case
algo.add_positive_example example
example_colour = :light_green
else
algo.add_negative_example example
example_colour = :light_red
end
after = colourise_classification algo.classify example
puts "Example:" + " #{ example.inspect } ==> #{ kase }".send(example_colour)
puts "Prior Classification:" + " #{ prior }"
puts "After Classification:" + " #{ after }"
puts "----"
print_algo algo
end
end
def classify number
algos = Hash[
@data_set::Cases.map do |key|
[key, CEA::Algorithm.new(@data_set::Attributes)]
end
]
@data_set::Examples.take(number).each do |kase, example|
algos.each do |key, algo|
if kase == key
algo.add_positive_example example
else
algo.add_negative_example example
end
end
end
algos.each do |key, algo|
puts "For case: #{key}, Version space is:"
print_algo algo
puts "===="
end
@data_set::Examples.drop(number).each do |kase, example|
puts "For Example: " + example.inspect.light_green
puts " => ".light_green + kase.to_s.light_green
results = Hash[
algos.map do |key, algo|
classification = algo.classify example
puts "#{key} (#{algo.convergent_state == :converged ? "conv".green : "unco".red}) classifies as: #{colourise_classification classification}"
[key, classification]
end
]
if results.values.one? { |val| val == :positive }
puts "Class: " + results.index(:positive).to_s.green
elsif results.values.any? { |val| val == :unknown }
puts "Class: " + "don't know".magenta
elsif results.values.none? { |val| val == :positive }
puts "Class: " + "not classified".magenta
else
puts "Class: " + "error".red
end
puts
end
end
run