// Copyright 2015 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.cpdp.wekaclassifier; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import weka.classifiers.AbstractClassifier; import weka.classifiers.Classifier; import weka.classifiers.Evaluation; import weka.classifiers.functions.Logistic; import weka.core.DenseInstance; import weka.core.Instance; import weka.core.Instances; /** * Logistic Ensemble Classifier after Uchigaki et al. with some assumptions. It is unclear if these * assumptions are true. * * @author Steffen Herbold */ public class LogisticEnsemble extends AbstractClassifier { /** * default id */ private static final long serialVersionUID = 1L; /** * list with classifiers */ private List classifiers = null; /** * list with weights for each classifier */ private List weights = null; /** * local copy of the options to be passed to the ensemble of logistic classifiers */ private String[] options; /* * (non-Javadoc) * * @see weka.classifiers.AbstractClassifier#setOptions(java.lang.String[]) */ @Override public void setOptions(String[] options) throws Exception { this.options = options; } /* * (non-Javadoc) * * @see weka.classifiers.AbstractClassifier#distributionForInstance(weka.core.Instance) */ @Override public double[] distributionForInstance(Instance instance) throws Exception { Iterator classifierIter = classifiers.iterator(); Iterator weightIter = weights.iterator(); double[] result = new double[2]; while (classifierIter.hasNext()) { for (int j = 0; j < instance.numAttributes(); j++) { if (j != instance.classIndex()) { Instance copy = new DenseInstance(instance); for (int k = instance.numAttributes() - 1; k >= 0; k--) { if (j != k && k != instance.classIndex()) { copy.deleteAttributeAt(k); } } double[] localResult = classifierIter.next().distributionForInstance(copy); double currentWeight = weightIter.next(); for (int i = 0; i < localResult.length; i++) { result[i] = result[i] + localResult[i] * currentWeight; } } } } return result; } /* * (non-Javadoc) * * @see weka.classifiers.Classifier#buildClassifier(weka.core.Instances) */ @Override public void buildClassifier(Instances traindata) throws Exception { classifiers = new LinkedList<>(); weights = new LinkedList<>(); List weightsTmp = new LinkedList<>(); double sumWeights = 0.0; for (int j = 0; j < traindata.numAttributes(); j++) { if (j != traindata.classIndex()) { final Logistic classifier = new Logistic(); classifier.setOptions(options); final Instances copy = new Instances(traindata); for (int k = traindata.numAttributes() - 1; k >= 0; k--) { if (j != k && k != traindata.classIndex()) { copy.deleteAttributeAt(k); } } classifier.buildClassifier(copy); classifiers.add(classifier); Evaluation eval = new Evaluation(copy); eval.evaluateModel(classifier, copy); weightsTmp.add(eval.matthewsCorrelationCoefficient(1)); sumWeights += eval.matthewsCorrelationCoefficient(1); } } for (double tmp : weightsTmp) { weights.add(tmp / sumWeights); } } }