/**
* This file is part of General Entity Annotator Benchmark.
*
* General Entity Annotator Benchmark is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* General Entity Annotator Benchmark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with General Entity Annotator Benchmark. If not, see <http://www.gnu.org/licenses/>.
*/
package org.aksw.gerbil.evaluate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.aksw.gerbil.dataset.Dataset;
import org.aksw.gerbil.datatypes.ExperimentTaskConfiguration;
import org.aksw.gerbil.datatypes.ExperimentType;
import org.aksw.gerbil.datatypes.marking.ClassifiedMeaning;
import org.aksw.gerbil.datatypes.marking.ClassifiedSpanMeaning;
import org.aksw.gerbil.datatypes.marking.MarkingClasses;
import org.aksw.gerbil.evaluate.impl.ClassConsideringFMeasureCalculator;
import org.aksw.gerbil.evaluate.impl.ClassifyingEvaluatorDecorator;
import org.aksw.gerbil.evaluate.impl.ConfidenceBasedFMeasureCalculator;
import org.aksw.gerbil.evaluate.impl.ConfidenceScoreEvaluatorDecorator;
import org.aksw.gerbil.evaluate.impl.DoubleResultComparator;
import org.aksw.gerbil.evaluate.impl.FMeasureCalculator;
import org.aksw.gerbil.evaluate.impl.GSInKBClassifyingEvaluatorDecorator;
import org.aksw.gerbil.evaluate.impl.HierarchicalFMeasureCalculator;
import org.aksw.gerbil.evaluate.impl.SpanMergingEvaluatorDecorator;
import org.aksw.gerbil.evaluate.impl.SubTaskAverageCalculator;
import org.aksw.gerbil.evaluate.impl.filter.MarkingFilteringEvaluatorDecorator;
import org.aksw.gerbil.evaluate.impl.filter.SearcherBasedNotMatchingMarkingFilter;
import org.aksw.gerbil.matching.Matching;
import org.aksw.gerbil.matching.MatchingsSearcher;
import org.aksw.gerbil.matching.MatchingsSearcherFactory;
import org.aksw.gerbil.matching.impl.ClassifiedMeaningMatchingsSearcher;
import org.aksw.gerbil.matching.impl.CompoundMatchingsSearcher;
import org.aksw.gerbil.matching.impl.HierarchicalMatchingsCounter;
import org.aksw.gerbil.matching.impl.MatchingsCounterImpl;
import org.aksw.gerbil.matching.impl.StrongSpanMatchingsSearcher;
import org.aksw.gerbil.matching.impl.clas.EmergingEntityMeaningClassifier;
import org.aksw.gerbil.matching.impl.clas.UriBasedMeaningClassifier;
import org.aksw.gerbil.semantic.kb.ExactWhiteListBasedUriKBClassifier;
import org.aksw.gerbil.semantic.kb.SimpleWhiteListBasedUriKBClassifier;
import org.aksw.gerbil.semantic.kb.UriKBClassifier;
import org.aksw.gerbil.semantic.subclass.SimpleSubClassInferencer;
import org.aksw.gerbil.semantic.subclass.SubClassInferencer;
import org.aksw.gerbil.transfer.nif.Meaning;
import org.aksw.gerbil.transfer.nif.MeaningSpan;
import org.aksw.gerbil.transfer.nif.Span;
import org.aksw.gerbil.transfer.nif.TypedSpan;
import org.aksw.gerbil.transfer.nif.data.TypedNamedEntity;
import org.aksw.gerbil.utils.filter.TypeBasedMarkingFilter;
import org.aksw.gerbil.web.config.RootConfig;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDFS;
@SuppressWarnings("deprecation")
public class EvaluatorFactory {
// private static final Logger LOGGER =
// LoggerFactory.getLogger(EvaluatorFactory.class);
protected UriKBClassifier globalClassifier = null;
protected SubClassInferencer inferencer = null;
public EvaluatorFactory() {
this(null, null);
}
public EvaluatorFactory(UriKBClassifier globalClassifier) {
this(globalClassifier, null);
}
public EvaluatorFactory(SubClassInferencer inferencer) {
this(null, inferencer);
}
public EvaluatorFactory(UriKBClassifier globalClassifier, SubClassInferencer inferencer) {
if (globalClassifier != null) {
this.globalClassifier = globalClassifier;
} else {
this.globalClassifier = RootConfig.createDefaultUriKBClassifier();
}
if (inferencer != null) {
this.inferencer = inferencer;
} else {
this.inferencer = new SimpleSubClassInferencer(ModelFactory.createDefaultModel());
}
}
@SuppressWarnings("rawtypes")
public Evaluator createEvaluator(ExperimentType type, ExperimentTaskConfiguration configuration, Dataset dataset) {
return createEvaluator(type, configuration, dataset, globalClassifier, inferencer);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Evaluator createEvaluator(ExperimentType type, ExperimentTaskConfiguration configuration, Dataset dataset,
UriKBClassifier classifier, SubClassInferencer inferencer) {
switch (type) {
case C2KB: {
return new ClassifyingEvaluatorDecorator<Meaning, ClassifiedMeaning>(
new ClassConsideringFMeasureCalculator<ClassifiedMeaning>(
new MatchingsCounterImpl<ClassifiedMeaning>(new ClassifiedMeaningMatchingsSearcher()),
MarkingClasses.IN_KB, MarkingClasses.EE), new UriBasedMeaningClassifier<ClassifiedMeaning>(
classifier, MarkingClasses.IN_KB), new EmergingEntityMeaningClassifier<ClassifiedMeaning>());
}
case Sa2KB:
case A2KB: {
MatchingsSearcher<ClassifiedSpanMeaning> searcher = (MatchingsSearcher<ClassifiedSpanMeaning>) MatchingsSearcherFactory
.createSpanMatchingsSearcher(configuration.matching);
return new ClassifyingEvaluatorDecorator<MeaningSpan, ClassifiedSpanMeaning>(
new ClassConsideringFMeasureCalculator<ClassifiedSpanMeaning>(
new MatchingsCounterImpl<ClassifiedSpanMeaning>(
new CompoundMatchingsSearcher<ClassifiedSpanMeaning>(searcher,
new ClassifiedMeaningMatchingsSearcher<ClassifiedSpanMeaning>())),
MarkingClasses.IN_KB, MarkingClasses.EE, MarkingClasses.GS_IN_KB),
new UriBasedMeaningClassifier<ClassifiedSpanMeaning>(classifier, MarkingClasses.IN_KB),
new EmergingEntityMeaningClassifier<ClassifiedSpanMeaning>());
}
case ERec: {
return new ConfidenceBasedFMeasureCalculator<Span>(new MatchingsCounterImpl<Span>(
(MatchingsSearcher<Span>) MatchingsSearcherFactory
.createSpanMatchingsSearcher(configuration.matching)));
}
case D2KB: {
return new SearcherBasedNotMatchingMarkingFilter<MeaningSpan>(
new StrongSpanMatchingsSearcher<MeaningSpan>(),
new ClassifyingEvaluatorDecorator<MeaningSpan, ClassifiedSpanMeaning>(
new GSInKBClassifyingEvaluatorDecorator<ClassifiedSpanMeaning>(
new ClassConsideringFMeasureCalculator<ClassifiedSpanMeaning>(
new MatchingsCounterImpl<ClassifiedSpanMeaning>(
new CompoundMatchingsSearcher<ClassifiedSpanMeaning>(
(MatchingsSearcher<ClassifiedSpanMeaning>) MatchingsSearcherFactory
.createSpanMatchingsSearcher(configuration.matching),
new ClassifiedMeaningMatchingsSearcher<ClassifiedSpanMeaning>())),
MarkingClasses.IN_KB, MarkingClasses.EE, MarkingClasses.GS_IN_KB),
new StrongSpanMatchingsSearcher<ClassifiedSpanMeaning>()),
new UriBasedMeaningClassifier<ClassifiedSpanMeaning>(classifier, MarkingClasses.IN_KB),
new EmergingEntityMeaningClassifier<ClassifiedSpanMeaning>()), true);
}
case ETyping: {
return new SearcherBasedNotMatchingMarkingFilter<TypedSpan>(
new StrongSpanMatchingsSearcher<TypedSpan>(),
new ConfidenceScoreEvaluatorDecorator<TypedSpan>(new HierarchicalFMeasureCalculator<TypedSpan>(
new HierarchicalMatchingsCounter<TypedSpan>(
(MatchingsSearcher<TypedSpan>) MatchingsSearcherFactory
.createSpanMatchingsSearcher(configuration.matching), classifier,
inferencer)), FMeasureCalculator.MICRO_F1_SCORE_NAME, new DoubleResultComparator()),
true);
}
case RT2KB: {
return new ConfidenceScoreEvaluatorDecorator<TypedSpan>(new HierarchicalFMeasureCalculator<TypedSpan>(
new HierarchicalMatchingsCounter<TypedSpan>((MatchingsSearcher<TypedSpan>) MatchingsSearcherFactory
.createSpanMatchingsSearcher(configuration.matching), classifier, inferencer)),
FMeasureCalculator.MICRO_F1_SCORE_NAME, new DoubleResultComparator());
}
case OKE_Task1: {
ExperimentTaskConfiguration subTaskConfig;
List<SubTaskEvaluator<TypedNamedEntity>> evaluators = new ArrayList<SubTaskEvaluator<TypedNamedEntity>>();
UriKBClassifier okeClassifierTask1 = new ExactWhiteListBasedUriKBClassifier(Arrays.asList(
"http://www.ontologydesignpatterns.org/ont/d0.owl#Location",
"http://www.ontologydesignpatterns.org/ont/dul/DUL.owl#Organization",
"http://www.ontologydesignpatterns.org/ont/dul/DUL.owl#Person",
"http://www.ontologydesignpatterns.org/ont/dul/DUL.owl#Role"));
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.ERec, configuration.matching);
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, (Evaluator<TypedNamedEntity>) createEvaluator(
ExperimentType.ERec, subTaskConfig, dataset)));
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.D2KB, Matching.STRONG_ENTITY_MATCH);
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, (Evaluator<TypedNamedEntity>) createEvaluator(
ExperimentType.D2KB, subTaskConfig, dataset)));
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.ETyping, Matching.STRONG_ENTITY_MATCH);
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, (Evaluator<TypedNamedEntity>) createEvaluator(
ExperimentType.ETyping, subTaskConfig, dataset, okeClassifierTask1, inferencer)));
return new ConfidenceScoreEvaluatorDecorator<TypedNamedEntity>(
new SubTaskAverageCalculator<TypedNamedEntity>(evaluators), FMeasureCalculator.MICRO_F1_SCORE_NAME,
new DoubleResultComparator());
}
case OKE_Task2: {
ExperimentTaskConfiguration subTaskConfig;
List<SubTaskEvaluator<TypedNamedEntity>> evaluators = new ArrayList<SubTaskEvaluator<TypedNamedEntity>>();
String classTypes[] = new String[] { RDFS.Class.getURI(), OWL.Class.getURI() };
UriKBClassifier okeClassifierTask2 = new SimpleWhiteListBasedUriKBClassifier(
"http://www.ontologydesignpatterns.org/ont/");
// sub task 1, find the correct type of the entity (use only
// entities, without a class type!)
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.ETyping, Matching.STRONG_ENTITY_MATCH);
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, new MarkingFilteringEvaluatorDecorator<>(
new TypeBasedMarkingFilter<TypedNamedEntity>(false, classTypes),
(Evaluator<TypedNamedEntity>) createEvaluator(ExperimentType.ETyping, subTaskConfig, dataset,
okeClassifierTask2, inferencer))));
// sub task 2, find the correct position of the type in the text
// (use only entities with a class type!)
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.ERec, configuration.matching);
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, new MarkingFilteringEvaluatorDecorator<>(
new TypeBasedMarkingFilter<TypedNamedEntity>(true, classTypes),
new SpanMergingEvaluatorDecorator<>((Evaluator<TypedNamedEntity>) createEvaluator(
ExperimentType.ERec, subTaskConfig, dataset)))));
return new ConfidenceScoreEvaluatorDecorator<TypedNamedEntity>(
new SubTaskAverageCalculator<TypedNamedEntity>(evaluators), FMeasureCalculator.MICRO_F1_SCORE_NAME,
new DoubleResultComparator());
}
default: {
throw new IllegalArgumentException("Got an unknown Experiment Type.");
}
}
}
@SuppressWarnings({ "unchecked" })
protected void addSubTaskEvaluators(List<Evaluator<?>> evaluators, ExperimentTaskConfiguration configuration,
Dataset dataset) {
ExperimentTaskConfiguration subTaskConfig;
switch (configuration.type) {
case ERec: // falls through
case D2KB:
case ETyping:
case C2KB:
// Since the OKE challenge tasks are using the results of their
// subtasks, the definition of subtasks is part of their evaluation
// creation
case OKE_Task1:
case OKE_Task2: {
return;
}
case Sa2KB: // falls through
case A2KB: {
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.ERec, configuration.matching);
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, createEvaluator(ExperimentType.ERec, subTaskConfig,
dataset)));
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.D2KB, Matching.STRONG_ENTITY_MATCH);
// evaluators.add(createEvaluator(ExperimentType.ELink,
// configuration, dataset));
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, createEvaluator(ExperimentType.D2KB, subTaskConfig,
dataset)));
return;
}
case RT2KB: {
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.ERec, configuration.matching);
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, createEvaluator(ExperimentType.ERec, subTaskConfig,
dataset)));
subTaskConfig = new ExperimentTaskConfiguration(configuration.annotatorConfig, configuration.datasetConfig,
ExperimentType.ETyping, Matching.STRONG_ENTITY_MATCH);
// evaluators.add(createEvaluator(ExperimentType.ELink,
// configuration, dataset));
evaluators.add(new SubTaskEvaluator<>(subTaskConfig, createEvaluator(ExperimentType.ETyping, subTaskConfig,
dataset)));
return;
}
default: {
throw new RuntimeException();
}
}
}
public void addEvaluators(List<Evaluator<?>> evaluators, ExperimentTaskConfiguration configuration, Dataset dataset) {
evaluators.add(createEvaluator(configuration.type, configuration, dataset));
addSubTaskEvaluators(evaluators, configuration, dataset);
}
}