コード例 #1
0
		/// <summary>
		/// VMP message to 'matrixMultiply'
		/// </summary>
		/// <param name="A">Incoming message from 'A'. Must be a proper distribution.  If any element is 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="result">Modified to contain the outgoing message</param>
		/// <returns><paramref name="result"/></returns>
		/// <remarks><para>
		/// The outgoing message is a distribution matching the moments of 'matrixMultiply' as the random arguments are varied.
		/// The formula is <c>proj[sum_(A,B) p(A,B) factor(matrixMultiply,A,B)]</c>.
		/// </para></remarks>
		/// <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 GaussianArray2D MatrixMultiplyAverageLogarithm([SkipIfUniform] DistributionArray2D<Gaussian> A, [SkipIfUniform] DistributionArray2D<Gaussian> B, GaussianArray2D result)
		{
			if (result == null) result = new DistributionStructArray2D<Gaussian, double>(A.GetLength(0), B.GetLength(1));
			// x[i,j] = sum_k a[i,k]*b[k,j]
			// E(x[i,j]) = sum_k E(a[i,k])*E(b[k,j])
			// var(x[i,j]) = sum_k E(a[i,k])^2*var(b[k,j]) + var(a[i,k])*E(b[k,j])^2 + var(a[i,k])*var(b[k,j])
			int rows = result.GetLength(0);
			int cols = result.GetLength(1);
			int inner = A.GetLength(1);
			for (int i = 0; i < rows; i++) {
				for (int j = 0; j < cols; j++) {
					double mean = 0; double var = 0;
					for (int k = 0; k < inner; k++) {
						double Am, Av, Bm, Bv;
						A[i, k].GetMeanAndVariance(out Am, out Av);
						B[k, j].GetMeanAndVariance(out Bm, out Bv);
						mean += Am * Bm;
						var += Av * Bm * Bm + Bv * Am * Am + Av * Bv;
					}
					Gaussian rij = result[i, j];
					rij.SetMeanAndVariance(mean, var);
					result[i, j] = rij;
				}
			}
			return result;
		}
コード例 #2
0
        /// <summary>
        /// VMP message to 'matrixMultiply'
        /// </summary>
        /// <param name="A">Incoming message from 'A'. Must be a proper distribution.  If any element is 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="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'matrixMultiply' as the random arguments are varied.
        /// The formula is <c>proj[sum_(A,B) p(A,B) factor(matrixMultiply,A,B)]</c>.
        /// </para></remarks>
        /// <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 GaussianArray2D MatrixMultiplyAverageLogarithm([SkipIfUniform] DistributionArray2D <Gaussian> A, [SkipIfUniform] DistributionArray2D <Gaussian> B, GaussianArray2D result)
        {
            if (result == null)
            {
                result = new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), B.GetLength(1));
            }
            // x[i,j] = sum_k a[i,k]*b[k,j]
            // E(x[i,j]) = sum_k E(a[i,k])*E(b[k,j])
            // var(x[i,j]) = sum_k E(a[i,k])^2*var(b[k,j]) + var(a[i,k])*E(b[k,j])^2 + var(a[i,k])*var(b[k,j])
            int rows  = result.GetLength(0);
            int cols  = result.GetLength(1);
            int inner = A.GetLength(1);

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    double mean = 0; double var = 0;
                    for (int k = 0; k < inner; k++)
                    {
                        double Am, Av, Bm, Bv;
                        A[i, k].GetMeanAndVariance(out Am, out Av);
                        B[k, j].GetMeanAndVariance(out Bm, out Bv);
                        mean += Am * Bm;
                        var  += Av * Bm * Bm + Bv * Am * Am + Av * Bv;
                    }
                    Gaussian rij = result[i, j];
                    rij.SetMeanAndVariance(mean, var);
                    result[i, j] = rij;
                }
            }
            return(result);
        }
