/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="WishartFromShapeAndRateOp_Laplace2"]/message_doc[@name="RateAverageConditional(Wishart, double, Wishart, Wishart, Wishart)"]/*'/> public static Wishart RateAverageConditional([SkipIfUniform] Wishart sample, double shape, Wishart rate, Wishart to_rate, Wishart result) { if (sample.IsPointMass) { return(WishartFromShapeAndRateOp.RateAverageConditional(sample.Point, shape, result)); } // f(Y,R) = |Y|^(a-c) |R|^a exp(-tr(YR)) // p(Y) = |Y|^(a_y-c) exp(-tr(YB_y) // p(R) = |R|^(a_r-c) exp(-tr(RB_r) // int_Y f(Y,R) p(Y) dY = |R|^a |R+B_y|^-(a+a_y-c) int dim = sample.Dimension; double c = 0.5 * (dim + 1); double shape2 = shape - c + sample.Shape; Wishart ratePost = rate * to_rate; PositiveDefiniteMatrix r = ratePost.GetMean(); PositiveDefiniteMatrix rby = r + sample.Rate; PositiveDefiniteMatrix invrby = rby.Inverse(); PositiveDefiniteMatrix rInvrby = rby; rInvrby.SetToProduct(r, invrby); double xxddlogp = Matrix.TraceOfProduct(rInvrby, rInvrby) * shape2; double delta = -xxddlogp / dim; PositiveDefiniteMatrix invR = r.Inverse(); PositiveDefiniteMatrix dlogp = invrby; dlogp.Scale(-shape2); LowerTriangularMatrix rChol = new LowerTriangularMatrix(dim, dim); rChol.SetToCholesky(r); result.SetDerivatives(rChol, invR, dlogp, xxddlogp, GammaFromShapeAndRateOp.ForceProper, shape); return(result); }
public static Gaussian BAverageConditional([SkipIfUniform] VectorGaussian product, [SkipIfUniform] VectorGaussian a, Gaussian b) { if (!b.IsPointMass) { throw new ArgumentException("b is not a point mass", nameof(b)); } double bPoint = b.Point; Vector productMean = Vector.Zero(product.Dimension); PositiveDefiniteMatrix productVariance = new PositiveDefiniteMatrix(product.Dimension, product.Dimension); product.GetMeanAndVariance(productMean, productVariance); Vector aMean = Vector.Zero(product.Dimension); PositiveDefiniteMatrix aVariance = new PositiveDefiniteMatrix(product.Dimension, product.Dimension); a.GetMeanAndVariance(aMean, aVariance); PositiveDefiniteMatrix variance = new PositiveDefiniteMatrix(product.Dimension, product.Dimension); variance.SetToSum(1, productVariance, bPoint * bPoint, aVariance); // variance = productVariance + aVariance * b^2 PositiveDefiniteMatrix precision = variance.Inverse(); Vector diff = aMean * bPoint; diff.SetToDifference(productMean, diff); // diff = productMean - aMean * b var precisionDiff = precision * diff; double dlogf = aMean.Inner(precisionDiff) + bPoint * (precisionDiff.Inner(aVariance * precisionDiff) - Matrix.TraceOfProduct(precision, aVariance)); double ddlogf = -1; return(Gaussian.FromDerivatives(bPoint, dlogf, ddlogf, GaussianProductOp.ForceProper)); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="WishartFromShapeAndRateOp_Laplace2"]/message_doc[@name="SampleAverageConditional(Wishart, double, Wishart, Wishart, Wishart, Wishart)"]/*'/> public static Wishart SampleAverageConditional([NoInit] Wishart sample, double shape, [Proper] Wishart rate, [NoInit] Wishart to_rate, [NoInit] Wishart to_sample, Wishart result) { if (sample.IsUniform()) { return(SampleAverageConditional2(shape, rate, to_rate, result)); } // f(Y,R) = |Y|^(a-c) |R|^a exp(-tr(YR)) // p(Y) = |Y|^(a_y-c) exp(-tr(YB_y) // p(R) = |R|^(a_r-c) exp(-tr(RB_r) // int_R f(Y,R) p(R) dR = |Y|^(a-c) |Y+B_r|^-(a+a_r) int dim = sample.Dimension; double c = 0.5 * (dim + 1); double shape2 = shape + rate.Shape; Wishart samplePost = sample * to_sample; if (!samplePost.IsProper()) { return(SampleAverageConditional2(shape, rate, to_rate, result)); } PositiveDefiniteMatrix y = samplePost.GetMean(); PositiveDefiniteMatrix yPlusBr = y + rate.Rate; PositiveDefiniteMatrix invyPlusBr = yPlusBr.Inverse(); PositiveDefiniteMatrix yInvyPlusBr = yPlusBr; yInvyPlusBr.SetToProduct(y, invyPlusBr); double xxddlogf = shape2 * Matrix.TraceOfProduct(yInvyPlusBr, yInvyPlusBr); PositiveDefiniteMatrix invY = y.Inverse(); //double delta = -xxddlogf / dim; //result.Shape = delta + shape; //result.Rate.SetToSum(delta, invY, shape2, invyPlusBr); LowerTriangularMatrix yChol = new LowerTriangularMatrix(dim, dim); yChol.SetToCholesky(y); PositiveDefiniteMatrix dlogp = invyPlusBr; dlogp.Scale(-shape2); result.SetDerivatives(yChol, invY, dlogp, xxddlogf, GammaFromShapeAndRateOp.ForceProper, shape - c); if (result.Rate.Any(x => double.IsNaN(x))) { throw new Exception("result.Rate is nan"); } return(result); }
/// <summary> /// Function to recalulate KBB and InvKBB /// </summary> protected void Recalculate() { int numBas = NumberBasisPoints; int numFeat = NumberFeatures; if (prior == null || numBas <= 0 || numFeat <= 0) { ClearCachedValues(); } else { kBB = prior.Covariance(basis); invKBB = kBB.Inverse(); //invKBB = new PositiveDefiniteMatrix(NumberBasisPoints, NumberBasisPoints); //LowerTriangularMatrix lt = new LowerTriangularMatrix(NumberBasisPoints, NumberBasisPoints); //lt.SetToCholesky(kBB); //invKBB.SetToIdentity(); //invKBB.PredivideBy(lt); //invKBB.PredivideByTranspose(lt); } }
/// <summary> /// Evidence message for EP /// </summary> /// <param name="Sample">Constant value for 'sample'.</param> /// <param name="MeanMean">Buffer 'MeanMean'.</param> /// <param name="MeanVariance">Buffer 'MeanVariance'.</param> /// <param name="Precision">Constant value for 'precision'.</param> /// <returns>Logarithm of the factor's average value across the given argument distributions</returns> /// <remarks><para> /// The formula for the result is <c>log(factor(sample,mean,precision))</c>. /// </para></remarks> public static double LogAverageFactor(Vector Sample, [Fresh] Vector MeanMean, [Fresh] PositiveDefiniteMatrix MeanVariance, PositiveDefiniteMatrix Precision) { return VectorGaussian.GetLogProb(Sample, MeanMean, Precision.Inverse() + MeanVariance); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ArrayFromVectorOp"]/message_doc[@name="ArrayAverageConditional{GaussianList}(IList{Gaussian}, VectorGaussianMoments, GaussianList)"]/*'/> /// <typeparam name="GaussianList">The type of the resulting array.</typeparam> public static GaussianList ArrayAverageConditional <GaussianList>( [NoInit] IList <Gaussian> array, [SkipIfUniform] VectorGaussianMoments vector, GaussianList result) where GaussianList : IList <Gaussian> { if (result.Count != vector.Dimension) { throw new ArgumentException("vector.Dimension (" + vector.Dimension + ") != result.Count (" + result.Count + ")"); } int length = result.Count; if (array.All(g => g.IsUniform()) || vector.IsUniform() || vector.IsPointMass) { for (int i = 0; i < length; i++) { result[i] = Gaussian.FromMeanAndVariance(vector.Mean[i], vector.Variance[i, i]); } } else { // Z = N(m1; m2, V1+V2) // logZ = -0.5 (m1-m2)'inv(V1+V2)(m1-m2) // dlogZ = (m1-m2)'inv(V1+V2) dm2 // ddlogZ = -dm2'inv(V1+V2) dm2 VectorGaussianMoments product = new VectorGaussianMoments(length); Vector mean = product.Mean; PositiveDefiniteMatrix variance = product.Variance; vector.GetMeanAndVariance(mean, variance); for (int i = 0; i < length; i++) { double m, v; array[i].GetMeanAndVariance(out m, out v); variance[i, i] += v; mean[i] -= m; } double offset = 1e-10; for (int i = 0; i < length; i++) { variance[i, i] += offset; } PositiveDefiniteMatrix precision = variance.Inverse(); Vector meanTimesPrecision = precision * mean; double precisionThreshold = 1; if (array.Any(g => g.Precision <= precisionThreshold)) { // compute the posterior mean and variance product.SetToProduct(vector, array); mean = product.Mean; variance = product.Variance; } for (int i = 0; i < length; i++) { if (array[i].Precision <= precisionThreshold) { result[i] = Gaussian.FromMeanAndVariance(mean[i], variance[i, i]) / array[i]; } else { double alpha = meanTimesPrecision[i]; double beta = precision[i, i]; if (double.IsNaN(alpha)) { throw new Exception("alpha is NaN"); } if (double.IsNaN(beta)) { throw new Exception("beta is NaN"); } result[i] = GaussianOp.GaussianFromAlphaBeta(array[i], alpha, beta, false); if (double.IsNaN(result[i].MeanTimesPrecision)) { throw new Exception("result is NaN"); } if (result[i].Precision < 0) { throw new Exception("result is improper"); } } } } return(result); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ArrayFromVectorOp"]/message_doc[@name="ArrayAverageConditional{GaussianList}(IList{Gaussian}, VectorGaussian, GaussianList)"]/*'/> /// <typeparam name="GaussianList">The type of the resulting array.</typeparam> public static GaussianList ArrayAverageConditional <GaussianList>( [NoInit] IList <Gaussian> array, [SkipIfUniform] VectorGaussian vector, GaussianList result) where GaussianList : IList <Gaussian> { if (result.Count != vector.Dimension) { throw new ArgumentException("vector.Dimension (" + vector.Dimension + ") != result.Count (" + result.Count + ")"); } int length = result.Count; bool allPointMass = array.All(g => g.IsPointMass); if (allPointMass) { // efficient special case for (int i = 0; i < length; i++) { double x = array[i].Point; // -prec*(x-m) = -prec*x + prec*m double dlogp = vector.MeanTimesPrecision[i]; for (int j = 0; j < length; j++) { dlogp -= vector.Precision[i, j] * array[j].Point; } double ddlogp = -vector.Precision[i, i]; result[i] = Gaussian.FromDerivatives(x, dlogp, ddlogp, false); } } else if (vector.IsPointMass) { // efficient special case Vector mean = vector.Point; for (int i = 0; i < length; i++) { result[i] = Gaussian.PointMass(mean[i]); } } else if (vector.IsUniform()) { for (int i = 0; i < length; i++) { result[i] = Gaussian.Uniform(); } } else if (array.Any(g => g.IsPointMass)) { // Z = N(m1; m2, V1+V2) // logZ = -0.5 (m1-m2)'inv(V1+V2)(m1-m2) // dlogZ = (m1-m2)'inv(V1+V2) dm2 // ddlogZ = -dm2'inv(V1+V2) dm2 Vector mean = Vector.Zero(length); PositiveDefiniteMatrix variance = new PositiveDefiniteMatrix(length, length); vector.GetMeanAndVariance(mean, variance); for (int i = 0; i < length; i++) { if (array[i].IsUniform()) { continue; } double m, v; array[i].GetMeanAndVariance(out m, out v); variance[i, i] += v; mean[i] -= m; } PositiveDefiniteMatrix precision = variance.Inverse(); Vector meanTimesPrecision = precision * mean; for (int i = 0; i < length; i++) { if (array[i].IsUniform()) { result[i] = Gaussian.FromMeanAndVariance(mean[i], variance[i, i]); } else { double alpha = meanTimesPrecision[i]; double beta = precision[i, i]; result[i] = GaussianOp.GaussianFromAlphaBeta(array[i], alpha, beta, false); } } } else { // Compute inv(V1+V2)*(m1-m2) as inv(V2)*inv(inv(V1) + inv(V2))*(inv(V1)*m1 + inv(V2)*m2) - inv(V2)*m2 = inv(V2)*(m - m2) // Compute inv(V1+V2) as inv(V2)*inv(inv(V1) + inv(V2))*inv(V2) - inv(V2) PositiveDefiniteMatrix precision = (PositiveDefiniteMatrix)vector.Precision.Clone(); Vector meanTimesPrecision = vector.MeanTimesPrecision.Clone(); for (int i = 0; i < length; i++) { Gaussian g = array[i]; precision[i, i] += g.Precision; meanTimesPrecision[i] += g.MeanTimesPrecision; } bool fastMethod = true; if (fastMethod) { bool isPosDef; // this destroys precision LowerTriangularMatrix precisionChol = precision.CholeskyInPlace(out isPosDef); if (!isPosDef) { throw new PositiveDefiniteMatrixException(); } // variance = inv(precisionChol*precisionChol') = inv(precisionChol)'*inv(precisionChol) = varianceChol*varianceChol' // this destroys meanTimesPrecision var mean = meanTimesPrecision.PredivideBy(precisionChol); mean = mean.PredivideByTranspose(precisionChol); var varianceCholTranspose = precisionChol; // this destroys precisionChol varianceCholTranspose.SetToInverse(precisionChol); for (int i = 0; i < length; i++) { Gaussian g = array[i]; double variance_ii = GetSquaredLengthOfColumn(varianceCholTranspose, i); // works when g is uniform, but not when g is point mass result[i] = Gaussian.FromMeanAndVariance(mean[i], variance_ii) / g; } } else { // equivalent to above, but slower PositiveDefiniteMatrix variance = precision.Inverse(); var mean = variance * meanTimesPrecision; for (int i = 0; i < length; i++) { Gaussian g = array[i]; // works when g is uniform, but not when g is point mass result[i] = Gaussian.FromMeanAndVariance(mean[i], variance[i, i]) / g; } } } return(result); }
/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixVectorProductOp"]/message_doc[@name="AAverageConditional(VectorGaussian, DistributionArray2D{Gaussian, double}, Vector, PositiveDefiniteMatrix, DistributionStructArray2D{Gaussian, double})"]/*'/> public static DistributionStructArray2D <Gaussian, double> AAverageConditional([SkipIfUniform] VectorGaussian product, DistributionArray2D <Gaussian, double> A, Vector BMean, PositiveDefiniteMatrix BVariance, DistributionStructArray2D <Gaussian, double> result) { if (product.IsUniform()) { result.SetToUniform(); return(result); } if (!A.IsPointMass) { throw new ArgumentException("A is not a point mass"); } // logZ = log N(mProduct; A*BMean, vProduct + A*BVariance*A') // = -0.5 (mProduct - A*BMean)' inv(vProduct + A*BVariance*A') (mProduct - A*BMean) - 0.5 logdet(vProduct + A*BVariance*A') // = -0.5 (mProduct - A*BMean)' pPrec inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) // - 0.5 logdet(pProduct + pProduct*A*BVariance*A'*pProduct) + logdet(pProduct) // dlogZ = 0.5 (dA*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) // +0.5 (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (dA*BMean) // +0.5 (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) (pProduct*dA*BVariance*A'*pProduct + pProduct*A*BVariance*dA'*pProduct) inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) // - 0.5 tr(inv(pProduct + pProduct*A*BVariance*A'*pProduct) (pProduct*dA*BVariance*A'*pProduct + pProduct*A*BVariance*dA'*pProduct)) // dlogZ/dA = pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) BMean' // + pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct*A*BVariance // - pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct A*BVariance var Amatrix = new Matrix(A.Point); var pProductA = product.Precision * Amatrix; var pProductABV = pProductA * BVariance; PositiveDefiniteMatrix prec = new PositiveDefiniteMatrix(product.Dimension, product.Dimension); prec.SetToSum(product.Precision, pProductABV * pProductA.Transpose()); // pProductA is now free for (int i = 0; i < prec.Rows; i++) { if (prec[i, i] == 0) { prec[i, i] = 1; } } var v = prec.Inverse(); var ABM = Amatrix * BMean; var pProductABM = product.Precision * ABM; var diff = pProductABM; diff.SetToDifference(product.MeanTimesPrecision, pProductABM); // ABM is now free var pProductV = product.Precision * v; var pProductVdiff = ABM; pProductVdiff.SetToProduct(pProductV, diff); var Vdiff = v * diff; pProductV.Scale(-1); pProductV.SetToSumWithOuter(pProductV, 1, pProductVdiff, Vdiff); Matrix dlogZ = pProductA; dlogZ.SetToProduct(pProductV, pProductABV); dlogZ.SetToSumWithOuter(dlogZ, 1, pProductVdiff, BMean); int rows = A.GetLength(0); int cols = A.GetLength(1); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { double dlogp = dlogZ[i, j]; // for now, we don't compute the second derivative. double ddlogp = -1; result[i, j] = Gaussian.FromDerivatives(A[i, j].Point, dlogp, ddlogp, false); } } return(result); }