public static void NoiseTest(double noiseVariance) { int d = 2; int n = 1000; // generate data var N0I = new VectorGaussian(Vector.Zero(d), PositiveDefiniteMatrix.Identity(d)); var wTrue = N0I.Sample(); Normalize(wTrue); Vector[] x = new Vector[n]; bool[] y = new bool[n]; for (int i = 0; i < n; i++) { x[i] = N0I.Sample(); y[i] = (x[i].Inner(wTrue) + Gaussian.Sample(0, 1.0 / noiseVariance)) > 0.0; } // evaluate models var fixedNoise = new BPM_FixedNoise(d, n); var noiseRange = new double[] { 1, 2, 10, 20, 30, 100, 1000, 1e4 }; foreach (double noiseTrain in noiseRange) { Vector wTrain = fixedNoise.Train(x, y, noiseTrain); Normalize(wTrain); double err = System.Math.Acos(wTrain.Inner(wTrue)) / System.Math.PI; //double err = Math.Sqrt(wTrue.Inner(wTrue) -2*wTrue.Inner(wTrain) + wTrain.Inner(wTrain)); Console.WriteLine("noiseTrain = {0}, error = {1}", noiseTrain, err); } }
/// <summary> /// Generates a data set from a particular true model. /// </summary> public Vector[] GenerateData(int nData) { Vector trueM1 = Vector.FromArray(2.0, 3.0); Vector trueM2 = Vector.FromArray(7.0, 5.0); PositiveDefiniteMatrix trueP1 = new PositiveDefiniteMatrix( new double[, ] { { 3.0, 0.2 }, { 0.2, 2.0 } }); PositiveDefiniteMatrix trueP2 = new PositiveDefiniteMatrix( new double[, ] { { 2.0, 0.4 }, { 0.4, 4.0 } }); VectorGaussian trueVG1 = VectorGaussian.FromMeanAndPrecision(trueM1, trueP1); VectorGaussian trueVG2 = VectorGaussian.FromMeanAndPrecision(trueM2, trueP2); double truePi = 0.6; Bernoulli trueB = new Bernoulli(truePi); // Restart the infer.NET random number generator Rand.Restart(12347); Vector[] data = new Vector[nData]; for (int j = 0; j < nData; j++) { bool bSamp = trueB.Sample(); data[j] = bSamp ? trueVG1.Sample() : trueVG2.Sample(); } return(data); }
/// <summary> /// For the multinomial regression model: generate synthetic data, /// infer the model parameters and calculate the RMSE between the true /// and mean inferred coefficients. /// </summary> /// <param name="numSamples">Number of samples</param> /// <param name="numFeatures">Number of input features</param> /// <param name="numClasses">Number of classes</param> /// <param name="countPerSample">Total count per sample</param> /// <returns>RMSE between the true and mean inferred coefficients</returns> public double MultinomialRegressionSynthetic( int numSamples, int numFeatures, int numClasses, int countPerSample, double noiseVar = 0.0) { var features = new Vector[numSamples]; var counts = new int[numSamples][]; var coefficients = new Vector[numClasses]; var bias = Vector.Zero(numClasses); Rand.Restart(1); for (int i = 0; i < numClasses - 1; i++) { bias[i] = Rand.Normal(); coefficients[i] = Vector.Zero(numFeatures); Rand.Normal(Vector.Zero(numFeatures), PositiveDefiniteMatrix.Identity(numFeatures), coefficients[i]); } bias[numClasses - 1] = 0; coefficients[numClasses - 1] = Vector.Zero(numFeatures); var noiseDistribution = new VectorGaussian(Vector.Zero(numClasses), PositiveDefiniteMatrix.IdentityScaledBy(numClasses, noiseVar)); for (int i = 0; i < numSamples; i++) { features[i] = Vector.Zero(numFeatures); Rand.Normal(Vector.Zero(numFeatures), PositiveDefiniteMatrix.Identity(numFeatures), features[i]); var temp = Vector.FromArray(coefficients.Select(o => o.Inner(features[i])).ToArray()); if (noiseVar != 0.0) { temp += noiseDistribution.Sample(); } var p = MMath.Softmax(temp + bias); counts[i] = Rand.Multinomial(countPerSample, p); } IList <VectorGaussian> weightsPost; IList <Gaussian> biasPost; bool trackLowerBound = true; double ev = MultinomialRegression(features, counts, out weightsPost, out biasPost, trackLowerBound); if (trackLowerBound) { Console.WriteLine("Log lower bound= " + ev); } double error = 0; Console.WriteLine("Weights -------------- "); for (int i = 0; i < numClasses; i++) { var bMean = weightsPost[i].GetMean(); error += (bMean - coefficients[i]).Sum(o => o * o); Console.WriteLine("Class " + i + " True " + coefficients[i]); Console.WriteLine("Class " + i + " Inferred " + bMean); } error = System.Math.Sqrt(error / (numClasses * numFeatures)); Console.WriteLine("RMSE " + error); Console.WriteLine("Bias -------------- "); Console.WriteLine("True " + bias); Console.WriteLine("Inferred " + Vector.FromArray(biasPost.Select(o => o.GetMean()).ToArray())); return(error); }
public double MulticlassRegressionSynthetic(int numSamples, object softmaxOperator, out int iterations, out double lowerBound, double noiseVar = 0.0) { int numFeatures = 6; int numClasses = 4; var features = new Vector[numSamples]; var counts = new int[numSamples]; var coefficients = new Vector[numClasses]; var mean = Vector.Zero(numClasses); for (int i = 0; i < numClasses - 1; i++) { mean[i] = Rand.Normal(); coefficients[i] = Vector.Zero(numFeatures); Rand.Normal(Vector.Zero(numFeatures), PositiveDefiniteMatrix.Identity(numFeatures), coefficients[i]); } mean[numClasses - 1] = 0; coefficients[numClasses - 1] = Vector.Zero(numFeatures); var noiseDistribution = new VectorGaussian(Vector.Zero(numClasses), PositiveDefiniteMatrix.IdentityScaledBy(numClasses, noiseVar)); for (int i = 0; i < numSamples; i++) { features[i] = Vector.Zero(numFeatures); Rand.Normal(Vector.Zero(numFeatures), PositiveDefiniteMatrix.Identity(numFeatures), features[i]); var temp = Vector.FromArray(coefficients.Select(o => o.Inner(features[i])).ToArray()); if (noiseVar != 0.0) { temp += noiseDistribution.Sample(); } var p = MMath.Softmax(temp + mean); counts[i] = Rand.Sample(p); } Rand.Restart(DateTime.Now.Millisecond); VectorGaussian[] bPost; Gaussian[] meanPost; iterations = MulticlassRegression(features, counts, numClasses, out bPost, out meanPost, out lowerBound, softmaxOperator, true); var bMeans = bPost.Select(o => o.GetMean()).ToArray(); var bVars = bPost.Select(o => o.GetVariance()).ToArray(); double error = 0; Console.WriteLine("Coefficients -------------- "); for (int i = 0; i < numClasses; i++) { error += (bMeans[i] - coefficients[i]).Sum(o => o * o); Console.WriteLine("True " + coefficients[i]); Console.WriteLine("Inferred " + bMeans[i]); } Console.WriteLine("Mean -------------- "); Console.WriteLine("True " + mean); Console.WriteLine("Inferred " + Vector.FromArray(meanPost.Select(o => o.GetMean()).ToArray())); error = System.Math.Sqrt(error / (numClasses * numFeatures)); Console.WriteLine(numSamples + " " + error); return(error); }
public IFunction Sample() { if (this.FixedParameters.NumberFeatures > 1) { throw new Exception("Sampling of a Sparse Gaussian Process is not supported for input spaces of dimension > 1."); } if (this.FixedParameters.NumberBasisPoints <= 0) { return(((Sampleable <IFunction>) this.FixedParameters.Prior).Sample()); } // Try to find a reasonable range to sample from int numSamplePoints = 51; double maxabs = 1.0; for (int i = 0; i < this.FixedParameters.NumberBasisPoints; i++) { double absb = Math.Abs(this.FixedParameters.Basis[i][0]); if (maxabs < absb) { maxabs = absb; } } maxabs *= 1.5; // Go beyond the basis points List <Vector> x = new List <Vector>(numSamplePoints); double increm = (2.0 * maxabs) / ((double)(numSamplePoints - 1)); double start = -maxabs; double currx = start; for (int i = 0; i < numSamplePoints; i++) { Vector xv = Vector.Zero(1); xv[0] = currx; x.Add(xv); currx += increm; } // x now contains the set of input points at which we'll sample the // posterior function distribution VectorGaussian vg = VectorGaussian.FromMeanAndVariance(Mean(x), Covariance(x)); // Sample to get the outputs Vector y = vg.Sample(); // Build the spline LinearSpline ls = new LinearSpline(); ls.KnotStart = start; ls.KnotIncrem = increm; ls.YPoints = y; return(ls as IFunction); }
public int SyntheticData(int D, int N, int Ntest, double noiseVariance) { xtrain = new Vector[N]; xtest = new Vector[Ntest]; ytrain = new bool[N]; ytest = new bool[Ntest]; var N0I = new VectorGaussian(Vector.Zero(D), PositiveDefiniteMatrix.Identity(D)); var trueW = N0I.Sample(); for (int i = 0; i < N; i++) { xtrain[i] = N0I.Sample(); ytrain[i] = (xtrain[i].Inner(trueW) + Gaussian.Sample(0, 1.0 / noiseVariance)) > 0.0; } for (int i = 0; i < Ntest; i++) { xtest[i] = N0I.Sample(); ytest[i] = (xtest[i].Inner(trueW) + Gaussian.Sample(0, 1.0 / noiseVariance)) > 0.0; } return(0); }
/// <summary> /// Run our VB implementation of the Semi Parametric Latent Factor Model of /// Teh, Y., Seeger, M., and Jordan, M. (AISTATS 2005). /// </summary> public SPLFM_VMP RunSPLFM_VMP(Vector[] inputs, double[,] data, bool[,] isMissing, Settings settings, string[] errorMeasureNames = null, Converter <IPredictionSPLFMModel, double[]> modelAssessor = null, string swfn = null) { var model = new SPLFM_VMP(); var nodeOptimiser = new KernelOptimiser(settings); nodeOptimiser.xData = inputs; nodeOptimiser.kernel = ObjectCloner.Clone(settings.node_kernel); nodeOptimiser.hypersToOptimise = settings.nodeHypersToOptimise; var nodeFunctionsInit = Enumerable.Range(0, settings.Q).Select(i => VectorGaussian.FromMeanAndVariance( VectorGaussian.Sample(Vector.Zero(data.GetLength(1)), PositiveDefiniteMatrix.IdentityScaledBy(data.GetLength(1), 100)), PositiveDefiniteMatrix.IdentityScaledBy(data.GetLength(1), settings.init_precision))).ToArray(); // should put this manually in generated code var distArray = Distribution <Vector> .Array(nodeFunctionsInit); double inputsRange = inputs.Select(i => i[0]).Max() - inputs.Select(i => i[0]).Min(); Console.WriteLine("Init node kernel {0}", settings.node_kernel); model.SetObservedValue("D", data.GetLength(0)); model.SetObservedValue("Q", settings.Q); model.SetObservedValue("N", data.GetLength(1)); model.SetObservedValue("observedData", data); model.SetObservedValue("nodeFunctionsInitVar", distArray); model.SetObservedValue("K_node_inverse", Utils.GramMatrix(nodeOptimiser.kernel, inputs).Inverse()); model.SetObservedValue("noisePrecisionPrior", settings.noisePrecisionPrior); //model.SetObservedValue("nodeNoisePrecisionPrior", settings.nodeNoisePrecisionPrior); model.SetObservedValue("nodeSignalPrecisionsPrior", Enumerable.Range(0, settings.Q).Select(o => settings.nodeSignalPrecisionsPrior).ToArray()); model.SetObservedValue("isMissing", isMissing); model.nodeKernelOptimiser = nodeOptimiser; model.Reset(); var start = DateTime.Now; if (swfn != null) { using (var sw = new StreamWriter(swfn, true)) { sw.Write("{0} {1} {2}", "it", "time", "ml"); if (errorMeasureNames != null) { sw.Write(" " + errorMeasureNames.Aggregate((p, q) => p + " " + q)); } sw.Write(" " + Utils.KernelHyperNames(nodeOptimiser.kernel).Select(o => "node_" + o).Aggregate((p, q) => p + " " + q)); sw.Write(" noise"); for (int i = 0; i < settings.Q; i++) { sw.Write(" signal" + i); } sw.WriteLine(); } } double oldML = double.NegativeInfinity; double ml = 0; int it = 0; for (; it < settings.max_iterations; it++) { model.Update(1); ml = model.Marginal <Bernoulli>("ev").LogOdds; var noisePrecisionPost = model.Marginal <Gamma>("noisePrecision"); var assessment = (modelAssessor != null) ? modelAssessor(model).Select(o => o.ToString()).Aggregate((p, q) => p + " " + q) : ""; Console.WriteLine("It " + it + " node " + nodeOptimiser.kernel + " ml " + ml + " err " + assessment); if (Math.Abs(oldML - ml) < settings.ml_tolerance) { break; } oldML = ml; if (swfn != null) { using (var sw = new StreamWriter(swfn, true)) { var nodeSignalPrecisionsPost = model.Marginal <Gamma[]>("nodeSignalPrecisions"); sw.Write("{0} {1} {2}", it, (DateTime.Now - start).TotalMilliseconds, ml); if (modelAssessor != null) { sw.Write(" " + assessment); } sw.Write(" " + Utils.KernelToArray(nodeOptimiser.kernel).Select(o => o.ToString()).Aggregate((p, q) => p + " " + q)); sw.Write(" " + noisePrecisionPost.GetMeanInverse()); for (int i = 0; i < settings.Q; i++) { sw.Write(" " + nodeSignalPrecisionsPost[i].GetMeanInverse()); } sw.WriteLine(); } } } Console.WriteLine("Finished after " + it); return(model); }
/// <summary> /// Run GPRN without node noise /// </summary> /// <param name="inputs">Covariates X</param> /// <param name="data">Outputs Y</param> /// <param name="settings">Algorithm settings</param> /// <param name="swfn">Filename for logging</param> /// <returns>Fitted model</returns> public GPRN_VMP NetworkModelCA(Vector[] inputs, double[,] data, Settings settings, string swfn = null) { bool anyIsMissing = false; // AnyIsMissing(isMissing); var model = new GPRN_VMP(); var nodeOptimiser = new KernelOptimiser(settings); var weightOptimiser = new KernelOptimiser(settings); nodeOptimiser.xData = inputs; weightOptimiser.xData = inputs; nodeOptimiser.kernel = ObjectCloner.Clone(settings.node_kernel); nodeOptimiser.hypersToOptimise = settings.nodeHypersToOptimise; weightOptimiser.kernel = ObjectCloner.Clone(settings.weight_kernel); weightOptimiser.hypersToOptimise = settings.weightHypersToOptimise; var nodeFunctionsInit = Enumerable.Range(0, settings.Q).Select(i => VectorGaussian.FromMeanAndVariance( VectorGaussian.Sample(Vector.Zero(data.GetLength(1)), PositiveDefiniteMatrix.IdentityScaledBy(data.GetLength(1), 100)), PositiveDefiniteMatrix.IdentityScaledBy(data.GetLength(1), settings.init_precision))).ToArray(); // should put this manually in generated code var distArray = Distribution <Vector> .Array(nodeFunctionsInit); double inputsRange = inputs.Select(i => i[0]).Max() - inputs.Select(i => i[0]).Min(); Console.WriteLine("Init node kernel {0}\ninit weight kernel {1}", settings.node_kernel, settings.weight_kernel); model.SetObservedValue("D", data.GetLength(0)); model.SetObservedValue("Q", settings.Q); model.SetObservedValue("N", data.GetLength(1)); model.SetObservedValue("observedData", data); model.SetObservedValue("nodeFunctionsInitVar", distArray); model.SetObservedValue("K_node_inverse", Utils.GramMatrix(nodeOptimiser.kernel, inputs).Inverse()); model.SetObservedValue("K_weights_inverse", Utils.GramMatrix(weightOptimiser.kernel, inputs).Inverse()); model.SetObservedValue("noisePrecisionPrior", settings.noisePrecisionPrior); //model.SetObservedValue("nodeNoisePrecisionPrior", settings.nodeNoisePrecisionPrior); model.SetObservedValue("nodeSignalPrecisionsPrior", settings.nodeSignalPrecisionsPrior); //model.SetObservedValue("isMissing", isMissing); model.nodeKernelOptimiser = nodeOptimiser; model.weightKernelOptimiser = weightOptimiser; model.Reset(); var start = DateTime.Now; if (swfn != null) { using (var sw = new StreamWriter(swfn, true)) { sw.Write("{0} {1} {2}", "it", "time", "ml"); if (anyIsMissing) { sw.Write(" {0} {1}", "logProb", "error"); } sw.Write(" " + Utils.KernelHyperNames(nodeOptimiser.kernel).Select(o => "node_" + o).Aggregate((p, q) => p + " " + q)); sw.Write(" " + Utils.KernelHyperNames(weightOptimiser.kernel).Select(o => "weight_" + o).Aggregate((p, q) => p + " " + q)); sw.Write(" noise"); for (int i = 0; i < settings.Q; i++) { sw.Write(" signal" + i); } sw.WriteLine(); } } double oldML = double.NegativeInfinity; double ml = 0; int it = 0; for (; it < settings.max_iterations; it++) { model.Update(1); ml = model.Marginal <Bernoulli>("ev").LogOdds; var noisePrecisionPost = model.Marginal <Gamma>("noisePrecision"); double logProb = 0, error = 0, MSLL = 0, SMSE = 0; Console.WriteLine("It {9} Time: {8:G3} Node ls=exp({0:G3})={1:G3} Weight ls=exp({2:G3})={3:G3} ml={4:G3} error={5:G3} msll={6:G3} smse={7:G3}", nodeOptimiser.kernel[0], Math.Exp(nodeOptimiser.kernel[0]), weightOptimiser.kernel[0], Math.Exp(weightOptimiser.kernel[0]), ml, error, MSLL, SMSE, (DateTime.Now - start).TotalMilliseconds, it); if (Math.Abs(oldML - ml) < settings.ml_tolerance) { break; } oldML = ml; if (swfn != null) { using (var sw = new StreamWriter(swfn, true)) { var nodeSignalPrecisionsPost = model.Marginal <Gamma[]>("nodeSignalPrecisions"); sw.Write("{0} {1} {2}", it, (DateTime.Now - start).TotalMilliseconds, ml); if (anyIsMissing) { sw.Write(" {0} {1}", logProb, error); } sw.Write(" " + Utils.KernelToArray(nodeOptimiser.kernel).Select(o => o.ToString()).Aggregate((p, q) => p + " " + q)); sw.Write(" " + Utils.KernelToArray(weightOptimiser.kernel).Select(o => o.ToString()).Aggregate((p, q) => p + " " + q)); sw.Write(" " + noisePrecisionPost.GetMeanInverse()); for (int i = 0; i < settings.Q; i++) { sw.Write(" " + nodeSignalPrecisionsPost[i].GetMeanInverse()); } sw.WriteLine(); } } } Console.WriteLine("Finished after " + it); return(model); }
static IEnumerable<double[]> Samples(VectorGaussian distribution) { while (true) { yield return distribution.Sample().ToArray(); } }
/// <summary> /// Primary definition of the GPRN model as an Infer.NET model. /// </summary> /// <param name="inputs">Covariates X</param> /// <param name="data">Outputs Y</param> /// <param name="Q">Number of latent functions</param> /// <param name="missing">Which elements of Y are missing</param> /// <param name="nodeFunctionNoise">Whether to include node noise</param> /// <param name="constrainWpositive">Whether to constrain W to be positive [experimental]</param> /// <param name="isotropicNoise">Whether to use isotropic observation noise</param> /// <param name="meanFunctions">Whether to include a per output mean function</param> /// <param name="initLoglengthscales">Initial values for the length scales of the kernels</param> /// <param name="sw">An output file for logging</param> public void GPRN_InferNET_model(Vector[] inputs, double[,] data, int Q, bool grid = false, bool[,] missing = null, bool nodeFunctionNoise = false, bool constrainWpositive = false, bool isotropicNoise = true, bool meanFunctions = false, double[] initLoglengthscales = null, StreamWriter sw = null) { var toInfer = new List <IVariable>(); SummationKernel kf_node = new SummationKernel(new SquaredExponential(0)) + new WhiteNoise(-3); var K_node = Utils.GramMatrix(kf_node, inputs); SummationKernel kf_weights = new SummationKernel(new SquaredExponential(1)) + new WhiteNoise(-3); var K_weights = Utils.GramMatrix(kf_weights, inputs); var D = Variable.Observed <int>(data.GetLength(0)).Named("D"); var d = new Range(D).Named("d"); var Qvar = Variable.Observed <int>(Q).Named("Q"); var q = new Range(Qvar).Named("q"); var N = Variable.Observed <int>(data.GetLength(1)).Named("N"); var n = new Range(N).Named("n"); if (missing == null) { missing = new bool[D.ObservedValue, N.ObservedValue]; // check this is all false } var ev = Variable.Bernoulli(.5).Named("ev"); var modelBlock = Variable.If(ev); var nodeSignalPrecisions = Variable.Array <double>(q).Named("nodeSignalPrecisions"); // set this to 1 if not learning signal variance var nodeSignalPrecisionsPrior = Variable.Observed(Enumerable.Range(0, Q).Select(_ => Gamma.FromShapeAndRate(.1, .1)).ToArray(), q).Named("nodeSignalPrecisionsPrior"); nodeSignalPrecisions[q] = Variable.Random <double, Gamma>(nodeSignalPrecisionsPrior[q]); var nodeFunctions = Variable.Array <Vector>(q).Named("nodeFunctions"); var K_node_inverse = Variable.Observed(K_node.Inverse()).Named("K_node_inverse"); nodeFunctions[q] = Variable <Vector> .Factor(MyFactors.VectorGaussianScaled, nodeSignalPrecisions[q], K_node_inverse); nodeFunctions.AddAttribute(new MarginalPrototype(new VectorGaussian(N.ObservedValue))); var nodeFunctionValues = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValues"); var nodeFunctionValuesPredictive = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValuesPredictive"); VariableArray <double> nodeNoisePrecisions = null; if (nodeFunctionNoise) { var nodeFunctionValuesClean = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValuesClean"); nodeFunctionValuesClean[q] = Variable.ArrayFromVector(nodeFunctions[q], n); nodeNoisePrecisions = Variable.Array <double>(q).Named("nodeNoisePrecisions"); var nodeNoisePrecisionPrior = Variable.Observed(Enumerable.Range(0, Q).Select(_ => Gamma.FromShapeAndRate(.1, .01)).ToArray(), q).Named("nodeNoisePrecisionPrior"); nodeNoisePrecisions[q] = Variable.Random <double, Gamma>(nodeNoisePrecisionPrior[q]); toInfer.Add(nodeNoisePrecisions); nodeFunctionValues[q][n] = Variable.GaussianFromMeanAndPrecision(nodeFunctionValuesClean[q][n], nodeNoisePrecisions[q]); nodeFunctionValuesPredictive[q][n] = Variable.GaussianFromMeanAndPrecision(nodeFunctionValuesClean[q][n], nodeNoisePrecisions[q]); } else { nodeFunctionValues[q] = Variable.ArrayFromVector(nodeFunctions[q], n); nodeFunctionValuesPredictive[q] = Variable.ArrayFromVector(nodeFunctions[q], n); } var weightFunctions = Variable.Array <Vector>(d, q).Named("weightFunctions"); var K_weights_inverse = Variable.Observed(K_weights.Inverse()).Named("K_weights_inverse"); weightFunctions[d, q] = Variable <Vector> .Factor(MyFactors.VectorGaussianScaled, Variable.Constant <double>(1), K_weights_inverse).ForEach(d, q); weightFunctions.AddAttribute(new MarginalPrototype(new VectorGaussian(N.ObservedValue))); var weightFunctionValues = Variable.Array(Variable.Array <double>(n), d, q).Named("weightFunctionValues"); var weightFunctionValues2 = Variable.Array(Variable.Array <double>(n), d, q).Named("weightFunctionValuesPredictive"); weightFunctionValues[d, q] = Variable.ArrayFromVector(weightFunctions[d, q], n); if (constrainWpositive) { var weightFunctionValuesCopy = Variable.Array(Variable.Array <double>(n), d, q).Named("weightFunctionValuesCopy"); weightFunctionValuesCopy[d, q][n] = Variable.GaussianFromMeanAndPrecision(weightFunctionValues[d, q][n], 100); Variable.ConstrainPositive(weightFunctionValuesCopy[d, q][n]); } weightFunctionValues2[d, q] = Variable.ArrayFromVector(weightFunctions[d, q], n); var observedData = Variable.Array <double>(d, n).Named("observedData"); var noisePrecisionPrior = Variable.Observed(Gamma.FromShapeAndRate(1, .1)).Named("noisePrecisionPrior"); Variable <double> noisePrecision = null; VariableArray <double> noisePrecisionArray = null; if (isotropicNoise) { noisePrecision = Variable.Random <double, Gamma>(noisePrecisionPrior).Named("noisePrecision"); toInfer.Add(noisePrecision); } else { noisePrecisionArray = Variable.Array <double>(d).Named("noisePrecision"); noisePrecisionArray[d] = Variable.Random <double, Gamma>(noisePrecisionPrior).ForEach(d); toInfer.Add(noisePrecisionArray); } var isMissing = Variable.Array <bool>(d, n).Named("isMissing"); isMissing.ObservedValue = missing; var noiseLessY = Variable.Array <double>(d, n).Named("noiseLessY"); VariableArray <VariableArray <double>, double[][]> meanFunctionValues = null; if (meanFunctions) { GPFactor.settings = new Settings { solverMethod = Settings.SolverMethod.GradientDescent, }; VariableArray <KernelFunction> kf = Variable.Array <KernelFunction>(d); kf.ObservedValue = Enumerable.Range(0, D.ObservedValue).Select( o => new SummationKernel(new SquaredExponential()) + new WhiteNoise(-3)).ToArray(); var mf = Variable.Array <Vector>(d).Named("meanFunctions"); mf[d] = Variable <Vector> .Factor <double, Vector[], int[], KernelFunction>(MyFactors.GP, 1.0 /*Variable.GammaFromShapeAndRate(1,1)*/, inputs, new int[] { 0 }, kf[d]); mf.AddAttribute(new MarginalPrototype(new VectorGaussian(N.ObservedValue))); meanFunctionValues = Variable.Array(Variable.Array <double>(n), d).Named("meanFunctionValues"); meanFunctionValues[d] = Variable.ArrayFromVector(mf[d], n); toInfer.Add(meanFunctionValues); } using (Variable.ForEach(n)) using (Variable.ForEach(d)) { var temp = Variable.Array <double>(q).Named("temp"); temp[q] = weightFunctionValues[d, q][n] * nodeFunctionValues[q][n]; if (meanFunctions) { noiseLessY[d, n] = Variable.Sum(temp) + meanFunctionValues[d][n]; } else { noiseLessY[d, n] = Variable.Sum(temp); } using (Variable.IfNot(isMissing[d, n])) if (isotropicNoise) { observedData[d, n] = Variable.GaussianFromMeanAndPrecision(noiseLessY[d, n], noisePrecision); } else { observedData[d, n] = Variable.GaussianFromMeanAndPrecision(noiseLessY[d, n], noisePrecisionArray[d]); } using (Variable.If(isMissing[d, n])) observedData[d, n] = Variable.GaussianFromMeanAndPrecision(0, 1); } observedData.ObservedValue = data; var nodeFunctionsInit = Enumerable.Range(0, Q).Select(i => VectorGaussian.FromMeanAndVariance( VectorGaussian.Sample(Vector.Zero(N.ObservedValue), PositiveDefiniteMatrix.IdentityScaledBy(N.ObservedValue, 100)), PositiveDefiniteMatrix.IdentityScaledBy(N.ObservedValue, 100))).ToArray(); // should put this manually in generated code var distArray = Distribution <Vector> .Array(nodeFunctionsInit); var nodeFunctionsInitVar = Variable.Observed(distArray).Named("nodeFunctionsInitVar"); nodeFunctions.InitialiseTo(nodeFunctionsInitVar); modelBlock.CloseBlock(); toInfer.AddRange(new List <IVariable>() { ev, noiseLessY, nodeFunctionValues, nodeSignalPrecisions, nodeFunctionValuesPredictive, weightFunctionValues, weightFunctionValues2 }); var infer = new InferenceEngine(new VariationalMessagePassing()); infer.ModelName = "MeanFunction"; var ca = infer.GetCompiledInferenceAlgorithm(toInfer.ToArray()); var kernel = new SummationKernel(new SquaredExponential(initLoglengthscales[0])); kernel += new WhiteNoise(-3); ca.SetObservedValue(K_node_inverse.NameInGeneratedCode, Utils.GramMatrix(kernel, inputs).Inverse()); kernel = new SummationKernel(new SquaredExponential(initLoglengthscales[1])); kernel += new WhiteNoise(-3); ca.SetObservedValue(K_weights_inverse.NameInGeneratedCode, Utils.GramMatrix(kernel, inputs).Inverse()); ca.Reset(); double oldML = double.NegativeInfinity; double ml = 0; int it = 0; for (; it < 100; it++) { ca.Update(1); ml = ca.Marginal <Bernoulli>(ev.NameInGeneratedCode).LogOdds; Console.WriteLine(ml); if (Math.Abs(oldML - ml) < .1) { break; } oldML = ml; } Console.WriteLine("Finished after " + it); }
/// <summary> /// An implementation of GPRN specialised for one step look ahead multivariate volatility experiments /// </summary> /// <param name="inputs">Covariates X</param> /// <param name="data">Outputs Y</param> /// <returns>Predicted covariance for the next time point</returns> public VectorGaussian GPRN_MultivariateVolatility( Vector[] inputs, double[,] data, double[] nodeSignalPrecs, double[] nodeNoisePrecs, double obsNoisePrec, ref VectorGaussian[] finit, ref VectorGaussian[,] winit, KernelFunction nodeKernel, KernelFunction weightKernel) { var missing = new bool[data.GetLength(0), data.GetLength(1)]; for (int i = 0; i < data.GetLength(0); i++) { missing[i, data.GetLength(1) - 1] = true; // last data point is missing } int Q = nodeSignalPrecs.Length; var toInfer = new List <IVariable>(); var K_node = Utils.GramMatrix(nodeKernel, inputs); var K_weights = Utils.GramMatrix(weightKernel, inputs); var D = Variable.Observed <int>(data.GetLength(0)).Named("D"); var d = new Range(D).Named("d"); var Qvar = Variable.Observed <int>(Q).Named("Q"); var q = new Range(Qvar).Named("q"); var N = Variable.Observed <int>(data.GetLength(1)).Named("N"); var n = new Range(N).Named("n"); var ev = Variable.Bernoulli(.5).Named("ev"); var modelBlock = Variable.If(ev); var nodeSignalPrecisions = Variable.Array <double>(q).Named("nodeSignalPrecisions"); nodeSignalPrecisions.ObservedValue = nodeSignalPrecs; var nodeFunctions = Variable.Array <Vector>(q).Named("nodeFunctions"); var K_node_inverse = Variable.Observed(K_node.Inverse()).Named("K_node_inverse"); nodeFunctions[q] = Variable <Vector> .Factor(MyFactors.VectorGaussianScaled, nodeSignalPrecisions[q], K_node_inverse); nodeFunctions.AddAttribute(new MarginalPrototype(new VectorGaussian(N.ObservedValue))); var nodeFunctionValues = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValues"); var nodeFunctionValuesPredictive = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValuesPredictive"); var nodeFunctionValuesClean = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValuesClean"); nodeFunctionValuesClean[q] = Variable.ArrayFromVector(nodeFunctions[q], n); var nodeNoisePrecisions = Variable.Array <double>(q).Named("nodeNoisePrecisions"); nodeNoisePrecisions.ObservedValue = nodeNoisePrecs; nodeFunctionValues[q][n] = Variable.GaussianFromMeanAndPrecision(nodeFunctionValuesClean[q][n], nodeNoisePrecisions[q]); nodeFunctionValuesPredictive[q][n] = Variable.GaussianFromMeanAndPrecision(nodeFunctionValuesClean[q][n], nodeNoisePrecisions[q]); var weightFunctions = Variable.Array <Vector>(d, q).Named("weightFunctions"); var K_weights_inverse = Variable.Observed(K_weights.Inverse()).Named("K_weights_inverse"); weightFunctions[d, q] = Variable <Vector> .Factor(MyFactors.VectorGaussianScaled, Variable.Constant <double>(1), K_weights_inverse).ForEach(d, q); weightFunctions.AddAttribute(new MarginalPrototype(new VectorGaussian(N.ObservedValue))); var weightFunctionValues = Variable.Array(Variable.Array <double>(n), d, q).Named("weightFunctionValues"); var weightFunctionValuesPredictive = Variable.Array(Variable.Array <double>(n), d, q).Named("weightFunctionValuesPredictive"); weightFunctionValues[d, q] = Variable.ArrayFromVector(weightFunctions[d, q], n); weightFunctionValuesPredictive[d, q] = Variable.ArrayFromVector(weightFunctions[d, q], n); var observedData = Variable.Array <double>(d, n).Named("observedData"); var noisePrecision = Variable.Observed(obsNoisePrec).Named("noisePrecision"); var isMissing = Variable.Array <bool>(d, n).Named("isMissing"); isMissing.ObservedValue = missing; var noiseLessY = Variable.Array <double>(d, n).Named("noiseLessY"); using (Variable.ForEach(n)) using (Variable.ForEach(d)) { var temp = Variable.Array <double>(q).Named("temp"); temp[q] = weightFunctionValues[d, q][n] * nodeFunctionValues[q][n]; noiseLessY[d, n] = Variable.Sum(temp); using (Variable.IfNot(isMissing[d, n])) observedData[d, n] = Variable.GaussianFromMeanAndPrecision(noiseLessY[d, n], noisePrecision); using (Variable.If(isMissing[d, n])) observedData[d, n] = Variable.GaussianFromMeanAndPrecision(0, 1); } observedData.ObservedValue = data; var nodeFunctionsInit = Enumerable.Range(0, Q).Select(i => VectorGaussian.FromMeanAndVariance( VectorGaussian.Sample(Vector.Zero(N.ObservedValue), PositiveDefiniteMatrix.IdentityScaledBy(N.ObservedValue, 100)), PositiveDefiniteMatrix.IdentityScaledBy(N.ObservedValue, 100))).ToArray(); // should put this manually in generated code var distArray = Distribution <Vector> .Array(nodeFunctionsInit); var nodeFunctionsInitVar = Variable.Observed(distArray).Named("nodeFunctionsInitVar"); nodeFunctions.InitialiseTo(nodeFunctionsInitVar); var finitNew = finit.Select(i => Utils.extendByOneDimension(i, Gaussian.FromMeanAndVariance(0, 1))).ToArray(); nodeFunctions.InitialiseTo(Distribution <Vector> .Array(finitNew)); var winitNew = new VectorGaussian[data.GetLength(0), Q]; for (int i = 0; i < data.GetLength(0); i++) { for (int j = 0; j < Q; j++) { winitNew[i, j] = Utils.extendByOneDimension(winit[i, j], Gaussian.FromMeanAndVariance(0, 1)); } } weightFunctions.InitialiseTo(Distribution <Vector> .Array(winitNew)); modelBlock.CloseBlock(); toInfer.AddRange(new List <IVariable>() { ev, noiseLessY, nodeFunctions, weightFunctions, nodeFunctionValuesPredictive, weightFunctionValues, weightFunctionValuesPredictive /* is this redundant? */ }); var ie = new InferenceEngine(new VariationalMessagePassing()); var ca = ie.GetCompiledInferenceAlgorithm(toInfer.ToArray()); ca.SetObservedValue(K_node_inverse.NameInGeneratedCode, Utils.GramMatrix(nodeKernel, inputs).Inverse()); ca.SetObservedValue(K_weights_inverse.NameInGeneratedCode, Utils.GramMatrix(weightKernel, inputs).Inverse()); ca.Reset(); double oldML = double.NegativeInfinity; double ml = 0; int it = 0; for (; it < 30; it++) { ca.Update(1); ml = ca.Marginal <Bernoulli>(ev.NameInGeneratedCode).LogOdds; Console.WriteLine(ml); if (Math.Abs(oldML - ml) < .1) { break; } oldML = ml; } var f = ca.Marginal <Gaussian[][]>("nodeFunctionValuesPredictive"); var W = ca.Marginal <Gaussian[, ][]>("weightFunctionValuesPredictive"); finit = ca.Marginal <VectorGaussian[]>(nodeFunctions.NameInGeneratedCode); winit = ca.Marginal <VectorGaussian[, ]>(weightFunctions.NameInGeneratedCode); return(Utils.CorrelatedPredictionsHelper(f, W, Gamma.PointMass(obsNoisePrec), Q, data.GetLength(0), data.GetLength(1) - 1)); }
/// <summary> /// Infer.NET definition of the Semi Parametric Latent Factor Model of /// Teh, Y., Seeger, M., and Jordan, M. (AISTATS 2005). /// </summary> /// <param name="inputs">Covariates X</param> /// <param name="data">Outputs Y</param> /// <param name="Q">Number of latent functions</param> /// <param name="missing">Which elements of Y are missing</param> /// <param name="nodeFunctionNoise">Whether to include node noise</param> public void SPLFM( Vector[] inputs, double[,] data, int Q, bool[,] missing = null, bool nodeFunctionNoise = false) { var toInfer = new List <IVariable>(); SummationKernel kf_node = new SummationKernel(new SquaredExponential(0)); var K_node = Utils.GramMatrix(kf_node, inputs); var D = Variable.Observed <int>(data.GetLength(0)).Named("D"); var d = new Range(D).Named("d"); var Qvar = Variable.Observed <int>(Q).Named("Q"); var q = new Range(Qvar).Named("q"); var N = Variable.Observed <int>(data.GetLength(1)).Named("N"); var n = new Range(N).Named("n"); if (missing == null) { missing = new bool[D.ObservedValue, N.ObservedValue]; // check this is all false } var ev = Variable.Bernoulli(.5).Named("ev"); var modelBlock = Variable.If(ev); var nodeSignalPrecisions = Variable.Array <double>(q).Named("nodeSignalPrecisions"); // set this to 1 if not learning signal variance var nodeSignalPrecisionsPrior = Variable.Observed(Enumerable.Range(0, Q).Select(_ => Gamma.FromShapeAndRate(.1, .1)).ToArray(), q).Named("nodeSignalPrecisionsPrior"); nodeSignalPrecisions[q] = Variable.Random <double, Gamma>(nodeSignalPrecisionsPrior[q]); var nodeFunctions = Variable.Array <Vector>(q).Named("nodeFunctions"); var K_node_inverse = Variable.Observed(K_node.Inverse()).Named("K_node_inverse"); nodeFunctions[q] = Variable <Vector> .Factor(MyFactors.VectorGaussianScaled, nodeSignalPrecisions[q], K_node_inverse); nodeFunctions.AddAttribute(new MarginalPrototype(new VectorGaussian(N.ObservedValue))); var nodeFunctionValues = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValues"); var nodeFunctionValuesPredictive = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValuesPredictive"); VariableArray <double> nodeNoisePrecisions = null; if (nodeFunctionNoise) { var nodeFunctionValuesClean = Variable.Array(Variable.Array <double>(n), q).Named("nodeFunctionValuesClean"); nodeFunctionValuesClean[q] = Variable.ArrayFromVector(nodeFunctions[q], n); nodeNoisePrecisions = Variable.Array <double>(q).Named("nodeNoisePrecisions"); var nodeNoisePrecisionPrior = Variable.Observed(Enumerable.Range(0, Q).Select(_ => Gamma.FromShapeAndRate(.1, .01)).ToArray(), q).Named("nodeNoisePrecisionPrior"); nodeNoisePrecisions[q] = Variable.Random <double, Gamma>(nodeNoisePrecisionPrior[q]); toInfer.Add(nodeNoisePrecisions); nodeFunctionValues[q][n] = Variable.GaussianFromMeanAndPrecision(nodeFunctionValuesClean[q][n], nodeNoisePrecisions[q]); nodeFunctionValuesPredictive[q][n] = Variable.GaussianFromMeanAndPrecision(nodeFunctionValuesClean[q][n], nodeNoisePrecisions[q]); } else { nodeFunctionValues[q] = Variable.ArrayFromVector(nodeFunctions[q], n); nodeFunctionValuesPredictive[q] = Variable.ArrayFromVector(nodeFunctions[q], n); } var weights = Variable.Array <double>(d, q).Named("weights"); weights[d, q] = Variable.GaussianFromMeanAndPrecision(0, 1).ForEach(d, q); var observedData = Variable.Array <double>(d, n).Named("observedData"); var noisePrecisionPrior = Variable.Observed(Gamma.FromShapeAndRate(1, .1)).Named("noisePrecisionPrior"); var noisePrecision = Variable.Random <double, Gamma>(noisePrecisionPrior).Named("noisePrecision"); var isMissing = Variable.Array <bool>(d, n).Named("isMissing"); isMissing.ObservedValue = missing; var noiseLessY = Variable.Array <double>(d, n).Named("noiseLessY"); using (Variable.ForEach(n)) using (Variable.ForEach(d)) { var temp = Variable.Array <double>(q).Named("temp"); temp[q] = weights[d, q] * nodeFunctionValues[q][n]; noiseLessY[d, n] = Variable.Sum(temp); using (Variable.IfNot(isMissing[d, n])) observedData[d, n] = Variable.GaussianFromMeanAndPrecision(noiseLessY[d, n], noisePrecision); using (Variable.If(isMissing[d, n])) observedData[d, n] = Variable.GaussianFromMeanAndPrecision(0, 1); } observedData.ObservedValue = data; var nodeFunctionsInit = Enumerable.Range(0, Q).Select(i => VectorGaussian.FromMeanAndVariance( VectorGaussian.Sample(Vector.Zero(N.ObservedValue), PositiveDefiniteMatrix.IdentityScaledBy(N.ObservedValue, 100)), PositiveDefiniteMatrix.IdentityScaledBy(N.ObservedValue, 100))).ToArray(); // should put this manually in generated code var distArray = Distribution <Vector> .Array(nodeFunctionsInit); var nodeFunctionsInitVar = Variable.Observed(distArray).Named("nodeFunctionsInitVar"); nodeFunctions.InitialiseTo(nodeFunctionsInitVar); modelBlock.CloseBlock(); toInfer.AddRange(new List <IVariable>() { ev, noiseLessY, noisePrecision, nodeFunctionValues, nodeSignalPrecisions, nodeFunctionValuesPredictive, weights }); var ie = new InferenceEngine(new VariationalMessagePassing()); ie.ModelName = "SPLFM"; var ca = ie.GetCompiledInferenceAlgorithm(toInfer.ToArray()); ca.Execute(100); var fvals = ca.Marginal <Gaussian[][]>(nodeFunctionValues.NameInGeneratedCode)[0]; // [q][n] var x = inputs.Select(i => i[0]).ToArray(); var mplWrapper = new MatplotlibWrapper(); mplWrapper.AddArray("x", x); mplWrapper.AddArray("y", fvals.Select(i => i.GetMean()).ToArray()); mplWrapper.AddArray("s", fvals.Select(i => Math.Sqrt(i.GetVariance())).ToArray()); mplWrapper.Plot(new string[] { "fill_between(x,y-s,y+s,color=\"gray\")", "ylabel(\"node (fitted)\")" }); }