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
|
# File 'lib/cabalist/model_additions.rb', line 6
def acts_as_cabalist(options = {})
raise 'No features specified' \
unless options.has_key?(:features)
raise 'Expecting an Array of features' \
unless options[:features].instance_of?(Array)
raise 'No class variable specified' \
unless options.has_key?(:class_variable)
collection = options[:collection] || :manually_classified
algorithm = options[:algorithm] || :id3
classifier = case algorithm
when :hyperpipes then ::Ai4r::Classifiers::Hyperpipes
when :ib1 then ::Ai4r::Classifiers::IB1
when :id3 then ::Ai4r::Classifiers::ID3
when :one_r then ::Ai4r::Classifiers::OneR
when :prism then ::Ai4r::Classifiers::Prism
when :zero_r then ::Ai4r::Classifiers::ZeroR
else raise 'Unknown algorithm provided'
end
scope :manually_classified,
where("autoclassified_at IS NULL AND %s IS NOT NULL" %
options[:class_variable])
scope :auto_classified,
where("autoclassified_at IS NOT NULL AND %s IS NOT NULL" %
options[:class_variable])
scope :not_classified,
where("autoclassified_at IS NULL AND %s IS NULL" %
options[:class_variable])
send(:define_method, :get_features, lambda {
options[:features].map { |f| self.send(f) }
})
send(:define_method, :get_class_variable, lambda {
self.send(options[:class_variable])
})
send(:define_method, :set_class_variable, lambda { |c|
self.send("#{options[:class_variable]}=".to_sym, c) or self
})
send(:define_singleton_method, :get_feature_names, lambda {
options[:features]
})
send(:define_singleton_method, :get_class_variable_name, lambda {
options[:class_variable]
})
send(:define_singleton_method, :build_model, lambda {
classifier::new.build(
Ai4r::Data::DataSet::new({
:data_items => send(collection).map do |el|
el.get_features.push(el.get_class_variable)
end,
:data_labels => get_feature_names + [get_class_variable_name]
})
)
})
send(:define_singleton_method, :train_model, lambda {
_model = build_model
Cabalist::Configuration.instance.database.put(name,
Marshal::dump(_model))
return _model
})
send(:define_singleton_method, :classifier, lambda {
_stored = Cabalist::Configuration.instance.database.get(self.name)
return _stored ? Marshal.load(_stored) : train_model
})
define_singleton_method(
:class_variable_domain,
lambda { self.classifier.data_set.build_domain(-1).to_a }
)
send(:define_method, :classify, lambda {
begin
self.class::classifier.eval(get_features)
rescue
nil
end
})
send(:define_method, :classify!, lambda {
set_class_variable(classify)
self.autoclassified_at = DateTime::now
})
send(:define_method, :teach, lambda { |new_class|
set_class_variable(new_class)
self.autoclassified_at = nil
})
end
|