Rank Eval: Handle precion@ edge case
There's a currently unhandled edge case for the precion@ metric. When none of the search hits in the result are rated, we have neither true nor false positives which currently leads to division by zero. We should return a precion of 0.0 in this case.
This commit is contained in:
parent
25565b9baa
commit
2dad72e68c
|
@ -122,22 +122,25 @@ public class PrecisionAtN implements RankedListQualityMetric {
|
||||||
**/
|
**/
|
||||||
@Override
|
@Override
|
||||||
public EvalQueryQuality evaluate(String taskId, SearchHit[] hits, List<RatedDocument> ratedDocs) {
|
public EvalQueryQuality evaluate(String taskId, SearchHit[] hits, List<RatedDocument> ratedDocs) {
|
||||||
int good = 0;
|
int truePositives = 0;
|
||||||
int bad = 0;
|
int falsePositives = 0;
|
||||||
List<RatedSearchHit> ratedSearchHits = joinHitsWithRatings(hits, ratedDocs);
|
List<RatedSearchHit> ratedSearchHits = joinHitsWithRatings(hits, ratedDocs);
|
||||||
for (RatedSearchHit hit : ratedSearchHits) {
|
for (RatedSearchHit hit : ratedSearchHits) {
|
||||||
Optional<Integer> rating = hit.getRating();
|
Optional<Integer> rating = hit.getRating();
|
||||||
if (rating.isPresent()) {
|
if (rating.isPresent()) {
|
||||||
if (rating.get() >= this.relevantRatingThreshhold) {
|
if (rating.get() >= this.relevantRatingThreshhold) {
|
||||||
good++;
|
truePositives++;
|
||||||
} else {
|
} else {
|
||||||
bad++;
|
falsePositives++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double precision = (double) good / (good + bad);
|
double precision = 0.0;
|
||||||
|
if (truePositives + falsePositives > 0) {
|
||||||
|
precision = (double) truePositives / (truePositives + falsePositives);
|
||||||
|
}
|
||||||
EvalQueryQuality evalQueryQuality = new EvalQueryQuality(taskId, precision);
|
EvalQueryQuality evalQueryQuality = new EvalQueryQuality(taskId, precision);
|
||||||
evalQueryQuality.addMetricDetails(new PrecisionAtN.Breakdown(good, good + bad));
|
evalQueryQuality.addMetricDetails(new PrecisionAtN.Breakdown(truePositives, truePositives + falsePositives));
|
||||||
evalQueryQuality.addHitsAndRatings(ratedSearchHits);
|
evalQueryQuality.addHitsAndRatings(ratedSearchHits);
|
||||||
return evalQueryQuality;
|
return evalQueryQuality;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,10 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
public class PrecisionAtNTests extends ESTestCase {
|
public class PrecisionAtNTests extends ESTestCase {
|
||||||
|
|
||||||
public void testPrecisionAtFiveCalculation() throws IOException, InterruptedException, ExecutionException {
|
public void testPrecisionAtFiveCalculation() {
|
||||||
List<RatedDocument> rated = new ArrayList<>();
|
List<RatedDocument> rated = new ArrayList<>();
|
||||||
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
|
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
|
||||||
EvalQueryQuality evaluated = (new PrecisionAtN(5)).evaluate("id", toSearchHits(rated, "test", "testtype"), rated);
|
EvalQueryQuality evaluated = (new PrecisionAtN(5)).evaluate("id", toSearchHits(rated, "test", "testtype"), rated);
|
||||||
|
@ -48,7 +47,7 @@ public class PrecisionAtNTests extends ESTestCase {
|
||||||
assertEquals(1, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
assertEquals(1, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrecisionAtFiveIgnoreOneResult() throws IOException, InterruptedException, ExecutionException {
|
public void testPrecisionAtFiveIgnoreOneResult() {
|
||||||
List<RatedDocument> rated = new ArrayList<>();
|
List<RatedDocument> rated = new ArrayList<>();
|
||||||
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
|
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
|
||||||
rated.add(new RatedDocument("test", "testtype", "1", Rating.RELEVANT.ordinal()));
|
rated.add(new RatedDocument("test", "testtype", "1", Rating.RELEVANT.ordinal()));
|
||||||
|
@ -65,7 +64,7 @@ public class PrecisionAtNTests extends ESTestCase {
|
||||||
* test that the relevant rating threshold can be set to something larger than 1.
|
* test that the relevant rating threshold can be set to something larger than 1.
|
||||||
* e.g. we set it to 2 here and expect dics 0-2 to be not relevant, doc 3 and 4 to be relevant
|
* e.g. we set it to 2 here and expect dics 0-2 to be not relevant, doc 3 and 4 to be relevant
|
||||||
*/
|
*/
|
||||||
public void testPrecisionAtFiveRelevanceThreshold() throws IOException, InterruptedException, ExecutionException {
|
public void testPrecisionAtFiveRelevanceThreshold() {
|
||||||
List<RatedDocument> rated = new ArrayList<>();
|
List<RatedDocument> rated = new ArrayList<>();
|
||||||
rated.add(new RatedDocument("test", "testtype", "0", 0));
|
rated.add(new RatedDocument("test", "testtype", "0", 0));
|
||||||
rated.add(new RatedDocument("test", "testtype", "1", 1));
|
rated.add(new RatedDocument("test", "testtype", "1", 1));
|
||||||
|
@ -80,7 +79,7 @@ public class PrecisionAtNTests extends ESTestCase {
|
||||||
assertEquals(5, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
assertEquals(5, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrecisionAtFiveCorrectIndex() throws IOException, InterruptedException, ExecutionException {
|
public void testPrecisionAtFiveCorrectIndex() {
|
||||||
List<RatedDocument> rated = new ArrayList<>();
|
List<RatedDocument> rated = new ArrayList<>();
|
||||||
rated.add(new RatedDocument("test_other", "testtype", "0", Rating.RELEVANT.ordinal()));
|
rated.add(new RatedDocument("test_other", "testtype", "0", Rating.RELEVANT.ordinal()));
|
||||||
rated.add(new RatedDocument("test_other", "testtype", "1", Rating.RELEVANT.ordinal()));
|
rated.add(new RatedDocument("test_other", "testtype", "1", Rating.RELEVANT.ordinal()));
|
||||||
|
@ -94,7 +93,7 @@ public class PrecisionAtNTests extends ESTestCase {
|
||||||
assertEquals(3, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
assertEquals(3, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrecisionAtFiveCorrectType() throws IOException, InterruptedException, ExecutionException {
|
public void testPrecisionAtFiveCorrectType() {
|
||||||
List<RatedDocument> rated = new ArrayList<>();
|
List<RatedDocument> rated = new ArrayList<>();
|
||||||
rated.add(new RatedDocument("test", "other_type", "0", Rating.RELEVANT.ordinal()));
|
rated.add(new RatedDocument("test", "other_type", "0", Rating.RELEVANT.ordinal()));
|
||||||
rated.add(new RatedDocument("test", "other_type", "1", Rating.RELEVANT.ordinal()));
|
rated.add(new RatedDocument("test", "other_type", "1", Rating.RELEVANT.ordinal()));
|
||||||
|
@ -107,6 +106,14 @@ public class PrecisionAtNTests extends ESTestCase {
|
||||||
assertEquals(3, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
assertEquals(3, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNoRatedDocs() throws Exception {
|
||||||
|
List<RatedDocument> rated = new ArrayList<>();
|
||||||
|
EvalQueryQuality evaluated = (new PrecisionAtN(5)).evaluate("id", toSearchHits(rated, "test", "testtype"), rated);
|
||||||
|
assertEquals(0.0d, evaluated.getQualityLevel(), 0.00001);
|
||||||
|
assertEquals(0, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
|
||||||
|
assertEquals(0, ((PrecisionAtN.Breakdown) evaluated.getMetricDetails()).getRetrieved());
|
||||||
|
}
|
||||||
|
|
||||||
public void testParseFromXContent() throws IOException {
|
public void testParseFromXContent() throws IOException {
|
||||||
String xContent = " {\n"
|
String xContent = " {\n"
|
||||||
+ " \"size\": 10,\n"
|
+ " \"size\": 10,\n"
|
||||||
|
|
Loading…
Reference in New Issue