package model.supervised.naivebayes;

import data.DataSet;
import model.Predictable;
import model.Trainable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import utils.random.RandomUtils;
import utils.sort.SortIntDoubleUtils;

import java.util.HashMap;

/**
 * Created by hanxuan on 10/15/15 for machine_learning.
 */
public abstract class NaiveBayes implements Predictable, Trainable{

    private static final Logger log = LogManager.getLogger(NaiveBayes.class);

    protected DataSet data = null;

    protected int featureLength = Integer.MIN_VALUE;

    protected HashMap<Integer, Object> indexClassMap = null;

    protected int classCount = Integer.MIN_VALUE;

    private double[] priors = null;


    //******************************//

    protected abstract double[] predictClassProbability(double[] features);

    protected abstract void naiveBayesTrain();

    protected abstract void naiveBayesInit();

    //******************************//

    @Override
    public double predict(double[] feature) {

        double[] probabilities = predictClassProbability(feature);
        for (int i = 0; i < classCount; i++) {
            probabilities[i] += Math.log(priors[i]);
        }
        int[] indexes = RandomUtils.getIndexes(classCount);
        SortIntDoubleUtils.sort(indexes, probabilities);
        return indexes[indexes.length - 1];
    }

    @Override
    public double score(double[] feature) {
        double[] probabilities = predictClassProbability(feature);
        double score = probabilities[1] - probabilities[0];
        return score;
    }

    @Override
    public void train() {

        for (int category : indexClassMap.keySet()) {
            priors[category] = data.getCategoryProportion(category);
        }

        naiveBayesTrain();
    }

    @Override
    public void initialize(DataSet d) {

        data = d;
        featureLength = d.getFeatureLength();
        indexClassMap = d.getLabels().getIndexClassMap();
        classCount = indexClassMap.size();
        priors = new double[classCount];
        naiveBayesInit();

        log.info("Naive Bayes Model initializing, classCount: {}", classCount);
    }
}

@@ -182,24 +182,57 @@
 g4j.Logger;%0A
+import utils.array.ArraySumUtil;%0A
 import utils
@@ -1123,309 +1123,479 @@
 = pr
-edictClassProbability(feature);%0A        for (int i = 0; i %3C classCount; i++) %7B%0A            probabilities%5Bi%5D += Math.log(priors%5Bi%5D);%0A        %7D%0A        int%5B%5D indexes = RandomUtils.getIndexes(classCount);%0A        SortIntDoubleUtils.sort(indexes, probabilities);%0A        return indexes%5Bindexes.length - 1%5D
+obs(feature);%0A        int%5B%5D indexes = RandomUtils.getIndexes(classCount);%0A        SortIntDoubleUtils.sort(indexes, probabilities);%0A        return indexes%5Bindexes.length - 1%5D;%0A    %7D%0A%0A    @Override%0A    public double%5B%5D probs(double%5B%5D feature) %7B%0A        double%5B%5D probabilities = predictClassProbability(feature);%0A        for (int i = 0; i %3C classCount; i++) %7B%0A            probabilities%5Bi%5D += Math.log(priors%5Bi%5D);%0A        %7D%0A        return ArraySumUtil.normalize(probabilities)
 ;%0A  

add probs method