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}