/// <summary> /// Calcualtes loglikelihood of Gaussian Mixture Distribution /// </summary> /// <param name="observations">Observation seuqnce</param> /// <param name="mixingCoefficients">Mixing coeficients</param> /// <param name="covariances">Array of covariance matrixes</param> /// <param name="mean">Array of mean vectors</param> /// <returns>Loglikelihood</returns> public static double Calculate(double[][] observations, double[] mixingCoefficients, double[][,] covariances, double[][] means) { var N = observations.Length; var K = mixingCoefficients.Length; var D = means[0].Length; var result = 0.0d; var constant = (1 / Math.Pow(Math.Sqrt(2 * Math.PI), D)); for (int n = 0; n < N; n++) { var x = observations[n]; var mixtureResult = 0.0; for (int k = 0; k < K; k++) { var covarianceMatrix = new Matrix(covariances[k]); var covarianceMatrixInverse = covarianceMatrix.Inverse(); var distance = Mahalanobis.Calculate(x, means[k], covarianceMatrixInverse); var prefix = constant * (1 / Math.Sqrt(covarianceMatrix.Determinant)); mixtureResult += mixingCoefficients[k] * prefix *Math.Exp(-0.5 *distance); } result += Math.Log(mixtureResult); } return(result); }
/// <summary> /// 1. Calculate Mahalanobis Distance for exponent factor /// 2. Check if the matrix is semetric /// 3. Check if the matrix is positive and semidifine /// 4. Calculate Inverse matrix /// 5. Check if matrix is Positive definite /// </summary> /// <param name="x">Observation vector</param> /// <returns>Probability</returns> public override double ProbabilityDensityFunction(params double[] x) { var k = x.Length; var sigmaInverse = _matrix.Inverse(); var distance = Mahalanobis.Calculate(x, Mean, sigmaInverse); var constant = (1 / Math.Pow(SqrtPi, k)) * (1 / Math.Sqrt(_matrix.Determinant)); var p = constant * Math.Exp(-0.5 * distance); // This means that the probability is to low (underflow) if (p.EqualsToZero() || double.IsNaN(p)) { p = MINIMUM_PROBABILITY; } // if (p > 1 || p < 0) // { // Debug.Write(Environment.NewLine + "Covariance matrix " + Environment.NewLine); // Debug.Write(_matrix.ToString()); // Debug.Write(Environment.NewLine + "Mean Vector " + Environment.NewLine); // Debug.Write((new Vector(Mean)).ToString()); // Debug.Write(Environment.NewLine + "Observation Vector " + Environment.NewLine); // Debug.Write((new Vector(x)).ToString()); // Debug.Write(Environment.NewLine); // //throw new ApplicationException(string.Format("Probability function value {0} must be in range [0..1]", p)); // } return(p > 1 ? 1 : p); }
/// <summary> /// Caclulates Loglikelihood of Multivariate Gaussian Distribution /// </summary> /// <param name="observations">Observarion Sequence</param> /// <param name="covariance">Covariance Matrixe</param> /// <param name="mean">Mean Vector</param> /// <returns>Loglikelihood</returns> public static double Calculate(double[][] observations, double[,] covariance, double[] mean) { var N = observations.Length; var D = covariance.GetLength(0); var constant = N * D * 0.5 * Math.Log(2 * Math.PI); var covarianceMatrix = new Matrix(covariance); var covarianceMatrixInverse = covarianceMatrix.Inverse(); var lnCovariance = N * 0.5 * Math.Log(covarianceMatrix.Determinant); var sumObservations = 0.0; for (int n = 0; n < N; n++) { var x = observations[n]; var distance = Mahalanobis.Calculate(x, mean, covarianceMatrixInverse); sumObservations += distance; } return(-constant - lnCovariance - 0.5 * sumObservations); }
public void Calculate_MeanVectorAndCovarianceMatrixAndVector_MahalanobisDistance() { var m = new double[] { 500, 500 }; var x = new double[] { 410, 400 }; var sigma = new double[2, 2]; sigma[0, 0] = 6291.55737; sigma[0, 1] = 3754.32851; sigma[1, 0] = 3754.32851; sigma[1, 1] = 6280.77066; var matrix = new Matrix(sigma); var sigmaInverse = matrix.Inverse(); sigmaInverse[0, 0] = Math.Round(sigmaInverse[0, 0], 5); sigmaInverse[0, 1] = Math.Round(sigmaInverse[0, 1], 5); sigmaInverse[1, 0] = Math.Round(sigmaInverse[1, 0], 5); sigmaInverse[1, 1] = Math.Round(sigmaInverse[1, 1], 5); var d = Mahalanobis.Calculate(x, m, sigmaInverse); Assert.AreEqual(1.825, Math.Round(d, 3)); }