コード例 #3
0
        /// <summary>
        /// VMP message to 'A'
        /// </summary>
        /// <param name="matrixMultiply">Incoming message from 'matrixMultiply'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
        /// <param name="A">Incoming message from 'A'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
        /// <param name="B">Constant value for 'B'.</param>
        /// <param name="to_A">Previous outgoing message to 'A'.</param>
        /// <returns>The outgoing VMP message to the 'A' argument</returns>
        /// <remarks><para>
        /// The outgoing message is the factor viewed as a function of 'A' with 'matrixMultiply' integrated out.
        /// The formula is <c>sum_matrixMultiply p(matrixMultiply) factor(matrixMultiply,A,B)</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="matrixMultiply"/> is not a proper distribution</exception>
        /// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
        public static GaussianArray2D AAverageLogarithm([SkipIfUniform] GaussianArray2D matrixMultiply, [Proper, Stochastic] GaussianArray2D A, double[,] B, GaussianArray2D to_A)
        {
            GaussianArray2D result = to_A;

            if (result == null)
            {
                result = new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), A.GetLength(1));
            }
            int rows  = matrixMultiply.GetLength(0);
            int cols  = matrixMultiply.GetLength(1);
            int inner = A.GetLength(1);

            double[] ab = new double[cols];
            //Gaussian temp = new Gaussian();
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    double sum = 0.0;
                    for (int k = 0; k < inner; k++)
                    {
                        sum += A[i, k].GetMean() * B[k, j];
                    }
                    ab[j] = sum;
                }
                for (int k = 0; k < inner; k++)
                {
                    double prec = 0.0;
                    double pm   = 0.0;
                    double Am   = A[i, k].GetMean();
                    for (int j = 0; j < cols; j++)
                    {
                        double   Bm = B[k, j];
                        Gaussian x  = matrixMultiply[i, j];
                        prec += (Bm * Bm) * x.Precision;
                        //pm += Bm * (x.MeanTimesPrecision - x.Precision * (ab[j] - Am * Bm));
                        //Replace previous line with:
                        ab[j] -= Am * Bm;
                        pm    += Bm * (x.MeanTimesPrecision - x.Precision * ab[j]);
                    }

                    Gaussian old_result = (Gaussian)result[i, k].Clone();
                    Gaussian rik        = result[i, k];
                    rik.Precision          = prec;
                    rik.MeanTimesPrecision = pm;
                    result[i, k]           = rik;
                    Gaussian partial      = A[i, k] / old_result;
                    Gaussian newPosterior = partial * rik;
                    Am = newPosterior.GetMean();
                    for (int j = 0; j < cols; j++)
                    {
                        ab[j] += Am * B[k, j];
                    }
                }
            }
            return(result);
        }
コード例 #4
0
        /// <summary>
        /// VMP message to 'X'.
        /// </summary>
        /// <param name="A">Incoming message from 'a'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
        /// <param name="B">Incoming message from 'b'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
        /// <returns>The outgoing VMP message to the 'X' argument.</returns>
        /// <remarks><para>
        /// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'innerProduct'.
        /// The formula is <c>int log(f(innerProduct,x)) q(x) dx</c> where <c>x = (a,b)</c>.
        /// </para></remarks>
        /// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
        /// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
        public static GaussianArray2D XAverageLogarithm([SkipIfAllUniform] VectorGaussianArray A, [SkipIfAllUniform] VectorGaussianArray B, GaussianArray2D result)
        {
            int I = A.GetLength(0), J = B.Count, K = A[0].Dimension;

            if (result == null)
            {
                result = new DistributionStructArray2D <Gaussian, double>(I, J);
            }
            // p(x|a,b) = N(E[a]'*E[b], E[b]'*var(a)*E[b] + E[a]'*var(b)*E[a] + trace(var(a)*var(b)))
            var ma = new Vector[I];
            var mb = new Vector[J];
            var va = new PositiveDefiniteMatrix[I];
            var vb = new PositiveDefiniteMatrix[J];

            for (int i = 0; i < I; i++)
            {
                ma[i] = Vector.Zero(K);
                va[i] = new PositiveDefiniteMatrix(K, K);
                A[i].GetMeanAndVariance(ma[i], va[i]);
            }
            for (int j = 0; j < J; j++)
            {
                mb[j] = Vector.Zero(K);
                vb[j] = new PositiveDefiniteMatrix(K, K);
                B[j].GetMeanAndVariance(mb[j], vb[j]);
            }
            // Uses John Winn's rule for deterministic factors.
            // Strict variational inference would set the variance to 0.
            for (int i = 0; i < I; i++)
            {
                for (int j = 0; j < J; j++)
                {
                    var rij = result[i, j];
                    rij.SetMeanAndVariance(ma[i].Inner(mb[j]), va[i].QuadraticForm(mb[j]) + vb[j].QuadraticForm(ma[i]) + va[i].Inner(vb[j]));
                    result[i, j] = rij;
                }
            }
            return(result);
        }
