Skip to content

Instantly share code, notes, and snippets.

@wendykan
Last active March 17, 2017 05:18
Show Gist options
  • Save wendykan/2fcbbf95945faa0f2c89895694069010 to your computer and use it in GitHub Desktop.
Save wendykan/2fcbbf95945faa0f2c89895694069010 to your computer and use it in GitHub Desktop.
Custom evaluation metric code for DSTL Kaggle competition
using System;
using System.Collections.Generic;
using System.Linq;
using GeoAPI.Geometries;
using Kaggle.DataFrames;
using NetTopologySuite.IO;
namespace Kaggle.Metrics.Custom {
[PublishedEvaluationAlgorithm("JaccardDSTLParallel", Name = "JaccardDSTLParallel",
Description = "JaccardDSTLParallel",
IsPublic = false, IsMax = true)]
public class JaccardDSTLParallel : DataFrameEvaluationAlgorithm<JaccardDSTLParallel.Solution, JaccardDSTLParallel.Submission> {
public class Solution : TypedDataFrame {
public Series<string> ImageId { get; set; }
public Series<int> ClassType { get; set; }
public Series<string> MultipolygonWKT { get; set; }
//public Series<string> Usage { get; set; }
}
public class Submission : TypedDataFrame {
public Series<string> ImageId { get; set; }
public Series<int> ClassType { get; set; }
public Series<string> MultipolygonWKT { get; set; }
}
public override double EvaluateSubmissionSubset(Solution solution, Submission submission) {
return CalculateIouVectorParallel(Enumerable.Range(0, solution.ImageId.Count).Select(i => {
if (solution.ImageId[i] != submission.ImageId[i] || solution.ClassType[i] != submission.ClassType[i]) {
throw new Exception(String.Format("Unexpected image '{0}' of class type '{1}'", submission.ImageId[i], submission.ClassType[i]));
}
return new JoinedMP {
ImageId = solution.ImageId[i],
ClassType = solution.ClassType[i],
SolWkt = solution.MultipolygonWKT[i],
SubWkt = submission.MultipolygonWKT[i],
};
}));
}
private double CalculateIouVectorParallel(IEnumerable<JoinedMP> joined) {
try {
return joined.AsParallel().Select(x => {
var reader = new WKTReader();
var solMP = reader.Read(x.SolWkt);
try {
var subMP = reader.Read(x.SubWkt);
var tmp = CompareMultipolygon(solMP, subMP);
x.IouTP = tmp.TP;
x.IouDenom = tmp.Denom;
} catch (Exception e) {
throw new Exception(String.Format("For image {0}, class {1}, there's an exception in geometry {2}.", x.ImageId, x.ClassType, e));
}
return x;
})
.GroupBy(x => x.ClassType)
.Select(g => {
var tp = 0.0;
var denom = 0.0;
foreach(var x in g) {
tp += x.IouTP;
denom += x.IouDenom;
}
return tp / denom;
})
.Average();
} catch(AggregateException ae) {
throw ae.InnerExceptions.First();
}
}
class JoinedMP {
public string ImageId;
public int ClassType;
public string SolWkt;
public string SubWkt;
public double IouTP;
public double IouDenom;
}
private IntersectionStats CompareMultipolygon(IGeometry predMultipoly, IGeometry truthMultipoly) {
double tp = 0.0;
tp = predMultipoly.Intersection(truthMultipoly).Area;
double predArea = predMultipoly.Area;
double actualArea = truthMultipoly.Area;
return new IntersectionStats {
TP = tp,
Denom = predArea + actualArea - tp
};
}
class IntersectionStats {
public double TP;
public double Denom;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment