Beispiel #1
0
		/// Generate LDA data - returns an array of dictionaries mapping unique word index
		/// to word count per document.
		/// <param name="trueTheta">Known Theta</param>
		/// <param name="truePhi">Known Phi</param>
		/// <param name="averageNumWords">Average number of words to sample per doc</param>
		/// <returns></returns>
		public static Dictionary<int, int>[] GenerateLDAData(Dirichlet[] trueTheta, Dirichlet[] truePhi, int averageNumWords)
		{
			int numVocab = truePhi[0].Dimension;
			int numTopics = truePhi.Length;
			int numDocs = trueTheta.Length;

			// Sample from the model
			Vector[] topicDist = new Vector[numDocs];
			Vector[] wordDist = new Vector[numTopics];
			for (int i = 0; i < numDocs; i++)
				topicDist[i] = trueTheta[i].Sample();
			for (int i = 0; i < numTopics; i++)
				wordDist[i] = truePhi[i].Sample();

			var wordCounts = new Dictionary<int, int>[numDocs];
			for (int i=0; i < numDocs; i++)
			{
				int LengthOfDoc = Poisson.Sample((double)averageNumWords);

				var counts = new Dictionary<int, int>();
				for (int j=0; j < LengthOfDoc; j++)
				{
					int topic = Discrete.Sample(topicDist[i]);
					int w = Discrete.Sample(wordDist[topic]);
					if (!counts.ContainsKey(w))
						counts.Add(w, 1);
					else
						counts[w] = counts[w] + 1;
				}
				wordCounts[i] = counts;
			}
			return wordCounts;
		}
 public void CanGetAlpha()
 {
     var d = new Dirichlet(0.3, 10);
     for (var i = 0; i < 10; i++)
     {
         Assert.AreEqual(0.3, d.Alpha[i]);
     }
 }
        public void CanCreateSymmetricDirichlet()
        {
            var d = new Dirichlet(0.3, 5);

            for (var i = 0; i < 5; i++)
            {
                Assert.AreEqual(0.3, d.Alpha[i]);
            }
        }
        public void CanGetAlpha()
        {
            Dirichlet d = new Dirichlet(0.3, 10);

            double[] alpha = new double[10];
            for (int i = 0; i < 10; i++)
            {
                Assert.AreEqual(0.3, d.Alpha[i]);
            }
        }
Beispiel #5
0
		/// <summary>
		/// Evidence message for EP
		/// </summary>
		/// <param name="sample">Incoming message from 'sample'.</param>
		/// <param name="trialCount">Constant value for 'trialCount'.</param>
		/// <param name="p">Incoming message from 'p'.</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(sum_(sample,p) p(sample,p) factor(sample,trialCount,p))</c>.
		/// </para></remarks>
		public static double LogAverageFactor(IList<int> sample, int trialCount, Dirichlet p)
		{
			double result = MMath.GammaLn(trialCount+1);
			for (int i = 0; i < sample.Count; i++) {
				result += MMath.GammaLn(sample[i]+p.PseudoCount[i]) + MMath.GammaLn(p.PseudoCount[i])
					-MMath.GammaLn(sample[i]+1);
			}
			result += MMath.GammaLn(p.TotalCount) - MMath.GammaLn(p.TotalCount + trialCount);
			return result;
		}
        public void CanCreateDirichlet()
        {
            var alpha = new double[10];
            for (var i = 0; i < 10; i++)
            {
                alpha[i] = i;
            }

            var d = new Dirichlet(alpha);

            for (var i = 0; i < 5; i++)
            {
                Assert.AreEqual(i, d.Alpha[i]);
            }
        }
Beispiel #7
0
		/// <summary>
		/// Randomly create true theta and phi arrays
		/// </summary>
		/// <param name="numVocab">Vocabulary size</param>
		/// <param name="numTopics">Number of topics</param>
		/// <param name="numDocs">Number of documents</param>
		/// <param name="averageDocLength">Avarage document length</param>
		/// <param name="trueTheta">Theta array (output)</param>
		/// <param name="truePhi">Phi array (output)</param>
		public static void CreateTrueThetaAndPhi(
			int numVocab, int numTopics, int numDocs, int averageDocLength, int averageWordsPerTopic,
			out Dirichlet[] trueTheta, out Dirichlet[] truePhi)
		{
			truePhi = new Dirichlet[numTopics];
			for (int i=0; i < numTopics; i++)
			{
				truePhi[i] = Dirichlet.Uniform(numVocab);
				truePhi[i].PseudoCount.SetAllElementsTo(0.0);
				// Draw the number of unique words in the topic.
				int numUniqueWordsPerTopic = Poisson.Sample((double)averageWordsPerTopic);
				if (numUniqueWordsPerTopic >= numVocab) numUniqueWordsPerTopic = numVocab;
				if (numUniqueWordsPerTopic < 1) numUniqueWordsPerTopic = 1;
				double expectedRepeatOfWordInTopic = 
					((double)numDocs) * averageDocLength / numUniqueWordsPerTopic;
				int[] shuffledWordIndices = Rand.Perm(numVocab);
				for (int j = 0; j < numUniqueWordsPerTopic; j++)
				{
					int wordIndex = shuffledWordIndices[j];
					// Draw the count for that word
					int cnt = Poisson.Sample(expectedRepeatOfWordInTopic);
					truePhi[i].PseudoCount[wordIndex] = cnt + 1.0;
				}
			}

			trueTheta = new Dirichlet[numDocs];
			for (int i=0; i < numDocs; i++)
			{
				trueTheta[i] = Dirichlet.Uniform(numTopics);
				trueTheta[i].PseudoCount.SetAllElementsTo(0.0);
				// Draw the number of unique topics in the doc.
				int numUniqueTopicsPerDoc = Math.Min(1 + Poisson.Sample(1.0), numTopics);
				double expectedRepeatOfTopicInDoc = 
					averageDocLength / numUniqueTopicsPerDoc;
				int[] shuffledTopicIndices = Rand.Perm(numTopics);
				for (int j = 0; j < numUniqueTopicsPerDoc; j++)
				{
					int topicIndex = shuffledTopicIndices[j];
					// Draw the count for that topic
					int cnt = Poisson.Sample(expectedRepeatOfTopicInDoc);
					trueTheta[i].PseudoCount[topicIndex] = cnt + 1.0;
				}
			}
		}
Beispiel #8
0
		/// <summary>
		/// Evidence message for EP
		/// </summary>
		/// <param name="prob">Incoming message from 'prob'.</param>
		/// <param name="mean">Constant value for 'mean'.</param>
		/// <param name="to_prob">Previous outgoing message to 'prob'.</param>
		/// <param name="totalCount">Constant value for 'totalCount'.</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(sum_(prob) p(prob) factor(prob,mean,totalCount))</c>.
		/// </para></remarks>
		public static double LogAverageFactor(Dirichlet prob, Vector mean, Dirichlet to_prob, double totalCount)
		{
			return to_prob.GetLogAverageOf(prob);
		}
        public void DiscreteFromDirichletOpTest()
        {
            Dirichlet probs4  = new Dirichlet(1.0, 2, 3, 4);
            Discrete  sample4 = new Discrete(0.4, 0.6, 0, 0);
            Dirichlet result4 = DiscreteFromDirichletOp.ProbsAverageConditional(sample4, probs4, Dirichlet.Uniform(4));

            Dirichlet probs3  = new Dirichlet(1.0, 2, 7);
            Discrete  sample3 = new Discrete(0.4, 0.6, 0);
            Dirichlet result3 = DiscreteFromDirichletOp.ProbsAverageConditional(sample3, probs3, Dirichlet.Uniform(3));

            for (int i = 0; i < 3; i++)
            {
                Assert.True(MMath.AbsDiff(result4.PseudoCount[i], result3.PseudoCount[i], 1e-6) < 1e-10);
            }

            Dirichlet probs2  = new Dirichlet(1.0, 2);
            Discrete  sample2 = new Discrete(0.4, 0.6);
            Dirichlet result2 = DiscreteFromDirichletOp.ProbsAverageConditional(sample2, probs2, Dirichlet.Uniform(2));

            Beta      beta      = new Beta(1.0, 2);
            Bernoulli bernoulli = new Bernoulli(0.4);
            Beta      result1   = BernoulliFromBetaOp.ProbTrueAverageConditional(bernoulli, beta);

            Assert.Equal(result2.PseudoCount[0], result1.TrueCount, 1e-10);
            Assert.Equal(result2.PseudoCount[1], result1.FalseCount, 1e-10);

            // test handling of small alphas
            Discrete sample = DiscreteFromDirichletOp.SampleAverageLogarithm(Dirichlet.Symmetric(2, 1e-8), Discrete.Uniform(2));

            Assert.True(sample.IsUniform());
        }
Beispiel #10
0
		/// <summary>
		/// Perform the quadrature required for the VMP evidence message
		/// </summary>
		/// <param name="meanQ">Incoming message from m='mean'.</param>
		/// <param name="totalCountQ">Incoming message from s='totalCount'.</param>
		/// <returns>Vector of E[ LogGamma(s*m_k)].</returns>
		/// <remarks><para>
		/// The quadrature over 'totalCount' (which is Gamma-distributed) is 
		/// peformed by a change of variable x=log(s) followed by Gauss-Hermite 
		/// quadrature. The quadrature over m is performed using Gauss-Legendre. 
		/// </para></remarks>
		public static Vector EvidenceMessageExpectations(
				Dirichlet meanQ,
				Gamma totalCountQ)
		{
			// Get shape and scale of the distribution
			double at, bt;
			totalCountQ.GetShapeAndScale(out at, out bt);
			bt = 1 / bt; // want rate not scale

			// Mean in the transformed domain
			double proposalMean = totalCountQ.GetMeanLog();
			// Laplace approximation of variance in transformed domain 
			double proposalVariance = 1 / at;

			// Quadrature coefficient
			int nt = 32;
			Vector nodes = Vector.Zero(nt);
			Vector weights = Vector.Zero(nt);
			Vector expx = Vector.Zero(nt);
			if (!totalCountQ.IsPointMass) {
				Quadrature.GaussianNodesAndWeights(proposalMean, proposalVariance, nodes, weights);
				// Precompute weights for each m slice
				for (int i = 0; i < nt; i++) {
					double x = nodes[i];
					expx[i] = Math.Exp(x);
					double p = at * x - bt * expx[i] - Gaussian.GetLogProb(x, proposalMean, proposalVariance);
					weights[i] *= Math.Exp(p);
				}
			}

			int nm = 20;
			Vector mnodes = Vector.Zero(nm);
			Vector mweight = Vector.Zero(nm);
			Quadrature.UniformNodesAndWeights(0, 1, mnodes, mweight);
			int K = meanQ.Dimension;
			Vector[] mweights = new Vector[K];
			Beta[] mkDist = new Beta[K];
			double[] EELogGamma = new double[K];
			for (int i = 0; i < K; i++) {
				mweights[i] = Vector.Copy(mweight);
				mkDist[i] = new Beta(meanQ.PseudoCount[i], meanQ.TotalCount - meanQ.PseudoCount[i]);
				EELogGamma[i] = 0;
			}

			for (int j = 0; j < nm; j++) {
				double m = mnodes[j];
				double ELogGamma = 0;
				if (totalCountQ.IsPointMass)
					ELogGamma = MMath.GammaLn(m * totalCountQ.Point);
				else {
					// Calculate expectations in x=log(s) space using Gauss-Hermite quadrature
					for (int i = 0; i < nt; i++) {
						double x = nodes[i];
						ELogGamma += weights[i] * (MMath.GammaLn(m * expx[i]) + x);
					}
					// Normalise and add removed components
					double normalisation = Math.Pow(bt, at) / MMath.Gamma(at);
					ELogGamma = normalisation * ELogGamma - proposalMean;
				}
				for (int i = 0; i < K; i++) {
					mweights[i][j] *= Math.Exp(mkDist[i].GetLogProb(m));
					EELogGamma[i] += mweights[i][j] * ELogGamma;
				}
			}
			return Vector.FromArray(EELogGamma);
		}
Beispiel #11
0
        /// <summary>
        /// Attachs the data to the workers labels with and sets the workers' confusion matrix priors.
        /// </summary>
        /// <param name="taskIndices">The matrix of the task indices (columns) of each worker (rows).</param>
        /// <param name="workerLabels">The matrix of the labels (columns) of each worker (rows).</param>
        /// <param name="confusionMatrixPrior">The workers' confusion matrix priors.</param>
        protected virtual void AttachData(int[][] taskIndices, int[][] workerLabels, Dirichlet[][] confusionMatrixPrior)
        {
            int numClasses = c.SizeAsInt;
            WorkerCount.ObservedValue = taskIndices.Length;
            WorkerTaskCount.ObservedValue = taskIndices.Select(tasks => tasks.Length).ToArray();
            WorkerTaskIndex.ObservedValue = taskIndices;
            // Prediction mode is indicated by none of the workers having a label.
            // We can just look at the first one
            if (workerLabels[0] != null)
            {
                WorkerLabel.ObservedValue = workerLabels;
            }
            else
            {
                WorkerLabel.ClearObservedValue();
            }

            if (confusionMatrixPrior != null)
            {
                ConfusionMatrixPrior.ObservedValue = Util.ArrayInit(confusionMatrixPrior.Length, worker => Util.ArrayInit(numClasses, lab => confusionMatrixPrior[worker][lab]));
            }
        }
