001/**
002 * Copyright (C) 2007 - 2016, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 *
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.dllearner.accuracymethods;
020
021import org.apache.log4j.Logger;
022import org.dllearner.core.ComponentAnn;
023import org.dllearner.core.Reasoner;
024import org.dllearner.core.config.ConfigOption;
025import org.dllearner.learningproblems.Heuristics;
026import org.semanticweb.owlapi.model.OWLClassExpression;
027import org.semanticweb.owlapi.model.OWLIndividual;
028
029import java.util.Collection;
030import java.util.Iterator;
031
032@ComponentAnn(name = "Predictive Accuracy Approximate", shortName = "approx.prec_acc", version = 0)
033public class AccMethodPredAccApprox extends AccMethodPredAcc implements AccMethodTwoValuedApproximate {
034        final static Logger logger = Logger.getLogger(AccMethodPredAccApprox.class);
035        @Override
036        public void init() {
037                logger.warn("Approximating predictive accuracy is an experimental feature. USE IT AT YOUR OWN RISK. If you consider to use it for anything serious, please extend the unit tests at org.dllearner.test.junit.HeuristicTests first and verify that it works.");
038        }
039        // approximation and F-measure
040        // (taken from class learning => super class instances corresponds to negative examples
041        // and class instances to positive examples)
042    @ConfigOption(description = "The Approximate Delta", defaultValue = "0.05", required = false)
043        private double approxDelta = 0.05;
044        @ConfigOption(description = "(configured by the learning problem)")
045        private Reasoner reasoner;
046        
047    
048        @Override
049        public double getAccApprox2(OWLClassExpression description, Collection<OWLIndividual> positiveExamples, Collection<OWLIndividual> negativeExamples, double noise) {
050                int maxNotCovered = (int) Math.ceil(noise*positiveExamples.size());
051
052                int notCoveredPos = 0;
053                //                      int notCoveredNeg = 0;
054
055                int posClassifiedAsPos = 0;
056                int negClassifiedAsNeg = 0;
057
058                int nrOfPosChecks = 0;
059                int nrOfNegChecks = 0;
060
061                // special case: we test positive and negative examples in turn
062                Iterator<OWLIndividual> itPos = positiveExamples.iterator();
063                Iterator<OWLIndividual> itNeg = negativeExamples.iterator();
064
065                do {
066                        // in each loop we pick 0 or 1 positives and 0 or 1 negative
067                        // and classify it
068
069                        if(itPos.hasNext()) {
070                                OWLIndividual posExample = itPos.next();
071                                //                                      System.out.println(posExample);
072
073                                if(reasoner.hasType(description, posExample)) {
074                                        posClassifiedAsPos++;
075                                } else {
076                                        notCoveredPos++;
077                                }
078                                nrOfPosChecks++;
079
080                                // take noise into account
081                                if(notCoveredPos > maxNotCovered) {
082                                        return -1;
083                                }
084                        }
085
086                        if(itNeg.hasNext()) {
087                                OWLIndividual negExample = itNeg.next();
088                                if(!reasoner.hasType(description, negExample)) {
089                                        negClassifiedAsNeg++;
090                                }
091                                nrOfNegChecks++;
092                        }
093
094                        // compute how accurate our current approximation is and return if it is sufficiently accurate
095                        double approx[] = Heuristics.getPredAccApproximation(positiveExamples.size(), negativeExamples.size(), 1, nrOfPosChecks, posClassifiedAsPos, nrOfNegChecks, negClassifiedAsNeg);
096                        if(approx[1]<approxDelta) {
097                                //                                      System.out.println(approx[0]);
098                                return approx[0];
099                        }
100
101                } while(itPos.hasNext() || itNeg.hasNext());
102
103                return Heuristics.getPredictiveAccuracy(positiveExamples.size(), negativeExamples.size(), posClassifiedAsPos, negClassifiedAsNeg, 1);
104        }
105
106        @Override
107        public double getApproxDelta() {
108                return approxDelta;
109        }
110
111        @Override
112        public void setApproxDelta(double approxDelta) {
113                this.approxDelta = approxDelta;
114        }
115
116        @Override
117        public void setReasoner(Reasoner reasoner) {
118                this.reasoner = reasoner;
119        }
120
121}