/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="InnerProductOpBase"]/message_doc[@name="AAverageConditional(Gaussian, Vector, DenseVector, PositiveDefiniteMatrix, VectorGaussian)"]/*'/> public static VectorGaussian AAverageConditional([SkipIfUniform] Gaussian innerProduct, Vector A, DenseVector BMean, PositiveDefiniteMatrix BVariance, VectorGaussian result) { if (innerProduct.IsUniform()) { return(VectorGaussian.Uniform(A.Count)); } // logZ = log N(mProduct; A'*BMean, vProduct + A'*BVariance*A) // = -0.5 (mProduct - A'*BMean)^2 / (vProduct + A'*BVariance*A) -0.5 log(vProduct + A'*BVariance*A) // v*innerProduct.Precision double v = 1 + BVariance.QuadraticForm(A, A) * innerProduct.Precision; double diff = innerProduct.MeanTimesPrecision - A.Inner(BMean) * innerProduct.Precision; // dlogZ/dA = BMean * (mProduct - A'*BMean)/v + (BVariance*A) (diff)^2 / v^2 - (BVariance*A)/v double diff2 = diff * diff; double v2 = v * v; var avb = BVariance * A; var avbPrec = avb * innerProduct.Precision; var dlogZ = (BMean * diff - avbPrec) / v + avb * diff2 / v2; // -ddlogZ/dA^2 = (BMean.Outer(BMean) + BVariance) / v + avb.Outer(avb) * (4 * diff2 / (v2 * v)) // -(avb.Outer(avb - BMean * (2 * diff)) * 2 + BVariance * diff2) / v2; PositiveDefiniteMatrix negativeHessian = BVariance * (innerProduct.Precision / v - diff2 / v2); negativeHessian.SetToSumWithOuter(negativeHessian, innerProduct.Precision / v, BMean, BMean); negativeHessian.SetToSumWithOuter(negativeHessian, 4 * diff2 / (v2 * v) - 2 * innerProduct.Precision / v2, avb, avbPrec); negativeHessian.SetToSumWithOuter(negativeHessian, 2 * diff / v2, avbPrec, BMean); negativeHessian.SetToSumWithOuter(negativeHessian, 2 * diff / v2, BMean, avbPrec); negativeHessian.Symmetrize(); return(VectorGaussian.FromDerivatives(A, dlogZ, negativeHessian, GaussianProductOp.ForceProper)); }
/// <summary>VMP message to <c>A</c>.</summary> /// <param name="sum">Incoming message from <c>Sum</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="A">Incoming message from <c>A</c>. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <param name="B">Incoming message from <c>B</c>. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <param name="MeanOfB">Buffer <c>MeanOfB</c>.</param> /// <param name="CovarianceOfB">Buffer <c>CovarianceOfB</c>.</param> /// <param name="result">Modified to contain the outgoing message.</param> /// <returns> /// <paramref name="result" /> /// </returns> /// <remarks> /// <para>The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except <c>A</c>. Because the factor is deterministic, <c>Sum</c> is integrated out before taking the logarithm. The formula is <c>exp(sum_(B) p(B) log(sum_Sum p(Sum) factor(Sum,A,B)))</c>.</para> /// </remarks> /// <exception cref="ImproperMessageException"> /// <paramref name="sum" /> is not a proper distribution.</exception> /// <exception cref="ImproperMessageException"> /// <paramref name="A" /> is not a proper distribution.</exception> /// <exception cref="ImproperMessageException"> /// <paramref name="B" /> is not a proper distribution.</exception> public static DistributionStructArray <Bernoulli, bool> AAverageLogarithm( [SkipIfUniform] Gaussian sum, [Proper] DistributionStructArray <Bernoulli, bool> A, [Proper] VectorGaussian B, Vector MeanOfB, PositiveDefiniteMatrix CovarianceOfB, DistributionStructArray <Bernoulli, bool> result) { double mu = sum.GetMean(); var Ebbt = new PositiveDefiniteMatrix(A.Count, A.Count); Ebbt.SetToSumWithOuter(CovarianceOfB, 1, MeanOfB, MeanOfB); var ma = A.Select(x => x.GetMean()).ToArray(); for (int i = 0; i < A.Count; i++) { double term1 = 0.0; for (int j = 0; j < A.Count; j++) { if (j != i) { term1 += ma[i] * Ebbt[i, j]; } } var ri = result[i]; ri.LogOdds = -.5 * sum.Precision * (2.0 * term1 + Ebbt[i, i] - 2.0 * mu * MeanOfB[i]); result[i] = ri; } return(result); }
/// <summary> /// VMP message to 'A' /// </summary> /// <param name="X">Incoming message from 'X'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="A">Incoming message from 'A'.</param> /// <param name="B">Incoming message from 'B'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <param name="MeanOfB">Buffer 'MeanOfB'.</param> /// <param name="CovarianceOfB">Buffer 'CovarianceOfB'.</param> /// <param name="result">Modified to contain the outgoing message</param> /// <returns><paramref name="result"/></returns> /// <remarks><para> /// The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except 'A'. /// Because the factor is deterministic, 'X' is integrated out before taking the logarithm. /// The formula is <c>exp(sum_(B) p(B) log(sum_X p(X) factor(X,A,B)))</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="X"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception> public static GaussianArray AAverageLogarithm([SkipIfUniform] Gaussian X, GaussianArray A, [SkipIfUniform] VectorGaussian B, Vector MeanOfB, PositiveDefiniteMatrix CovarianceOfB, /*PositiveDefiniteMatrix Ebbt,*/ GaussianArray result) { int inner = MeanOfB.Count; if (result == null) { result = new GaussianArray(inner); } // E[log N(x[i,j]; a[i,:]*b[:,j], 0)] = -0.5 E[(x[i,j]- sum_k a[i,k]*b[k,j])^2]/0 // = -0.5 (E[x[i,j]^2] - 2 E[x[i,j]] a[i,k] E[b[k,j]] + a[i,k] a[i,k2] E(b[k,j] b[k2,j]))/0 // a[i,k] * (-2 E[x[i,j]] E[b[k,j]] + sum_{k2 not k} E[a[i,k2]] E(b[k,j] b[k2,j])) // a[i,k]^2 * E(b[k,j]^2) // message to a[i,k] = N(a; inv(prec[i,k])*(sum_j E[b[k,j]]*res[i,j,k]/var(x[i,j])), inv(prec[i,k])) // where res[i,j,k] = E[x[i,j]] - sum_{k2 not k} E[a[i,k2]] E[b[k2,j]] // prec[i,k] = sum_j E(b[k,j]^2)/var(x[i,j]) // result.Precision = prec[i,k] // result.MeanTimesPrecision = sum_j E[b[k,j]]*res[i,j,k]/var(x[i,j]) // = sum_j E[b[k,j]]*(X.MeanTimesPrecision - X.precision*(sum_{k2 not k})) var Ebbt = new PositiveDefiniteMatrix(inner, inner); // should we be caching this too? Ebbt.SetToSumWithOuter(CovarianceOfB, 1, MeanOfB, MeanOfB); //var ma = A.Select(z => z.GetMean()).ToArray(); var ma = new double[inner]; for (int k = 0; k < inner; k++) { ma[k] = A[k].GetMean(); } for (int k = 0; k < inner; k++) { double prec = 0.0; double pm = 0.0; prec += Ebbt[k, k] * X.Precision; double sum = 0.0; for (int r = 0; r < inner; r++) { if (r != k) { sum += Ebbt[r, k] * ma[r]; } } pm += MeanOfB[k] * X.MeanTimesPrecision - X.Precision * sum; Gaussian rk = result[k]; rk.Precision = prec; if (prec < 0) { throw new ApplicationException("improper message"); } rk.MeanTimesPrecision = pm; result[k] = rk; } return(result); }
/// <summary> /// Update the buffer 'CovarianceOfB' /// </summary> /// <param name="B">Incoming message from 'B'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <returns>New value of buffer 'CovarianceOfB'</returns> /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception> public static PositiveDefiniteMatrix Eaat(GaussianArray A, PositiveDefiniteMatrix result) { int inner = A.Count; var VarianceOfA = Vector.Zero(inner); var MeanOfA = Vector.Zero(inner); for (int k = 0; k < inner; k++) { MeanOfA[k] = A[k].GetMean(); VarianceOfA[k] = A[k].GetVariance(); } result.SetToDiagonal(VarianceOfA); result.SetToSumWithOuter(result, 1, MeanOfA, MeanOfA); return result; }
/// <summary> /// Update the buffer 'CovarianceOfB' /// </summary> /// <param name="B">Incoming message from 'B'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <returns>New value of buffer 'CovarianceOfB'</returns> /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception> public static PositiveDefiniteMatrix Eaat(GaussianArray A, PositiveDefiniteMatrix result) { int inner = A.Count; var VarianceOfA = Vector.Zero(inner); var MeanOfA = Vector.Zero(inner); for (int k = 0; k < inner; k++) { MeanOfA[k] = A[k].GetMean(); VarianceOfA[k] = A[k].GetVariance(); } result.SetToDiagonal(VarianceOfA); result.SetToSumWithOuter(result, 1, MeanOfA, MeanOfA); return(result); }
/// <summary> /// Adds a weighted observation. /// </summary> /// <param name="x"></param> /// <param name="weight"></param> public void Add(Vector x, double weight) { // new_mean = mean + w/(count + w)*(x - mean) // new_cov = count/(count + w)*(cov + w/(count+w)*(x-mean)*(x-mean)') count += weight; if (count == 0) { return; } diff.SetToDifference(x, mean); double s = weight / count; mean.SetToSum(1.0, mean, s, diff); //outer.SetToOuter(diff,diff2); // this is more numerically stable: //outer.SetToOuter(diff, diff).Scale(s); cov.SetToSumWithOuter(cov, s, diff, diff); cov.Scale(1 - s); }
/// <summary> /// VMP message to 'A' /// </summary> /// <param name="sum">Incoming message from 'Sum'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="A">Incoming message from 'A'. Must be a proper distribution. If all elements are uniform, the result will be uniform.</param> /// <param name="B">Incoming message from 'B'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <param name="MeanOfB">Buffer 'MeanOfB'.</param> /// <param name="CovarianceOfB">Buffer 'CovarianceOfB'.</param> /// <param name="result">Modified to contain the outgoing message</param> /// <returns><paramref name="result"/></returns> /// <remarks><para> /// The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except 'A'. /// Because the factor is deterministic, 'Sum' is integrated out before taking the logarithm. /// The formula is <c>exp(sum_(B) p(B) log(sum_Sum p(Sum) factor(Sum,A,B)))</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="sum"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception> public static DistributionStructArray<Bernoulli, bool> AAverageLogarithm([SkipIfUniform] Gaussian sum, [Proper] DistributionStructArray<Bernoulli, bool> A, [Proper] VectorGaussian B, Vector MeanOfB, PositiveDefiniteMatrix CovarianceOfB, DistributionStructArray<Bernoulli, bool> result) { double mu = sum.GetMean(); var Ebbt = new PositiveDefiniteMatrix(A.Count, A.Count); Ebbt.SetToSumWithOuter(CovarianceOfB, 1, MeanOfB, MeanOfB); var ma = A.Select(x => x.GetMean()).ToArray(); for (int i = 0; i < A.Count; i++) { double term1 = 0.0; for (int j = 0; j < A.Count; j++) if (j != i) term1 += ma[i] * Ebbt[i, j]; var ri = result[i]; ri.LogOdds = -.5 * sum.Precision * (2.0 * term1 + Ebbt[i, i] - 2.0 * mu * MeanOfB[i]); result[i] = ri; } return result; }
/// <summary> /// Update the buffer 'CovarianceOfB' /// </summary> /// <param name="B">Incoming message from 'B'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <returns>New value of buffer 'CovarianceOfB'</returns> /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception> public static PositiveDefiniteMatrix Ebbt(PositiveDefiniteMatrix CovarianceOfB, Vector MeanOfB, PositiveDefiniteMatrix result) { result.SetToSumWithOuter(CovarianceOfB, 1, MeanOfB, MeanOfB); return result; }
/// <summary> /// VMP message to 'A' /// </summary> /// <param name="X">Incoming message from 'X'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="A">Incoming message from 'A'.</param> /// <param name="B">Incoming message from 'B'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <param name="MeanOfB">Buffer 'MeanOfB'.</param> /// <param name="CovarianceOfB">Buffer 'CovarianceOfB'.</param> /// <param name="result">Modified to contain the outgoing message</param> /// <returns><paramref name="result"/></returns> /// <remarks><para> /// The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except 'A'. /// Because the factor is deterministic, 'X' is integrated out before taking the logarithm. /// The formula is <c>exp(sum_(B) p(B) log(sum_X p(X) factor(X,A,B)))</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="X"/> is not a proper distribution</exception> /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception> public static GaussianArray AAverageLogarithm([SkipIfUniform] Gaussian X, GaussianArray A, [SkipIfUniform] VectorGaussian B, Vector MeanOfB, PositiveDefiniteMatrix CovarianceOfB, /*PositiveDefiniteMatrix Ebbt,*/ GaussianArray result) { int inner = MeanOfB.Count; if (result == null) result = new GaussianArray(inner); // E[log N(x[i,j]; a[i,:]*b[:,j], 0)] = -0.5 E[(x[i,j]- sum_k a[i,k]*b[k,j])^2]/0 // = -0.5 (E[x[i,j]^2] - 2 E[x[i,j]] a[i,k] E[b[k,j]] + a[i,k] a[i,k2] E(b[k,j] b[k2,j]))/0 // a[i,k] * (-2 E[x[i,j]] E[b[k,j]] + sum_{k2 not k} E[a[i,k2]] E(b[k,j] b[k2,j])) // a[i,k]^2 * E(b[k,j]^2) // message to a[i,k] = N(a; inv(prec[i,k])*(sum_j E[b[k,j]]*res[i,j,k]/var(x[i,j])), inv(prec[i,k])) // where res[i,j,k] = E[x[i,j]] - sum_{k2 not k} E[a[i,k2]] E[b[k2,j]] // prec[i,k] = sum_j E(b[k,j]^2)/var(x[i,j]) // result.Precision = prec[i,k] // result.MeanTimesPrecision = sum_j E[b[k,j]]*res[i,j,k]/var(x[i,j]) // = sum_j E[b[k,j]]*(X.MeanTimesPrecision - X.precision*(sum_{k2 not k})) var Ebbt = new PositiveDefiniteMatrix(inner, inner); // should we be caching this too? Ebbt.SetToSumWithOuter(CovarianceOfB, 1, MeanOfB, MeanOfB); //var ma = A.Select(z => z.GetMean()).ToArray(); var ma = new double[inner]; for (int k = 0; k < inner; k++) ma[k] = A[k].GetMean(); for (int k = 0; k < inner; k++) { double prec = 0.0; double pm = 0.0; prec += Ebbt[k, k] * X.Precision; double sum = 0.0; for (int r = 0; r < inner; r++) if (r != k) sum += Ebbt[r, k] * ma[r]; pm += MeanOfB[k] * X.MeanTimesPrecision - X.Precision * sum; Gaussian rk = result[k]; rk.Precision = prec; if (prec < 0) throw new ApplicationException("improper message"); rk.MeanTimesPrecision = pm; result[k] = rk; } return result; }
/// <summary> /// Update the buffer 'CovarianceOfB' /// </summary> /// <param name="B">Incoming message from 'B'. Must be a proper distribution. If any element is uniform, the result will be uniform.</param> /// <returns>New value of buffer 'CovarianceOfB'</returns> /// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception> public static PositiveDefiniteMatrix Ebbt(PositiveDefiniteMatrix CovarianceOfB, Vector MeanOfB, PositiveDefiniteMatrix result) { result.SetToSumWithOuter(CovarianceOfB, 1, MeanOfB, MeanOfB); return(result); }