Gaussian { public double mahalanobis(double[] query) { double[] delta = new double[k]; for (int i = 0; i < k; i++) { delta[i] = query[i] - mean[i]; } double diagSum = 0, nonDiagSum = 0; for (int d1 = 0; d1 < k; ++d1) { for (int d2 = d1; d2 < k; ++d2) { double v = delta[d1] * delta[d2] * inverseCov[d1][d2]; if (d1 == d2) { diagSum += v; } else { nonDiagSum += v; } } } return diagSum + 2 * nonDiagSum; } Gaussian();  Gaussian(double[] mean, RealMatrix cov); Gaussian fit(List<double[]> data); void initialize(); double mahalanobis(double[] query); double[] getMean(); RealMatrix getCovariance(); public int k; public double[] mean; public RealMatrix cov; public double[][] inverseCov; public boolean singular; }
@Test public void testMahalanobis() { MultivariateNormalDistribution mvNormal = getSample3dNormal(); Gaussian gaussian = new Gaussian(mvNormal.getMeans(), mvNormal.getCovariances()); int N = 100000; int k = 3; double[][] testData = new double[N][k]; for (int i = 0; i < N; i++) { testData[i] = mvNormal.sample(); } double[] mScores = new double[N]; long startTime = System.currentTimeMillis(); for (int i = 0; i < N; i++) { mScores[i] = gaussian.mahalanobis(testData[i]); } long endTime = System.currentTimeMillis(); log.debug("Mahalobis distance on {} in {}", N, endTime-startTime); double[] dScores = new double[N]; startTime = System.currentTimeMillis(); for (int i = 0; i < N; i++) { dScores[i] = -Math.log(mvNormal.density(testData[i])); } endTime = System.currentTimeMillis(); log.debug("LogPDF on {} in {}", N, endTime-startTime); for (int i = 1; i < N; i++) { assertEquals(mScores[i] > mScores[i-1], dScores[i] > dScores[i-1]); } }