コード例 #5
0
		/// <summary>
		/// VMP message to 'A'
		/// </summary>
		/// <param name="matrixMultiply">Incoming message from 'matrixMultiply'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
		/// <param name="A">Incoming message from 'A'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
		/// <param name="B">Constant value for 'B'.</param>
		/// <param name="to_A">Previous outgoing message to 'A'.</param>
		/// <returns>The outgoing VMP message to the 'A' argument</returns>
		/// <remarks><para>
		/// The outgoing message is the factor viewed as a function of 'A' with 'matrixMultiply' integrated out.
		/// The formula is <c>sum_matrixMultiply p(matrixMultiply) factor(matrixMultiply,A,B)</c>.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="matrixMultiply"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
		public static GaussianArray2D AAverageLogarithm([SkipIfUniform] GaussianArray2D matrixMultiply, [Proper, Stochastic] GaussianArray2D A, double[,] B, GaussianArray2D to_A)
		{
			GaussianArray2D result = to_A;
			if (result == null) result = new DistributionStructArray2D<Gaussian, double>(A.GetLength(0), A.GetLength(1));
			int rows = matrixMultiply.GetLength(0);
			int cols = matrixMultiply.GetLength(1);
			int inner = A.GetLength(1);
			double[] ab = new double[cols];
			//Gaussian temp = new Gaussian();
			for (int i = 0; i < rows; i++) {
				for (int j = 0; j < cols; j++) {
					double sum = 0.0;
					for (int k = 0; k < inner; k++) {
						sum += A[i, k].GetMean() * B[k, j];
					}
					ab[j] = sum;
				}
				for (int k = 0; k < inner; k++) {
					double prec = 0.0;
					double pm = 0.0;
					double Am = A[i, k].GetMean();
					for (int j = 0; j < cols; j++) {
						double Bm = B[k, j];
						Gaussian x = matrixMultiply[i, j];
						prec += (Bm * Bm) * x.Precision;
						//pm += Bm * (x.MeanTimesPrecision - x.Precision * (ab[j] - Am * Bm));
						//Replace previous line with:
						ab[j] -= Am * Bm;
						pm += Bm * (x.MeanTimesPrecision - x.Precision * ab[j]);
					}

					Gaussian old_result = (Gaussian)result[i, k].Clone();
					Gaussian rik = result[i, k];
					rik.Precision = prec;
					rik.MeanTimesPrecision = pm;
					result[i, k] = rik;
					Gaussian partial = A[i, k] / old_result;
					Gaussian newPosterior = partial * rik;
					Am = newPosterior.GetMean();
					for (int j = 0; j < cols; j++) ab[j] += Am * B[k, j];
				}
			}
			return result;
		}
