lib/ai4r/classifiers/hyperpipes.rb in ai4r-1.6 vs lib/ai4r/classifiers/hyperpipes.rb in ai4r-1.6.1

- old
+ new

@@ -6,11 +6,10 @@ # You can redistribute it and/or modify it under the terms of # the Mozilla Public License version 1.1 as published by the # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt require 'set' -require File.dirname(__FILE__) + '/../data/constants' require File.dirname(__FILE__) + '/../data/data_set' require File.dirname(__FILE__) + '/../classifiers/classifier' module Ai4r module Classifiers @@ -27,16 +26,17 @@ # Build a new Hyperpipes classifier. You must provide a DataSet instance # as parameter. The last attribute of each item is considered as # the item class. def build(data_set) + data_set.check_not_empty @data_set = data_set @domains = data_set.build_domains @pipes = {} - @domains.last.each {|cat| @pipes[cat] = build_pipe(@domains)} - @data_set.data_item.each {|item| update_pipe(@pipes[item.last], item) } + @domains.last.each {|cat| @pipes[cat] = build_pipe(@data_set)} + @data_set.data_items.each {|item| update_pipe(@pipes[item.last], item) } return self end # You can evaluate new data, predicting its class. @@ -45,11 +45,11 @@ def eval(data) votes = Hash.new {0} @pipes.each do |category, pipe| pipe.each_with_index do |bounds, i| if data[i].is_a? Numeric - votes[category]+=1 if data[i]>bounds[:min] && data[i]<bounds[:max] + votes[category]+=1 if data[i]>=bounds[:min] && data[i]<=bounds[:max] else votes[category]+=1 if bounds[data[i]] end end end @@ -77,35 +77,35 @@ labels = @data_set.data_labels.collect {|l| l.to_s} @pipes.each do |category, pipe| pipe.each_with_index do |bounds, i| rule = "votes['#{category}'] += 1 " if data[i].is_a? Numeric - rule += "if #{labels[i]} > #{bounds[:min]} && #{labels[i]} < #{bounds[:max]}" + rule += "if #{labels[i]} >= #{bounds[:min]} && #{labels[i]} <= #{bounds[:max]}" else - rule += "if #{bounds.inspect}['#{labels[i]}']" + rule += "if #{bounds.inspect}[#{labels[i]}]" end rules << rule end end - rules << "votes.to_a.max {|x, y| x.last <=> y.last}.first" - return rules.join('\n') + rules << "#{labels.last} = votes.to_a.max {|x, y| x.last <=> y.last}.first" + return rules.join("\n") end protected def build_pipe(data_set) data_set.data_items.first[0...-1].collect do |att| if att.is_a? Numeric - {:min=>POSITIVE_INFINITY, :max=>NEGATIVE_INFINITY} + {:min=>1.0/0, :max=>-1.0/0} else Hash.new(false) end end end def update_pipe(pipe, data_item) data_item[0...-1].each_with_index do |att, i| - if att.first.is_a? Numeric + if att.is_a? Numeric pipe[i][:min] = att if att < pipe[i][:min] pipe[i][:max] = att if att > pipe[i][:max] else pipe[i][att] = true end