Beispiel #12
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="SampleAverageConditional(Dirichlet, Discrete)"]/*'/>
 public static Discrete SampleAverageConditional([SkipIfUniform] Dirichlet probs, Discrete result)
 {
     result.SetProbs(probs.GetMean(result.GetWorkspace()));
     return(result);
 }
Beispiel #13
0
		/// <summary>
		/// Evidence message for VMP
		/// </summary>
		/// <param name="sample">Incoming message from 'sampleFromPseudoCounts'.</param>
		/// <param name="pseudoCounts">Constant value for 'pseudoCount'.</param>
		/// <param name="to_sample">Outgoing message to 'sample'.</param>
		/// <returns>Average of the factor's log-value across the given argument distributions</returns>
		/// <remarks><para>
		/// The formula for the result is <c>sum_(sampleFromPseudoCounts) p(sampleFromPseudoCounts) log(factor(sampleFromPseudoCounts,pseudoCount))</c>.
		/// Adding up these values across all factors and variables gives the log-evidence estimate for VMP.
		/// </para></remarks>
		public static double AverageLogFactor(Dirichlet sample, Vector pseudoCounts, [Fresh] Dirichlet to_sample)
		{
			return to_sample.GetAverageLog(sample);
		}
Beispiel #14
0
		public static Dirichlet ProbAverageConditional([SkipIfUniform] Gamma alpha, Dirichlet result)
		{
			throw new NotSupportedException(NotSupportedMessage);
		}
        public void DirichletOpQuadratureTest()
        {
            var matlabResults
                = new double[]
                    {
                        0.625872049875551,
                        0.866057568760984,
                        -0.266065360660541,
                        -1.227320719860393,
                        1.280900246404125
                    };
            var matlabResults2
                = new double[]
                    {
                        0.843302107208523,
                        0.610546297106219,
                        -2.182481855300747,
                        -0.254011377373013,
                        -0.217430057568389
                    };
            double am = 2;
            double bm = 1;
            double at = 3;
            double bt = 1;
            Dirichlet meanQ = new Dirichlet(new double[] {am, bm});
            Gamma totalCountQ = new Gamma(at, 1/bt);
            double[] EELogGamma;
            double[] EELogMLogGamma;
            double[] EELogOneMinusMLogGamma;
            double[] EELogSLogGamma;
            double[] EEMSDigamma;
            DirichletOp.MeanMessageExpectations(
                meanQ.PseudoCount,
                totalCountQ,
                out EELogGamma,
                out EELogMLogGamma,
                out EELogOneMinusMLogGamma);

            Console.WriteLine(System.Math.Abs(EELogGamma[0] - matlabResults[0]));
            Console.WriteLine(System.Math.Abs(EELogMLogGamma[0] - matlabResults[2]));
            Console.WriteLine(System.Math.Abs(EELogOneMinusMLogGamma[0] - matlabResults[3]));

            Console.WriteLine(System.Math.Abs(EELogGamma[1] - matlabResults2[0]));
            Console.WriteLine(System.Math.Abs(EELogMLogGamma[1] - matlabResults2[2]));
            Console.WriteLine(System.Math.Abs(EELogOneMinusMLogGamma[1] - matlabResults2[3]));

            DirichletOp.TotalCountMessageExpectations(
                meanQ.PseudoCount,
                totalCountQ,
                out EELogGamma,
                out EELogSLogGamma,
                out EEMSDigamma);

            Console.WriteLine(System.Math.Abs(EELogGamma[0] - matlabResults[0]));
            Console.WriteLine(System.Math.Abs(EELogSLogGamma[0] - matlabResults[1]));
            Console.WriteLine(System.Math.Abs(EEMSDigamma[0] - matlabResults[4]));

            Console.WriteLine(System.Math.Abs(EELogGamma[1] - matlabResults2[0]));
            Console.WriteLine(System.Math.Abs(EELogSLogGamma[1] - matlabResults2[1]));
            Console.WriteLine(System.Math.Abs(EEMSDigamma[1] - matlabResults2[4]));
        }
Beispiel #16
0
        /// <summary>
        /// Constructs an LDA model
        /// </summary>
        /// <param name="sizeVocab">Size of vocabulary</param>
        /// <param name="numTopics">Number of topics</param>
        public LDAShared(int numBatches, int sizeVocab, int numTopics)
        {
            SizeVocab         = sizeVocab;
            NumTopics         = numTopics;
            ThetaSparsity     = Sparsity.Dense;
            PhiSparsity       = Sparsity.ApproximateWithTolerance(0.00000000001); // Allow for round-off error
            NumDocuments      = Variable.New <int>().Named("NumDocuments");
            NumBatches        = numBatches;
            IterationsPerPass = new int[] { 1, 3, 5, 7, 9 };

            //---------------------------------------------
            // The model
            //---------------------------------------------
            Range D = new Range(NumDocuments).Named("D");
            Range W = new Range(SizeVocab).Named("W");
            Range T = new Range(NumTopics).Named("T");

            NumWordsInDoc = Variable.Array <int>(D).Named("NumWordsInDoc");
            Range WInD = new Range(NumWordsInDoc[D]).Named("WInD");

            Evidence = SharedVariable <bool> .Random(new Bernoulli(0.5)).Named("Evidence");

            Evidence.IsEvidenceVariable = true;

            Phi = SharedVariable <Vector> .Random(T, CreateUniformDirichletArray(numTopics, sizeVocab, PhiSparsity)).Named("Phi");

            // Phi definition sub-model - just one copy
            PhiDefModel = new Model(1).Named("PhiDefModel");

            IfBlock evidencePhiDefBlock = null;

            EvidencePhiDef      = Evidence.GetCopyFor(PhiDefModel).Named("EvidencePhiDef");
            evidencePhiDefBlock = Variable.If(EvidencePhiDef);
            PhiDef = Variable.Array <Vector>(T).Named("PhiDef");
            PhiDef.SetSparsity(PhiSparsity);
            PhiDef.SetValueRange(W);
            PhiPrior  = Variable.Array <Dirichlet>(T).Named("PhiPrior");
            PhiDef[T] = Variable <Vector> .Random(PhiPrior[T]);

            Phi.SetDefinitionTo(PhiDefModel, PhiDef);
            evidencePhiDefBlock.CloseBlock();

            // Document sub-model - many copies
            DocModel = new Model(numBatches).Named("DocModel");

            IfBlock evidenceDocBlock = null;

            EvidenceDoc      = Evidence.GetCopyFor(DocModel).Named("EvidenceDoc");
            evidenceDocBlock = Variable.If(EvidenceDoc);
            Theta            = Variable.Array <Vector>(D).Named("Theta");
            Theta.SetSparsity(ThetaSparsity);
            Theta.SetValueRange(T);
            ThetaPrior = Variable.Array <Dirichlet>(D).Named("ThetaPrior");
            Theta[D]   = Variable <Vector> .Random(ThetaPrior[D]);

            PhiDoc = Phi.GetCopyFor(DocModel);
            PhiDoc.AddAttribute(new MarginalPrototype(Dirichlet.Uniform(sizeVocab, PhiSparsity)));
            Words      = Variable.Array(Variable.Array <int>(WInD), D).Named("Words");
            WordCounts = Variable.Array(Variable.Array <double>(WInD), D).Named("WordCounts");
            using (Variable.ForEach(D))
            {
                using (Variable.ForEach(WInD))
                {
                    using (Variable.Repeat(WordCounts[D][WInD]))
                    {
                        Variable <int> topic = Variable.Discrete(Theta[D]).Named("topic");
                        using (Variable.Switch(topic))
                        {
                            Words[D][WInD] = Variable.Discrete(PhiDoc[topic]);
                        }
                    }
                }
            }

            evidenceDocBlock.CloseBlock();

            // Initialization to break symmetry
            ThetaInit = Variable.New <IDistribution <Vector[]> >().Named("ThetaInit");
            Theta.InitialiseTo(ThetaInit);
            EnginePhiDef = new InferenceEngine(new VariationalMessagePassing());
            EnginePhiDef.Compiler.ShowWarnings = false;
            EnginePhiDef.ModelName             = "LDASharedPhiDef";

            Engine = new InferenceEngine(new VariationalMessagePassing());
            Engine.OptimiseForVariables = new IVariable[] { Theta, PhiDoc, EvidenceDoc };

            Engine.Compiler.ShowWarnings = false;
            Engine.ModelName             = "LDAShared";
            Engine.Compiler.ReturnCopies = false;
            Engine.Compiler.FreeMemory   = true;
        }
Beispiel #17
0
 public static Discrete SampleAverageLogarithmInit([IgnoreDependency] Dirichlet probs)
 {
     return(Discrete.Uniform(probs.Dimension));
 }
Beispiel #18
0
        public void MixtureOfMultivariateGaussians()
        {
            // Define a range for the number of mixture components
            Range k = new Range(2).Named("k");

            // Mixture component means
            VariableArray <Vector> means = Variable.Array <Vector>(k).Named("means");

            means[k] = Variable.VectorGaussianFromMeanAndPrecision(Vector.Zero(2), PositiveDefiniteMatrix.IdentityScaledBy(2, 0.01)).ForEach(k);

            // Mixture component precisions
            VariableArray <PositiveDefiniteMatrix> precs = Variable.Array <PositiveDefiniteMatrix>(k).Named("precs");

            precs[k] = Variable.WishartFromShapeAndScale(100.0, PositiveDefiniteMatrix.IdentityScaledBy(2, 0.01)).ForEach(k);

            // Mixture weights
            Variable <Vector> weights = Variable.Dirichlet(k, new double[] { 1, 1 }).Named("weights");

            // Create a variable array which will hold the data
            Range n = new Range(300).Named("n");
            VariableArray <Vector> data = Variable.Array <Vector>(n).Named("x");
            // Create latent indicator variable for each data point
            VariableArray <int> z = Variable.Array <int>(n).Named("z");

            // The mixture of Gaussians model
            using (Variable.ForEach(n))
            {
                z[n] = Variable.Discrete(weights);
                using (Variable.Switch(z[n]))
                {
                    data[n] = Variable.VectorGaussianFromMeanAndPrecision(means[z[n]], precs[z[n]]);
                }
            }

            // Attach some generated data
            double truePi = 0.6;

            data.ObservedValue = GenerateData(n.SizeAsInt, truePi);

            // Initialise messages randomly to break symmetry
            VariableArray <Discrete> zInit = Variable.Array <Discrete>(n).Named("zInit");
            bool useObservedValue          = true;

            if (useObservedValue)
            {
                zInit.ObservedValue = Util.ArrayInit(n.SizeAsInt, i => Discrete.PointMass(Rand.Int(k.SizeAsInt), k.SizeAsInt));
            }
            else
            {
                // This approach doesn't work, because Infer.NET notices that Rand.Int is stochastic and thinks that it should perform message-passing here.
                using (Variable.ForEach(n))
                {
                    var randk = Variable <int> .Factor(new Func <int, int>(Rand.Int), (Variable <int>) k.Size);

                    randk.SetValueRange(k);
                    zInit[n] = Variable <Discrete> .Factor(Discrete.PointMass, randk, (Variable <int>) k.Size);
                }
            }
            z[n].InitialiseTo(zInit[n]);

            // The inference
            InferenceEngine ie = new InferenceEngine();

            ie.Algorithm = new VariationalMessagePassing();
            //ie.Compiler.GenerateInMemory = false;
            //ie.NumberOfIterations = 200;
            Dirichlet wDist    = (Dirichlet)ie.Infer(weights);
            Vector    wEstMean = wDist.GetMean();

            object meansActual = ie.Infer(means);

            Console.WriteLine("means = ");
            Console.WriteLine(meansActual);
            var precsActual = ie.Infer <IList <Wishart> >(precs);

            Console.WriteLine("precs = ");
            Console.WriteLine(precsActual);
            Console.WriteLine("w = {0} should be {1}", wEstMean, Vector.FromArray(truePi, 1 - truePi));
            //Console.WriteLine(StringUtil.JoinColumns("z = ", ie.Infer(z)));
            Assert.True(
                MMath.AbsDiff(wEstMean[0], truePi) < 0.05 ||
                MMath.AbsDiff(wEstMean[1], truePi) < 0.05);
        }
Beispiel #19
0
 public static double LogEvidenceRatio(Discrete sample, Dirichlet probs)
 {
     return(0.0);
 }
Beispiel #20
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="LogEvidenceRatio(int, Dirichlet)"]/*'/>
 public static double LogEvidenceRatio(int sample, Dirichlet probs)
 {
     return(LogAverageFactor(sample, probs));
 }
Beispiel #21
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="LogAverageFactor(int, Dirichlet)"]/*'/>
        public static double LogAverageFactor(int sample, Dirichlet probs)
        {
            Discrete to_sample = SampleAverageConditional(probs, Discrete.Uniform(probs.Dimension, probs.Sparsity));

            return(to_sample.GetLogProb(sample));
        }
Beispiel #22
0
		/// <summary>
		/// Buffer for E[log(prob)]
		/// </summary>
		/// <param name="prob">Incoming message from 'prob'</param>
		/// <param name="result">Will be the returned value. </param>
		/// <returns>E[log(prob)]</returns>
		public static Vector ProbMeanLog(Dirichlet prob, Vector result)
		{
            prob.GetMeanLog(result);
            return result; 
		}
Beispiel #23
0
        /// <summary>
        /// Runs inference on the LDA model.
        /// <para>
        /// Words in documents are observed, topic distributions per document (<see cref="Theta"/>)
        /// and word distributions per topic (<see cref="Phi"/>) are inferred.
        /// </para>
        /// </summary>
        /// <param name="wordsInDoc">For each document, the unique word counts in the document</param>
        /// <param name="alpha">Hyper-parameter for <see cref="Theta"/></param>
        /// <param name="beta">Hyper-parameter for <see cref="Phi"/></param>
        /// <param name="postTheta">Posterior marginals for <see cref="Theta"/></param>
        /// <param name="postPhi">Posterior marginals for <see cref="Phi"/></param>
        /// <returns>Log evidence - can be used for model selection.</returns>
        public virtual double Infer(Dictionary <int, int>[] wordsInDoc, double alpha, double beta, out Dirichlet[] postTheta, out Dirichlet[] postPhi)
        {
            int numDocs = wordsInDoc.Length;

            postTheta = new Dirichlet[numDocs];
            int  numIters     = Engine.NumberOfIterations;
            bool showProgress = Engine.ShowProgress;

            Engine.ShowProgress = false; // temporarily disable Infer.NET progress

            // Set up document index boundaries for each batch
            double numDocsPerBatch = ((double)numDocs) / NumBatches;

            if (numDocsPerBatch == 0)
            {
                numDocsPerBatch = 1;
            }

            int[] boundary = new int[NumBatches + 1];
            boundary[0] = 0;
            double currBoundary = 0.0;

            for (int batch = 1; batch <= NumBatches; batch++)
            {
                currBoundary += numDocsPerBatch;
                int bnd = (int)currBoundary;
                if (bnd > numDocs)
                {
                    bnd = numDocs;
                }

                boundary[batch] = bnd;
            }

            boundary[NumBatches] = numDocs;

            PhiPrior.ObservedValue = new Dirichlet[NumTopics];
            for (int i = 0; i < NumTopics; i++)
            {
                PhiPrior.ObservedValue[i] = Dirichlet.Symmetric(SizeVocab, beta);
            }

            NumDocuments.ObservedValue = -1;
            try
            {
                for (int pass = 0; pass < NumPasses; pass++)
                {
                    Engine.NumberOfIterations = IterationsPerPass[pass];
                    if (showProgress)
                    {
                        Console.Write(String.Format(
                                          "\nPass {0} ({1} iteration{2} per batch)",
                                          pass, IterationsPerPass[pass], IterationsPerPass[pass] == 1 ? "" : "s"));
                    }

                    PhiDefModel.InferShared(EnginePhiDef, 0);
                    for (int batch = 0; batch < NumBatches; batch++)
                    {
                        int startDoc = boundary[batch];
                        int endDoc   = boundary[batch + 1];
                        if (startDoc >= numDocs)
                        {
                            break;
                        }

                        int numDocsInThisBatch = endDoc - startDoc;
                        if (pass == 0)
                        {
                            ThetaInit.ObservedValue = LDAModel.GetInitialisation(numDocsInThisBatch, NumTopics, ThetaSparsity);
                        }
                        else
                        {
                            var thetaInit = new DirichletArray(numDocsInThisBatch);
                            for (int d = 0; d < numDocsInThisBatch; d++)
                            {
                                thetaInit[d] = new Dirichlet(postTheta[d + startDoc]);
                            }

                            ThetaInit.ObservedValue = thetaInit;
                        }

                        // Set up the observed values
                        if (NumDocuments.ObservedValue != numDocsInThisBatch)
                        {
                            NumDocuments.ObservedValue = numDocsInThisBatch;

                            ThetaPrior.ObservedValue = new Dirichlet[numDocsInThisBatch];
                            for (int i = 0; i < numDocsInThisBatch; i++)
                            {
                                ThetaPrior.ObservedValue[i] = Dirichlet.Symmetric(NumTopics, alpha);
                            }
                        }

                        int[]      numWordsInDocBatch   = new int[numDocsInThisBatch];
                        int[][]    wordsInDocBatch      = new int[numDocsInThisBatch][];
                        double[][] wordCountsInDocBatch = new double[numDocsInThisBatch][];
                        for (int i = 0, j = startDoc; j < endDoc; i++, j++)
                        {
                            numWordsInDocBatch[i] = wordsInDoc[j].Count;
                            wordsInDocBatch[i]    = wordsInDoc[j].Keys.ToArray();
                            ICollection <int> cnts = wordsInDoc[j].Values;
                            wordCountsInDocBatch[i] = new double[cnts.Count];
                            int k = 0;
                            foreach (int val in cnts)
                            {
                                wordCountsInDocBatch[i][k++] = (double)val;
                            }
                        }

                        NumWordsInDoc.ObservedValue = numWordsInDocBatch;
                        Words.ObservedValue         = wordsInDocBatch;
                        WordCounts.ObservedValue    = wordCountsInDocBatch;

                        DocModel.InferShared(Engine, batch);
                        var postThetaBatch = Engine.Infer <Dirichlet[]>(Theta);
                        for (int i = 0, j = startDoc; j < endDoc; i++, j++)
                        {
                            postTheta[j] = postThetaBatch[i];
                        }

                        postPhi = Distribution.ToArray <Dirichlet[]>(Phi.Marginal <IDistribution <Vector[]> >());

                        if (showProgress)
                        {
                            if ((batch % 80) == 0)
                            {
                                Console.WriteLine("");
                            }

                            Console.Write(".");
                        }
                    }
                }
            }
            finally
            {
                Engine.NumberOfIterations = numIters;
                Engine.ShowProgress       = showProgress;
            }

            if (showProgress)
            {
                Console.WriteLine();
            }

            postPhi = Distribution.ToArray <Dirichlet[]>(Phi.Marginal <IDistribution <Vector[]> >());

            return(Model.GetEvidenceForAll(PhiDefModel, DocModel));
        }
Beispiel #24
0
		public static Dirichlet ProbAverageLogarithm([SkipIfUniform] Gamma alpha, Dirichlet result)
		{
			result.PseudoCount.SetAllElementsTo(alpha.GetMean());
            result.TotalCount = result.PseudoCount.Sum(); 
			return result;
		}
 /// <inheritdoc />
 public override void SetDefaultPriors()
 {
     base.SetDefaultPriors();
     this.RandomGuessPrior.ObservedValue = Dirichlet.Uniform(this.Labels.SizeAsInt);
     this.AbilityPrior.ObservedValue     = Util.ArrayInit(this.WorkerCount, input => new Beta(2, 1));
 }
Beispiel #26
0
		public static double LogEvidenceRatio(Dirichlet prob, double alpha) { return 0.0; }
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="CharFromProbabilitiesOp"]/message_doc[@name="ProbabilitiesAverageConditional(DiscreteChar, Dirichlet, Dirichlet)"]/*'/>
 public static Dirichlet ProbabilitiesAverageConditional([SkipIfUniform] DiscreteChar character, Dirichlet probabilities, Dirichlet result)
 {
     return(DiscreteFromDirichletOp.ProbsAverageConditional(new Discrete(character.GetProbs()), probabilities, result));
 }
Beispiel #28
0
		/// <summary>
		/// VMP message to 'mean'
		/// </summary>
		/// <param name="mean">Incoming message from 'mean'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
		/// <param name="totalCount">Constant value for 'totalCount'.</param>
		/// <param name="prob">Incoming message from 'prob'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
		/// <param name="to_mean">Previous outgoing message to 'mean'.</param>
		/// <returns>The outgoing VMP message to the 'mean' argument</returns>
		/// <remarks><para>
		/// The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except 'mean'.
		/// The formula is <c>exp(sum_(prob) p(prob) log(factor(prob,mean,totalCount)))</c>.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="mean"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="prob"/> is not a proper distribution</exception>
		public static Dirichlet MeanAverageLogarithm([Proper] Dirichlet mean, double totalCount, [SkipIfUniform] Dirichlet prob, Dirichlet to_mean)
		{
			return MeanAverageLogarithm(mean, Gamma.PointMass(totalCount), prob, to_mean);
		}
 public static double LogEvidenceRatio(Dirichlet probabilities, DiscreteChar character)
 {
     return(0);
 }
Beispiel #30
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="AverageLogFactor(int, Dirichlet)"]/*'/>
 public static double AverageLogFactor(int sample, [Proper] Dirichlet probs)
 {
     return(probs.GetMeanLogAt(sample));
 }
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="CharFromProbabilitiesOp"]/message_doc[@name="LogEvidenceRatio(Dirichlet, Char)"]/*'/>
 public static double LogEvidenceRatio(Dirichlet probabilities, char character)
 {
     return(DiscreteFromDirichletOp.LogEvidenceRatio(character, probabilities));
 }
Beispiel #32
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="ProbsAverageLogarithm(int, Dirichlet)"]/*'/>
 public static Dirichlet ProbsAverageLogarithm(int sample, Dirichlet result)
 {
     return(ProbsConditional(sample, result));
 }
Beispiel #33
0
 public void InferPosteriors()
 {
     CPTTransPosterior      = Engine.Infer <Dirichlet[]>(CPTTrans);
     ProbInitPosterior      = Engine.Infer <Dirichlet>(ProbInit);
     ModelEvidencePosterior = Engine.Infer <Bernoulli>(ModelEvidence);
 }
 public void CanGetDimension()
 {
     var d = new Dirichlet(0.3, 10);
     Assert.AreEqual(10, d.Dimension);
 }
Beispiel #35
0
 public void SetUninformedPriors()
 {
     ProbInitPrior.ObservedValue = Dirichlet.Uniform(K.SizeAsInt);
     CPTTransPrior.ObservedValue = Util.ArrayInit(K.SizeAsInt, k => Dirichlet.Uniform(K.SizeAsInt)).ToArray();
 }
Beispiel #36
0
		/// <summary>
		/// Evidence message for EP
		/// </summary>
		/// <param name="prob">Constant value for 'prob'.</param>
		/// <param name="mean">Constant value for 'mean'.</param>
		/// <param name="totalCount">Constant value for 'totalCount'.</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(prob,mean,totalCount))</c>.
		/// </para></remarks>
		public static double LogAverageFactor(Vector prob, Vector mean, double totalCount)
		{
			var temp = mean.Clone();
			mean.SetToProduct(mean, totalCount);
			var d = new Dirichlet(temp);
			return d.GetLogProb(prob);
		}
Beispiel #37
0
 public void SetPriors(Dirichlet ProbInitPriorParamObs, Dirichlet[] CPTTransPriorObs)
 {
     ProbInitPrior.ObservedValue = ProbInitPriorParamObs;
     CPTTransPrior.ObservedValue = CPTTransPriorObs;
 }
Beispiel #38
0
		/// <summary>
		/// EP message to 'prob'
		/// </summary>
		/// <param name="prob">Incoming message from 'prob'.</param>
		/// <param name="mean">Constant value for 'mean'.</param>
		/// <param name="totalCount">Constant value for 'totalCount'.</param>
		/// <param name="result">Modified to contain the outgoing message</param>
		/// <returns><paramref name="result"/></returns>
		/// <remarks><para>
		/// The outgoing message is the factor viewed as a function of 'prob' conditioned on the given values.
		/// </para></remarks>
		public static Dirichlet ProbAverageConditional(Dirichlet prob, Vector mean, double totalCount, Dirichlet result)
		{
			result.PseudoCount.SetToProduct(mean, totalCount);
			return result;
		}
Beispiel #39
0
        public void MixtureOfMultivariateGaussians()
        {
            // Define a range for the number of mixture components
            Range k = new Range(2).Named("k");

            // Mixture component means
            VariableArray <Vector> means = Variable.Array <Vector>(k).Named("means");

            means[k] = Variable.VectorGaussianFromMeanAndPrecision(Vector.Zero(2), PositiveDefiniteMatrix.IdentityScaledBy(2, 0.01)).ForEach(k);

            // Mixture component precisions
            VariableArray <PositiveDefiniteMatrix> precs = Variable.Array <PositiveDefiniteMatrix>(k).Named("precs");

            precs[k] = Variable.WishartFromShapeAndScale(100.0, PositiveDefiniteMatrix.IdentityScaledBy(2, 0.01)).ForEach(k);

            // Mixture weights
            Variable <Vector> weights = Variable.Dirichlet(k, new double[] { 1, 1 }).Named("weights");

            // Create a variable array which will hold the data
            Range n = new Range(300).Named("n");
            VariableArray <Vector> data = Variable.Array <Vector>(n).Named("x");
            // Create latent indicator variable for each data point
            VariableArray <int> z = Variable.Array <int>(n).Named("z");

            // The mixture of Gaussians model
            using (Variable.ForEach(n))
            {
                z[n] = Variable.Discrete(weights);
                using (Variable.Switch(z[n]))
                {
                    data[n] = Variable.VectorGaussianFromMeanAndPrecision(means[z[n]], precs[z[n]]);
                }
            }

            // Attach some generated data
            double truePi = 0.6;

            data.ObservedValue = GenerateData(n.SizeAsInt, truePi);

            // Initialise messages randomly so as to break symmetry
            Discrete[] zinit = new Discrete[n.SizeAsInt];
            for (int i = 0; i < zinit.Length; i++)
            {
                zinit[i] = Discrete.PointMass(Rand.Int(k.SizeAsInt), k.SizeAsInt);
            }
            z.InitialiseTo(Distribution <int> .Array(zinit));

            // The inference
            InferenceEngine ie = new InferenceEngine();

            ie.Algorithm = new VariationalMessagePassing();
            //ie.Compiler.GenerateInMemory = false;
            //ie.NumberOfIterations = 200;
            Dirichlet wDist    = (Dirichlet)ie.Infer(weights);
            Vector    wEstMean = wDist.GetMean();

            object meansActual = ie.Infer(means);

            Console.WriteLine("means = ");
            Console.WriteLine(meansActual);
            var precsActual = ie.Infer <IList <Wishart> >(precs);

            Console.WriteLine("precs = ");
            Console.WriteLine(precsActual);
            Console.WriteLine("w = {0} should be {1}", wEstMean, Vector.FromArray(truePi, 1 - truePi));
            //Console.WriteLine(StringUtil.JoinColumns("z = ", ie.Infer(z)));
            Assert.True(
                MMath.AbsDiff(wEstMean[0], truePi) < 0.05 ||
                MMath.AbsDiff(wEstMean[1], truePi) < 0.05);
        }
Beispiel #40
0
		public static double LogEvidenceRatio(Dirichlet sample, Vector pseudoCounts) { return 0.0; }
Beispiel #41
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="ProbsAverageConditional(Discrete, Dirichlet, Dirichlet)"]/*'/>
        public static Dirichlet ProbsAverageConditional([SkipIfUniform] Discrete sample, [NoInit] Dirichlet probs, Dirichlet result)
        {
            if (probs.IsPointMass)
            {
                return(ProbsAverageConditional(sample, probs.Point, result));
            }
            if (sample.IsPointMass)
            {
                return(ProbsConditional(sample.Point, result));
            }
            // Z = sum_x q(x) int_p f(x,p)*q(p) = sum_x q(x) E[p[x]]
            Vector sampleProbs = sample.GetProbs();
            double Z           = sampleProbs.Inner(probs.PseudoCount);
            double invZ        = 1.0 / Z;
            // the posterior is a mixture of Dirichlets having the following form:
            // sum_x q(x) (alpha(x)/sum_i alpha(i)) Dirichlet(p; alpha(x)+1, alpha(not x)+0)
            // where the mixture weights are w(x) =propto q(x) alpha(x)
            //                               w[i] = sample[i]*probs.PseudoCount[i]/Z
            // The posterior mean of probs(x) = (w(x) + alpha(x))/(1 + sum_x alpha(x))
            double invTotalCountPlus1 = 1.0 / (probs.TotalCount + 1);
            Vector m = Vector.Zero(sample.Dimension, sample.Sparsity);

            m.SetToFunction(sampleProbs, probs.PseudoCount, (x, y) => (x * invZ + 1.0) * y * invTotalCountPlus1);
            if (!Dirichlet.AllowImproperSum)
            {
                // To get the correct mean, we need (probs.PseudoCount[i] + delta[i]) to be proportional to m[i].
                // If we set delta[argmin] = 0, then we just solve the equation
                //   (probs.PseudoCount[i] + delta[i])/probs.PseudoCount[argmin] = m[i]/m[argmin]
                // for delta[i].
                int argmin = sampleProbs.IndexOfMinimum();
                Debug.Assert(argmin != -1);
                double newTotalCount = probs.PseudoCount[argmin] / m[argmin];
                double argMinValue   = sampleProbs[argmin];
                result.PseudoCount.SetToFunction(m, probs.PseudoCount, (x, y) => 1.0 + (x * newTotalCount) - y);
                result.PseudoCount.SetToFunction(result.PseudoCount, sampleProbs, (x, y) => (y == argMinValue) ? 1.0 : x);
                result.TotalCount = result.PseudoCount.Sum(); // result.Dimension + newTotalCount - probs.TotalCount;
                return(result);
            }
            else
            {
                // The posterior meanSquare of probs(x) = (2 w(x) + alpha(x))/(2 + sum_x alpha(x)) * (1 + alpha(x))/(1 + sum_x alpha(x))
                double invTotalCountPlus2 = 1.0 / (2 + probs.TotalCount);
                Vector m2 = Vector.Zero(sample.Dimension, sample.Sparsity);
                m2.SetToFunction(sampleProbs, probs.PseudoCount, (x, y) => (2.0 * x * invZ + 1.0) * y * invTotalCountPlus2 * (1.0 + y) * invTotalCountPlus1);
                result.SetMeanAndMeanSquare(m, m2);
                result.SetToRatio(result, probs);
                return(result);
            }
        }
Beispiel #42
0
 public static Dirichlet ProbAverageLogarithm([SkipIfUniform] ConjugateDirichlet alpha, Dirichlet result)
 {
     if (!alpha.IsPointMass)
     {
         double mean, variance;
         alpha.SmartProposal(out mean, out variance);
         double alphaMode = Math.Exp(mean);
         if (double.IsNaN(alphaMode) || double.IsInfinity(alphaMode))
             throw new ApplicationException("Nan message in ProbAverageLogarithm");
         //result.PseudoCount.SetAllElementsTo(alphaMode);
         result.PseudoCount.SetAllElementsTo(alpha.GetMean());
     }
     else
         result.PseudoCount.SetAllElementsTo(alpha.Point); 
     result.TotalCount = result.PseudoCount.Sum(); 
     return result;
 }
Beispiel #43
0
		/// <summary>
		/// Run a single test for a single model
		/// </summary>
		/// <param name="sizeVocab">Size of the vocabulary</param>
		/// <param name="numTopics">Number of topics</param>
		/// <param name="trainWordsInTrainDoc">Lists of words in training documents used for training</param>
		/// <param name="testWordsInTrainDoc">Lists of words in training documents used for testing</param>
		/// <param name="alpha">Background pseudo-counts for distributions over topics</param>
		/// <param name="beta">Background pseudo-counts for distributions over words</param>
		/// <param name="shared">If true, uses shared variable version of the model</param>
		/// <param name="trueThetaTest">The true topic distributions for the documents in the test set</param>
		/// <param name="wordsInTestDoc">Lists of words in test documents</param>
		/// <param name="vocabulary">Vocabulary</param>
		static void RunTest(
			int sizeVocab, 
			int numTopics,
			Dictionary<int, int>[] trainWordsInTrainDoc, 
			Dictionary<int, int>[] testWordsInTrainDoc,
			double alpha, 
			double beta, 
			bool shared,
			Dirichlet[] trueThetaTest, 
			Dictionary<int, int>[] wordsInTestDoc,
			Dictionary<int, string> vocabulary = null
			)
		{
			Stopwatch stopWatch = new Stopwatch();
			// Square root of number of documents is the optimal for memory
			int batchCount = (int)Math.Sqrt((double)trainWordsInTrainDoc.Length);
			Rand.Restart(5);
			ILDA model;
			LDAPredictionModel predictionModel;
			LDATopicInferenceModel topicInfModel;
			if (shared)
			{
				model = new LDAShared(batchCount, sizeVocab, numTopics);
				((LDAShared)model).IterationsPerPass = Enumerable.Repeat(10, 5).ToArray();
			}
			else
			{
				model = new LDAModel(sizeVocab, numTopics);
				model.Engine.NumberOfIterations = 50;
			}

			Console.WriteLine("\n\n************************************");
			Console.WriteLine(
				String.Format("\nTraining {0}LDA model...\n",
				shared ? "batched " : "non-batched "));

			// Train the model - we will also get rough estimates of execution time and memory
			Dirichlet[] postTheta, postPhi;
			GC.Collect();
			PerformanceCounter memCounter = new PerformanceCounter("Memory", "Available MBytes");
			float preMem = memCounter.NextValue();
			stopWatch.Reset();
			stopWatch.Start();
			double logEvidence = model.Infer(trainWordsInTrainDoc, alpha, beta, out postTheta, out postPhi);
			stopWatch.Stop();
			float postMem = memCounter.NextValue();
			double approxMB = preMem - postMem;
			GC.KeepAlive(model); // Keep the model alive to this point (for the	memory counter)
			Console.WriteLine(String.Format("Approximate memory usage: {0:F2} MB", approxMB));
			Console.WriteLine(String.Format("Approximate execution time (including model compilation): {0} seconds", stopWatch.ElapsedMilliseconds/1000));

			// Calculate average log evidence over total training words
			int totalWords = trainWordsInTrainDoc.Sum(doc => doc.Sum(w => w.Value));
			Console.WriteLine("\nTotal number of training words = {0}", totalWords);
			Console.WriteLine(String.Format("Average log evidence of model: {0:F2}", logEvidence / (double)totalWords));

			if (vocabulary != null)
			{
				int numWordsToPrint = 20;
				// Print out the top n words for each topic
				for (int i = 0; i < postPhi.Length; i++)
				{
					double[] pc = postPhi[i].PseudoCount.ToArray();
					int[] wordIndices = new int[pc.Length];
					for (int j=0; j < wordIndices.Length; j++)
						wordIndices[j] = j;
					Array.Sort(pc, wordIndices);
					Console.WriteLine("Top {0} words in topic {1}:", numWordsToPrint, i);
					int idx = wordIndices.Length;
					for (int j = 0; j < numWordsToPrint; j++)
						Console.Write("\t{0}", vocabulary[wordIndices[--idx]]);
					Console.WriteLine();
				}
			}

			if (testWordsInTrainDoc != null)
			{
				// Test on unseen words in training documents
				Console.WriteLine("\n\nCalculating perplexity on test words in training documents...");
				predictionModel = new LDAPredictionModel(sizeVocab, numTopics);
				predictionModel.Engine.NumberOfIterations = 5;
				var predDist = predictionModel.Predict(postTheta, postPhi);
				var perplexity = Utilities.Perplexity(predDist, testWordsInTrainDoc);
				Console.WriteLine(String.Format("\nPerplexity = {0:F3}", perplexity));
			}

			if (wordsInTestDoc != null)
			{
				// Test on unseen documents. Note that topic ids for the trained model will be a random
				// permutation of the topic ids for the ground truth
				Console.WriteLine("\n\nInferring topics for test documents...");
				topicInfModel = new LDATopicInferenceModel(sizeVocab, numTopics);
				topicInfModel.Engine.NumberOfIterations = 10;
				var inferredTopicDists = topicInfModel.InferTopic(alpha, postPhi, wordsInTestDoc);
				Dictionary<TopicPair,int> topicPairCounts = new Dictionary<TopicPair, int>();
				for (int i = 0; i < inferredTopicDists.Length; i++)
				{
					int infTopic = inferredTopicDists[i].PseudoCount.IndexOfMaximum();
					int trueTopic = trueThetaTest[i].PseudoCount.IndexOfMaximum();
					TopicPair tp = new TopicPair() { InferredTopic = infTopic, TrueTopic = trueTopic };
					if (!topicPairCounts.ContainsKey(tp)) topicPairCounts.Add(tp, 1);
					else topicPairCounts[tp] = topicPairCounts[tp]+1;
				}
				var correctCount = CountCorrectTopicPredictions(topicPairCounts, numTopics);
				Console.WriteLine(String.Format("Maximum inferred topic matches maximum true topic {0} times out of {1}",
					correctCount, inferredTopicDists.Length));
				Console.WriteLine("\nThis uses a greedy algorithm to determine the mapping from inferred topic indices to true topic indices");
				Console.WriteLine("\n************************************");
			}
		}
Beispiel #44
0
		/// <summary>
		/// Evidence message for EP
		/// </summary>
		/// <param name="prob">Incoming message from 'prob'.</param>
		/// <param name="alpha">Constant value for 'alpha'.</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 int_prob p(prob) factor(prob,alpha,K))</c>.
		/// </para></remarks>
		public static double LogAverageFactor(Dirichlet prob, double alpha)
		{
			int dim = prob.Dimension;
			double sum = MMath.GammaLn(dim*alpha) - dim*MMath.GammaLn(alpha) - prob.GetLogNormalizer() - MMath.GammaLn(prob.TotalCount+dim*alpha);
			for (int i = 0; i < dim; i++) {
				sum += MMath.GammaLn(prob.PseudoCount[i]+alpha);
			}
			return sum;
		}
 public void DiscreteFromDirichletOpMomentMatchTest()
 {
     using (TestUtils.TemporarilyAllowDirichletImproperSums)
     {
         Dirichlet probsDist  = new Dirichlet(1, 2, 3, 4);
         Discrete  sampleDist = Discrete.Uniform(4);
         Assert.True(Dirichlet.Uniform(4).MaxDiff(DiscreteFromDirichletOp.ProbsAverageConditional(sampleDist, probsDist, Dirichlet.Uniform(4))) < 1e-4);
         sampleDist = Discrete.PointMass(1, 4);
         Assert.True(new Dirichlet(1, 2, 1, 1).MaxDiff(DiscreteFromDirichletOp.ProbsAverageConditional(sampleDist, probsDist, Dirichlet.Uniform(4))) < 1e-4);
         sampleDist = new Discrete(0, 1, 1, 0);
         Assert.True(new Dirichlet(0.9364, 1.247, 1.371, 0.7456).MaxDiff(DiscreteFromDirichletOp.ProbsAverageConditional(sampleDist, probsDist, Dirichlet.Uniform(4))) <
                     1e-3);
     }
 }
Beispiel #46
0
		/// <summary>
		/// EP message to 'prob'
		/// </summary>
		/// <param name="alpha">Constant value for 'alpha'.</param>
		/// <param name="result">Modified to contain the outgoing message</param>
		/// <returns><paramref name="result"/></returns>
		/// <remarks><para>
		/// The outgoing message is the factor viewed as a function of 'prob' conditioned on the given values.
		/// </para></remarks>
		public static Dirichlet ProbAverageConditional([SkipIfUniform] double alpha, Dirichlet result)
		{
			result.PseudoCount.SetAllElementsTo(alpha);
            result.TotalCount = result.PseudoCount.Sum(); 
			return result;
		}
Beispiel #47
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="ProbsAverageConditional(Discrete, Vector, Dirichlet)"]/*'/>
        public static Dirichlet ProbsAverageConditional([SkipIfUniform] Discrete sample, Vector probs, Dirichlet result)
        {
            Vector sampleProbs = sample.GetProbs();
            double Z           = sampleProbs.Inner(probs);
            Vector dLogP       = Vector.Zero(probs.Count);
            Vector ddLogP      = Vector.Zero(probs.Count);
            double sampleN     = sampleProbs[probs.Count - 1];
            double probN       = probs[probs.Count - 1];

            dLogP.SetToFunction(sampleProbs, sampleProb => (sampleProb - sampleN) / Z);
            ddLogP.SetToFunction(dLogP, x => - x * x);
            result.SetDerivatives(probs, dLogP, ddLogP, !Dirichlet.AllowImproperSum);
            return(result);
        }
Beispiel #48
0
		/// <summary>
		/// VMP message to 'mean'
		/// </summary>
		/// <param name="mean">Incoming message from 'mean'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
		/// <param name="totalCount">Constant value for 'totalCount'.</param>
		/// <param name="prob">Constant value for 'prob'.</param>
		/// <param name="to_mean">Previous outgoing message to 'mean'.</param>
		/// <returns>The outgoing VMP message to the 'mean' argument</returns>
		/// <remarks><para>
		/// The outgoing message is the factor viewed as a function of 'mean' conditioned on the given values.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="mean"/> is not a proper distribution</exception>
		public static Dirichlet MeanAverageLogarithm([Proper] Dirichlet mean, double totalCount, Vector prob, Dirichlet to_mean)
		{
			return MeanAverageLogarithm(mean, Gamma.PointMass(totalCount), Dirichlet.PointMass(prob), to_mean);
		}
        public void ValidateMean()
        {
            var d = new Dirichlet(0.3, 5);

            for (var i = 0; i < 5; i++)
            {
                AssertHelpers.AlmostEqual(0.3 / 1.5, d.Mean[i], 15);
            }
        }
Beispiel #50
0
		/// <summary>
		/// VMP message to 'mean'
		/// </summary>
		/// <param name="mean">Incoming message from 'mean'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
		/// <param name="totalCount">Incoming message from 'totalCount'. Must be a proper distribution.  If uniform, the result will be uniform.</param>
		/// <param name="prob">Incoming message from 'prob'. Must be a proper distribution.  If any element is uniform, the result will be uniform.</param>
		/// <param name="to_mean">Previous outgoing message to 'mean'.</param>
		/// <returns>The outgoing VMP message to the 'mean' argument</returns>
		/// <remarks><para>
		/// The outgoing message is the exponential of the average log-factor value, where the average is over all arguments except 'mean'.
		/// The formula is <c>exp(sum_(totalCount,prob) p(totalCount,prob) log(factor(prob,mean,totalCount)))</c>.
		/// </para></remarks>
		/// <exception cref="ImproperMessageException"><paramref name="mean"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="totalCount"/> is not a proper distribution</exception>
		/// <exception cref="ImproperMessageException"><paramref name="prob"/> is not a proper distribution</exception>
		public static Dirichlet MeanAverageLogarithm([Proper] Dirichlet mean, [Proper] Gamma totalCount, [SkipIfUniform] Dirichlet prob, Dirichlet to_mean)
		{
			Vector gradS = CalculateGradientForMean(mean.PseudoCount, totalCount, prob.GetMeanLog());
			// Project onto Dirichlet, efficient matrix inversion (see TM's Dirichlet fitting paper)
			int K = mean.Dimension;
			Vector q = Vector.Zero(K);
			double gOverQ = 0, OneOverQ = 0;
			for (int k = 0; k < K; k++) {
				q[k] = MMath.Trigamma(mean.PseudoCount[k]);
				gOverQ += gradS[k] / q[k];
				OneOverQ += 1 / q[k];
			}
			double z = -MMath.Trigamma(mean.TotalCount);
			double b = gOverQ / (1 / z + OneOverQ);
			// Create new approximation and damp

			if (damping == 0.0) {
				to_mean.PseudoCount.SetToFunction(gradS, q, (x, y) => ((x - b) / y) + 1.0);
				return to_mean;
			} else {
				var old_msg = (Dirichlet)to_mean.Clone();
				to_mean.PseudoCount.SetToFunction(gradS, q, (x, y) => ((x - b) / y) + 1.0);
				return (to_mean ^ (1 - damping)) * (old_msg ^ damping);
			}
		}
        public void ValidateVariance()
        {
            var alpha = new double[10];
            var sum = 0.0;
            for (var i = 0; i < 10; i++)
            {
                alpha[i] = i;
                sum += i;
            }

            var d = new Dirichlet(alpha);
            for (var i = 0; i < 10; i++)
            {
                AssertHelpers.AlmostEqual(i * (sum - i) / (sum * sum * (sum + 1.0)), d.Variance[i], 15);
            }
        }
Beispiel #52
0
        /// <summary>
        /// Returns the confusion matrix prior of each worker.
        /// </summary>
        /// <returns>The confusion matrix prior of each worker.</returns>
        public Dirichlet[] GetConfusionMatrixPrior()
        {
            var confusionMatrixPrior = new Dirichlet[LabelCount];
            for (int d = 0; d < LabelCount; d++)
            {
                //confusionMatrixPrior[d] = new Dirichlet(Util.ArrayInit(LabelCount, i => i == d ? (InitialWorkerBelief / (1 - InitialWorkerBelief)) * (LabelCount - 1) : 1.0));
                confusionMatrixPrior[d] = new Dirichlet(Util.ArrayInit(LabelCount, i => i == d ? 0.8 : 0.2));
            }

            return confusionMatrixPrior;
        }
Beispiel #53
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DiscreteFromDirichletOp"]/message_doc[@name="AverageLogFactor(Discrete, Vector)"]/*'/>
 public static double AverageLogFactor(Discrete sample, Vector probs)
 {
     return(AverageLogFactor(sample, Dirichlet.PointMass(probs)));
 }
Beispiel #54
0
		/// <summary>
		/// Main test program for Infer.NET LDA models
		/// </summary>
		/// <param name="args"></param>
		static void Main(string[] args)
		{
			Rand.Restart(5);
			Dictionary<int, string> vocabulary = null;
#if blei_corpus
			Dictionary<int, int>[] trainWordsInTrainDoc = Utilities.LoadWordCounts("C:\\Users\\PrairieRose\\Documents\\GitHub\\HabilisX\\Infer.NET 2.5\\Samples\\C#\\LDA\\TestLDA\\890Histobram.txt");
			vocabulary = Utilities.LoadVocabulary(@"C:\\Users\\PrairieRose\\Documents\\GitHub\\HabilisX\\Infer.NET 2.5\\Samples\\C#\\LDA\\TestLDA\\890Vocab.txt");
			Dictionary<int, int>[] testWordsInTrainDoc = trainWordsInTrainDoc;
			Dictionary<int, int>[] wordsInTestDoc = null;
			int sizeVocab = Utilities.GetVocabularySize(trainWordsInTrainDoc);
			int numTopics = 4;
			int numTrainDocs = trainWordsInTrainDoc.Length;
			Dirichlet[] trueThetaTest = null;
			Console.WriteLine("************************************");
			Console.WriteLine("Vocabulary size = " + sizeVocab);
			Console.WriteLine("Number of documents = " + numTrainDocs);
			Console.WriteLine("Number of topics = " + numTopics);
			Console.WriteLine("************************************");
			double alpha = 150 / numTopics;
			double beta = 0.1;
#else
			int numTopics = 4;
			int sizeVocab = 1000;
			int numTrainDocs = 500;
			int averageDocumentLength = 100;
			int averageWordsPerTopic = 10;
			int numTestDocs = numTopics * 5;
			int numDocs = numTrainDocs + numTestDocs;

			// Create the true model
			Dirichlet[] trueTheta, truePhi;
			Utilities.CreateTrueThetaAndPhi(
				sizeVocab, numTopics, numDocs, averageDocumentLength, averageWordsPerTopic,
				out trueTheta, out truePhi);

			// Split the documents between a train and test set
			Dirichlet[] trueThetaTrain = new Dirichlet[numTrainDocs];
			Dirichlet[] trueThetaTest = new Dirichlet[numTestDocs];
			int docx = 0;
			for (int i = 0; i < numTrainDocs; i++) trueThetaTrain[i] = trueTheta[docx++];
			for (int i = 0; i < numTestDocs; i++) trueThetaTest[i] = trueTheta[docx++];

			// Generate training and test data for the training documents
			Dictionary<int, int>[]  trainWordsInTrainDoc = Utilities.GenerateLDAData(trueThetaTrain, truePhi, (int)(0.9 * averageDocumentLength));
			Dictionary<int, int>[]  testWordsInTrainDoc = Utilities.GenerateLDAData(trueThetaTrain, truePhi, (int)(0.1 * averageDocumentLength));
			Dictionary<int, int>[]  wordsInTestDoc = Utilities.GenerateLDAData(trueThetaTest, truePhi, averageDocumentLength);
			Console.WriteLine("************************************");
			Console.WriteLine("Vocabulary size = " + sizeVocab);
			Console.WriteLine("Number of topics = " + numTopics);
			Console.WriteLine("True average words per topic = " + averageWordsPerTopic);
			Console.WriteLine("Number of training documents = " + numTrainDocs);
			Console.WriteLine("Number of test documents = " + numTestDocs);
			Console.WriteLine("************************************");
			double alpha = 1.0;
			double beta = 0.1;
#endif

			for (int i = 0; i < 2; i++)
			{
				bool shared = i == 0;
				// if (!shared) continue; // Comment out this line to see full LDA models
				RunTest(
					sizeVocab, 
					numTopics, 
					trainWordsInTrainDoc, 
					testWordsInTrainDoc,
					alpha,
					beta, 
					shared,
					trueThetaTest,
					wordsInTestDoc,
					vocabulary);
			}
			Console.ReadLine();
		}
Beispiel #55
0
        // Generate toy data - returns indices into vocab for each doc
        private int[][] GenerateToyLDAData(
            int numTopics, int numVocab, int numDocs, int expectedDocLength,
            out Dirichlet[] trueTheta, out Dirichlet[] truePhi)
        {
            truePhi = new Dirichlet[numTopics];
            for (int i = 0; i < numTopics; i++)
            {
                truePhi[i] = Dirichlet.Uniform(numVocab);
                truePhi[i].PseudoCount.SetAllElementsTo(0.0);
                // Draw the number of unique words in the topic
                int numUniqueWordsPerTopic = Poisson.Sample((double)numVocab / numTopics);
                if (numUniqueWordsPerTopic >= numVocab)
                {
                    numUniqueWordsPerTopic = numVocab;
                }
                double expectedRepeatOfWordInTopic =
                    ((double)numDocs) * expectedDocLength / numUniqueWordsPerTopic;
                int[] shuffledWordIndices = Rand.Perm(numVocab);
                for (int j = 0; j < numUniqueWordsPerTopic; j++)
                {
                    int wordIndex = shuffledWordIndices[j];
                    // Draw the count for that word
                    int cnt = Poisson.Sample(expectedRepeatOfWordInTopic);
                    truePhi[i].PseudoCount[wordIndex] = cnt + 1.0;
                }
            }

            trueTheta = new Dirichlet[numDocs];
            for (int i = 0; i < numDocs; i++)
            {
                trueTheta[i] = Dirichlet.Uniform(numTopics);
                trueTheta[i].PseudoCount.SetAllElementsTo(0.0);
                // Draw the number of unique topics in the doc. We expect this to be
                // very sparse
                int    numUniqueTopicsPerDoc      = System.Math.Min(1 + Poisson.Sample(1.0), numTopics);
                double expectedRepeatOfTopicInDoc =
                    expectedDocLength / numUniqueTopicsPerDoc;
                int[] shuffledTopicIndices = Rand.Perm(numTopics);
                for (int j = 0; j < numUniqueTopicsPerDoc; j++)
                {
                    int topicIndex = shuffledTopicIndices[j];
                    // Draw the count for that topic
                    int cnt = Poisson.Sample(expectedRepeatOfTopicInDoc);
                    trueTheta[i].PseudoCount[topicIndex] = cnt + 1.0;
                }
            }

            // Sample from the model
            Vector[] topicDist = new Vector[numDocs];
            Vector[] wordDist  = new Vector[numTopics];
            for (int i = 0; i < numDocs; i++)
            {
                topicDist[i] = trueTheta[i].Sample();
            }
            for (int i = 0; i < numTopics; i++)
            {
                wordDist[i] = truePhi[i].Sample();
            }


            int[][] wordsInDoc = new int[numDocs][];
            for (int i = 0; i < numDocs; i++)
            {
                int LengthOfDoc = Poisson.Sample((double)expectedDocLength);
                wordsInDoc[i] = new int[LengthOfDoc];
                for (int j = 0; j < LengthOfDoc; j++)
                {
                    int topic = Discrete.Sample(topicDist[i]);
                    wordsInDoc[i][j] = Discrete.Sample(wordDist[topic]);
                }
            }
            return(wordsInDoc);
        }