super();
this.invert = invert;
}
public OutlierResult run(Relation<V> relation) throws IllegalStateException {
DoubleMinMax mm = new DoubleMinMax();
// resulting scores
WritableDataStore<Double> oscores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, Double.class);
// Compute mean and covariance Matrix
CovarianceMatrix temp = CovarianceMatrix.make(relation);
V mean = temp.getMeanVector(relation);
// debugFine(mean.toString());
Matrix covarianceMatrix = temp.destroyToNaiveMatrix();
// debugFine(covarianceMatrix.toString());
Matrix covarianceTransposed = covarianceMatrix.cheatToAvoidSingularity(SINGULARITY_CHEAT).inverse();
// Normalization factors for Gaussian PDF
final double fakt = (1.0 / (Math.sqrt(Math.pow(MathUtil.TWOPI, DatabaseUtil.dimensionality(relation)) * covarianceMatrix.det())));
// for each object compute Mahalanobis distance
for(DBID id : relation.iterDBIDs()) {
V x = relation.get(id);
Vector x_minus_mean = x.minus(mean).getColumnVector();
// Gaussian PDF
final double mDist = x_minus_mean.transposeTimes(covarianceTransposed).times(x_minus_mean).get(0, 0);
final double prob = fakt * Math.exp(-mDist / 2.0);
mm.put(prob);
oscores.put(id, prob);
}
final OutlierScoreMeta meta;
if(invert) {
double max = mm.getMax() != 0 ? mm.getMax() : 1.;
for(DBID id : relation.iterDBIDs()) {
oscores.put(id, (max - oscores.get(id)) / max);
}
meta = new BasicOutlierScoreMeta(0.0, 1.0);
}
else {
meta = new InvertedOutlierScoreMeta(mm.getMin(), mm.getMax(), 0.0, Double.POSITIVE_INFINITY);
}
Relation<Double> res = new MaterializedRelation<Double>("Gaussian Model Outlier Score", "gaussian-model-outlier", TypeUtil.DOUBLE, oscores, relation.getDBIDs());
return new OutlierResult(meta, res);
}