Last active
March 17, 2017 05:18
-
-
Save wendykan/2fcbbf95945faa0f2c89895694069010 to your computer and use it in GitHub Desktop.
Custom evaluation metric code for DSTL Kaggle competition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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