package me.mcnelis.rudder.ml.supervised.classification; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.log4j.Logger; import me.mcnelis.rudder.data.collections.IRudderList; public class NaiveBayesClassification { private static final Logger LOG = Logger.getLogger(NaiveBayesClassification.class); protected Map<String, List<BayesFeature>> classList = new HashMap<String, List<BayesFeature>>(); protected IRudderList<?> records; public void setData(IRudderList<?> records) { this.records = records; } public void train() { for (Object r : records) { List<BayesFeature> featureList = null; if (!this.classList.containsKey(records.getStringLabel(r))) { featureList = new ArrayList<BayesFeature>(); } else { featureList = this.classList.get(records.getStringLabel(r)); } int idx = 0; for (Object f : records.getRecordFeatures(r)) { BayesFeature bf = null; try { bf = featureList.get(idx); bf.add(f); } catch (IndexOutOfBoundsException iobe) { if (f instanceof Double) { bf = new BayesContinuousFeature(); } else { bf = new BayesDiscreteFeature(); } bf.add(f); featureList.add(bf); } idx++; } this.classList.put(records.getStringLabel(r), featureList); } } public Map<String, Double> getClassScores(Object r) { HashMap<String, Double> labelScores = new HashMap<String, Double>(); for (String label : this.classList.keySet()) { double scores = 0d; List<BayesFeature> featureList = this.classList.get(label); Object[] values = this.records.getRecordFeatures(r).toArray(); int idx = 0; for (BayesFeature bf : featureList) { double rawScore = bf.getClassScore(values[idx]); if (rawScore == 0d) { rawScore = -1; } double score = Math.log(rawScore); if (Double.isNaN(score)) { score = 0d; } scores += score; idx++; } LOG.debug(label + ": " + scores); labelScores.put(label, scores); } double den = 0d; for (Double ps : labelScores.values()) { den += ps; } HashMap<String, Double> normalizedScores = new HashMap<String, Double>(); for (Entry<String, Double> label : labelScores.entrySet()) { normalizedScores.put(label.getKey(), labelScores.get(label.getKey()) / den); } return normalizedScores; } public String getLabel(Object r) { Map<String, Double> labelScores = this.getClassScores(r); double maxScore = 0d; String myLabel = ""; for (Entry<String, Double> label : labelScores.entrySet()) { if (maxScore < labelScores.get(label.getKey())) { myLabel = label.getKey(); maxScore = labelScores.get(label.getKey()); } } return myLabel; } }