コード例 #6
0
		/// <summary>
		/// VMP message to 'A'
		/// </summary>
		/// <param name="matrixMultiply">Incoming message from 'matrixMultiply'. Must be a proper distribution.  If any element is 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="to_A">Previous outgoing message to 'A'.</param>
		/// <returns>The outgoing VMP message to the 'A' argument</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, 'matrixMultiply' is integrated out before taking the logarithm.
		/// The formula is <c>exp(sum_(B) p(B) log(sum_matrixMultiply p(matrixMultiply) factor(matrixMultiply,A,B)))</c>.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="matrixMultiply"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="B"/> is not a proper distribution</exception>
		public static GaussianArray2D AAverageLogarithm([SkipIfUniform] GaussianArray2D matrixMultiply, [Stochastic] GaussianArray2D A, [SkipIfUniform] GaussianArray2D B, GaussianArray2D to_A)
		{
			GaussianArray2D result = to_A;
			if (result == null) result = new DistributionStructArray2D<Gaussian, double>(A.GetLength(0), A.GetLength(1));
			// 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}))
			int rows = matrixMultiply.GetLength(0);
			int cols = matrixMultiply.GetLength(1);
			int inner = A.GetLength(1);
			double[] ab = new double[cols];
			//Gaussian temp = new Gaussian();
			for (int i = 0; i < rows; i++) {
				for (int j = 0; j < cols; j++) {
					double sum = 0.0;
					for (int k = 0; k < inner; k++) {
						sum += A[i, k].GetMean() * B[k, j].GetMean();
					}
					ab[j] = sum;
				}
				for (int k = 0; k < inner; k++) {
					double prec = 0.0;
					double pm = 0.0;
					double Am = A[i, k].GetMean();
					for (int j = 0; j < cols; j++) {
						double Bm, Bv;
						B[k, j].GetMeanAndVariance(out Bm, out Bv);
						Gaussian x = matrixMultiply[i, j];
						prec += (Bv + Bm * Bm) * x.Precision;
						//pm += Bm * (x.MeanTimesPrecision - x.Precision * (ab[j] - Am * Bm));
						//Replace previous line with:
						ab[j] -= Am * Bm;
						pm += Bm * (x.MeanTimesPrecision - x.Precision * ab[j]);
					}

					Gaussian old_result = (Gaussian)result[i, k].Clone();
					Gaussian rik = result[i, k];
					rik.Precision = prec;
					rik.MeanTimesPrecision = pm;
					result[i, k] = rik;
					Gaussian partial = A[i, k] / old_result;
					Gaussian newPosterior = partial * rik;
					Am = newPosterior.GetMean();
					for (int j = 0; j < cols; j++) ab[j] += Am * B[k, j].GetMean();
				}
			}
			return result;
		}
 /// <summary>
 /// VMP message to 'X'.
 /// </summary>
 /// <param name="A">Incoming message from 'a'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
 /// <param name="B">Incoming message from 'b'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
 /// <returns>The outgoing VMP message to the 'X' argument.</returns>
 /// <remarks><para>
 /// The outgoing message is the exponential of the integral of the log-factor times incoming messages, over all arguments except 'innerProduct'.
 /// The formula is <c>int log(f(innerProduct,x)) q(x) dx</c> where <c>x = (a,b)</c>.
 /// </para></remarks>
 /// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
 /// <exception cref="ImproperMessageException"><paramref name="A"/> is not a proper distribution</exception>
 public static GaussianArray2D XAverageLogarithm([SkipIfAllUniform] VectorGaussianArray A, [SkipIfAllUniform] VectorGaussianArray B, GaussianArray2D result)
 {
     int I = A.GetLength(0), J = B.Count, K = A[0].Dimension;
     if (result == null) result = new DistributionStructArray2D<Gaussian, double>(I, J);
     // p(x|a,b) = N(E[a]'*E[b], E[b]'*var(a)*E[b] + E[a]'*var(b)*E[a] + trace(var(a)*var(b)))
     var ma = new Vector[I];
     var mb = new Vector[J];
     var va = new PositiveDefiniteMatrix[I];
     var vb = new PositiveDefiniteMatrix[J];
     for (int i = 0; i < I; i++)
     {
         ma[i] = Vector.Zero(K);
         va[i] = new PositiveDefiniteMatrix(K, K);
         A[i].GetMeanAndVariance(ma[i], va[i]);
     }
     for (int j = 0; j < J; j++)
     {
         mb[j] = Vector.Zero(K);
         vb[j] = new PositiveDefiniteMatrix(K, K);
         B[j].GetMeanAndVariance(mb[j], vb[j]);
     }
     // Uses John Winn's rule for deterministic factors.
     // Strict variational inference would set the variance to 0.
     for (int i = 0; i < I; i++)
         for (int j = 0; j < J; j++)
         {
             var rij = result[i, j];
             rij.SetMeanAndVariance(ma[i].Inner(mb[j]), va[i].QuadraticForm(mb[j]) + vb[j].QuadraticForm(ma[i]) + va[i].Inner(vb[j]));
             result[i, j] = rij;
         }
     return result;
 }
コード例 #8
0
        /// <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);
        }
