Class: Ai4r::Classifiers::Prism

Inherits:
Classifier show all
Defined in:
lib/ai4r/classifiers/prism.rb

Overview

Introduction

This is an implementation of the PRISM algorithm (Cendrowska, 1987) Given a set of preclassified examples, it builds a set of rules to predict the class of other instaces.

  1. Cendrowska (1987). PRISM: An algorithm for inducing modular rules.

International Journal of Man-Machine Studies. 27(4):349-370.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Data::Parameterizable

#get_parameters, included, #set_parameters

Constructor Details

#initializePrism

Returns a new instance of Prism.



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/ai4r/classifiers/prism.rb', line 38

def initialize
  super()
  @fallback_class = nil
  @bin_count = 10
  @attr_bins = {}

  @default_class = nil
  @tie_break = :first
  @bin_count = 10
  @attr_bins = {}
end

Instance Attribute Details

#data_setObject (readonly)

Returns the value of attribute data_set.



29
30
31
# File 'lib/ai4r/classifiers/prism.rb', line 29

def data_set
  @data_set
end

#majority_classObject (readonly)

Returns the value of attribute majority_class.



29
30
31
# File 'lib/ai4r/classifiers/prism.rb', line 29

def majority_class
  @majority_class
end

#rulesObject (readonly)

Returns the value of attribute rules.



29
30
31
# File 'lib/ai4r/classifiers/prism.rb', line 29

def rules
  @rules
end

Instance Method Details

#build(data_set) ⇒ Object

Build a new Prism classifier. You must provide a DataSet instance as parameter. The last attribute of each item is considered as the item class.

Parameters:

  • data_set (Object)

Returns:

  • (Object)


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
# File 'lib/ai4r/classifiers/prism.rb', line 55

def build(data_set)
  data_set.check_not_empty
  @data_set = data_set

  freqs = Hash.new(0)
  @data_set.data_items.each { |item| freqs[item.last] += 1 }
  @majority_class = freqs.max_by { |_, v| v }&.first
  @fallback_class = @default_class if @default_class
  @fallback_class = @majority_class if @fallback_class.nil?

  domains = @data_set.build_domains
  @attr_bins = {}
  domains[0...-1].each_with_index do |domain, i|
    @attr_bins[@data_set.data_labels[i]] = discretize_range(domain, @bin_count) if domain.is_a?(Array) && domain.length == 2 && domain.all? { |v| v.is_a? Numeric }
  end
  instances = @data_set.data_items.collect { |data| data }
  @rules = []
  domains.last.each do |class_value|
    while class_value?(instances, class_value)
      rule = build_rule(class_value, instances)
      @rules << rule
      instances = instances.reject { |data| matches_conditions(data, rule[:conditions]) }
    end
  end
  self
end

#eval(instace) ⇒ Object

You can evaluate new data, predicting its class. e.g.

classifier.eval(['New York',  '<30', 'F'])  # => 'Y'

Parameters:

  • instace (Object)

Returns:

  • (Object)


87
88
89
90
91
92
# File 'lib/ai4r/classifiers/prism.rb', line 87

def eval(instace)
  @rules.each do |rule|
    return rule[:class_value] if matches_conditions(instace, rule[:conditions])
  end
  @default_class || @fallback_class
end

#get_rulesObject

This method returns the generated rules in ruby code. e.g.

classifier.get_rules
  # => if age_range == '<30' then marketing_target = 'Y'
 elsif age_range == '>80' then marketing_target = 'Y'
 elsif city == 'Chicago' and age_range == '[30-50)' then marketing_target = 'Y'
 else marketing_target = 'N'
 end

It is a nice way to inspect induction results, and also to execute them:

age_range = '[30-50)'
city = 'New York'
eval(classifier.get_rules)
puts marketing_target
 'Y'

Returns:

  • (Object)


111
112
113
114
115
116
117
118
119
# File 'lib/ai4r/classifiers/prism.rb', line 111

def get_rules
  out = "if #{join_terms(@rules.first)} then #{then_clause(@rules.first)}"
  @rules[1...-1].each do |rule|
    out += "\nelsif #{join_terms(rule)} then #{then_clause(rule)}"
  end
  out += "\nelse #{then_clause(@rules.last)}" if @rules.size > 1
  out += "\nend"
  out
end