Beispiel #1
0
        /// <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));
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <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;
		}
Beispiel #5
0
        /// <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);
        }
Beispiel #7
0
		/// <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;
		}
Beispiel #10
0
 /// <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);
 }