コード例 #9
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixMultiplyOp"]/message_doc[@name="AAverageLogarithm(DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double}, double[,], DistributionStructArray2D{Gaussian, double})"]/*'/>
        public static GaussianArray2D AAverageLogarithm(
            [SkipIfUniform] GaussianArray2D matrixMultiply, [Proper, Stochastic] GaussianArray2D A, double[,] B, GaussianArray2D to_A)
        {
            GaussianArray2D result = to_A;

            if (result == null)
            {
                result = new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), A.GetLength(1));
            }
            int rows  = matrixMultiply.GetLength(0);
            int cols  = matrixMultiply.GetLength(1);
            int inner = A.GetLength(1);

            double[] ab = new double[cols];
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    double sum = 0.0;
                    for (int k = 0; k < inner; k++)
                    {
                        sum += A[i, k].GetMean() * B[k, j];
                    }
                    ab[j] = sum;
                }
                for (int k = 0; k < inner; k++)
                {
                    Gaussian old_result = result[i, k];
                    Gaussian rik        = Gaussian.Uniform();
                    double   Am         = A[i, k].GetMean();
                    for (int j = 0; j < cols; j++)
                    {
                        double Bm = B[k, j];
                        if (Bm == 0)
                        {
                            continue;
                        }
                        Gaussian x = matrixMultiply[i, j];
                        ab[j] -= Am * Bm;
                        Gaussian msg;
                        if (x.IsPointMass)
                        {
                            msg = Gaussian.PointMass(x.Point / Bm);
                        }
                        else
                        {
                            double prec = (Bm * Bm) * x.Precision;
                            //pm += Bm * (x.MeanTimesPrecision - x.Precision * (ab[j] - Am * Bm));
                            //Replace previous line with:
                            double pm = Bm * (x.MeanTimesPrecision - x.Precision * ab[j]);
                            msg = Gaussian.FromNatural(pm, prec);
                        }
                        rik.SetToProduct(rik, msg);
                    }
                    result[i, k] = rik;
                    Gaussian partial      = A[i, k] / old_result;
                    Gaussian newPosterior = partial * rik;
                    Am = newPosterior.GetMean();
                    for (int j = 0; j < cols; j++)
                    {
                        ab[j] += Am * B[k, j];
                    }
                }
            }
            return(result);
        }
コード例 #10
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixMultiplyOp"]/message_doc[@name="AAverageLogarithm(DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double}, DistributionStructArray2D{Gaussian, double})"]/*'/>
        public static GaussianArray2D AAverageLogarithm(
            [SkipIfUniform] GaussianArray2D matrixMultiply, [Stochastic] GaussianArray2D A, [SkipIfUniform] GaussianArray2D B, GaussianArray2D to_A)
        {
            GaussianArray2D result = to_A;

            if (result == null)
            {
                result = new DistributionStructArray2D <Gaussian, double>(A.GetLength(0), A.GetLength(1));
            }
            // 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}))
            int rows  = matrixMultiply.GetLength(0);
            int cols  = matrixMultiply.GetLength(1);
            int inner = A.GetLength(1);

            double[] ab = new double[cols];
            //Gaussian temp = new Gaussian();
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    double sum = 0.0;
                    for (int k = 0; k < inner; k++)
                    {
                        sum += A[i, k].GetMean() * B[k, j].GetMean();
                    }
                    ab[j] = sum;
                }
                for (int k = 0; k < inner; k++)
                {
                    Gaussian old_result = result[i, k];
                    Gaussian rik        = Gaussian.Uniform();
                    double   Am         = A[i, k].GetMean();
                    for (int j = 0; j < cols; j++)
                    {
                        double Bm, Bv;
                        B[k, j].GetMeanAndVariance(out Bm, out Bv);
                        if (Bm == 0)
                        {
                            continue;
                        }
                        Gaussian x = matrixMultiply[i, j];
                        ab[j] -= Am * Bm;
                        Gaussian msg;
                        if (x.IsPointMass)
                        {
                            msg = Gaussian.PointMass((x.Point * Bm) / (Bv + Bm * Bm));
                        }
                        else
                        {
                            double prec = (Bv + Bm * Bm) * x.Precision;
                            //pm += Bm * (x.MeanTimesPrecision - x.Precision * (ab[j] - Am * Bm));
                            //Replace previous line with:
                            double pm = Bm * (x.MeanTimesPrecision - x.Precision * ab[j]);
                            msg = Gaussian.FromNatural(pm, prec);
                        }
                        rik.SetToProduct(rik, msg);
                    }
                    result[i, k] = rik;
                    Gaussian partial      = A[i, k] / old_result;
                    Gaussian newPosterior = partial * rik;
                    Am = newPosterior.GetMean();
                    for (int j = 0; j < cols; j++)
                    {
                        ab[j] += Am * B[k, j].GetMean();
                    }
                }
            }
            return(result);
        }