Construction & inference (hybrid) in C#
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CLGaussianExample.cs" company="Bayes Server">
// Copyright (C) Bayes Server. All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace BayesServer.HelpSamples
{
using System;
using BayesServer.Inference.RelevanceTree;
public static class CLGaussianExample
{
public static void Main()
{
// In this example we programatically create a simple Bayesian network
// that has some continuous variables.
// Note that you can automatically define nodes from data using
// classes in BayesServer.Data.Discovery,
// and you can automatically learn the parameters using classes in
// BayesServer.Learning.Parameters,
// however here we build a Bayesian network from scratch.
var network = new Network("Demo");
// add the nodes (variables)
var dFalse = new State("False");
var dTrue = new State("True");
var d = new Variable("D", dFalse, dTrue);
var c1 = new Variable("C1", VariableValueType.Continuous);
var c2 = new Variable("C2", VariableValueType.Continuous);
network.Nodes.Add(new Node(d));
network.Nodes.Add(new Node(c1));
network.Nodes.Add(new Node(c2));
// add some directed links
network.Links.Add(new Link(d.Node, c2.Node));
network.Links.Add(new Link(c1.Node, c2.Node));
// at this point we have fully specified the structural (graphical) specification of the Bayesian Network.
// We must define the necessary probability distributions for each node.
// Each node in a Bayesian Network requires a probability distribution conditioned on it's parents.
// NewDistribution() can be called on a Node to create the appropriate probability distribution for a node
// or it can be created manually.
// The interface IDistribution has been designed to represent both discrete and continuous variables,
var tableD = d.Node.NewDistribution().Table; // access the table property of the Distribution
// IMPORTANT
// Note that calling Node.NewDistribution() does NOT assign the distribution to the node.
// A distribution cannot be assigned to a node until it is correctly specified.
// If a distribution becomes invalid (e.g. a parent node is added), it is automatically set to null.
tableD[dFalse] = 0.2;
tableD[dTrue] = 0.8;
// now tableD is correctly specified we can assign it to Node D;
d.Node.Distribution = tableD;
var gaussianC1 = (CLGaussian)c1.Node.NewDistribution();
gaussianC1.SetMean(c1, 3.5);
gaussianC1.SetVariance(c1, 12.2);
c1.Node.Distribution = gaussianC1;
var clgaussianC2 = (CLGaussian)c2.Node.NewDistribution();
clgaussianC2.SetMean(c2, 22.2, dFalse);
clgaussianC2.SetMean(c2, 54.6, dTrue);
clgaussianC2.SetVariance(c2, 14.6, dFalse);
clgaussianC2.SetVariance(c2, 3.2, dTrue);
clgaussianC2.SetWeight(c2, c1, 1.2, dFalse);
clgaussianC2.SetWeight(c2, c1, -2.1, dTrue);
c2.Node.Distribution = clgaussianC2;
// The network is now fully specified
// If required the network can be saved...
if (false) // change this to true to save the network
{
// network.Save("fileName.bayes"); // replace 'fileName.bayes' with your own path and uncomment start of line
}
// Now we will calculate P(C2|C1=4)
// use the factory design pattern to create the necessary inference related objects
var factory = new RelevanceTreeInferenceFactory();
var inference = factory.CreateInferenceEngine(network);
var queryOptions = factory.CreateQueryOptions();
var queryOutput = factory.CreateQueryOutput();
inference.Evidence.Set(c1, 4.0); // set c1 = 4
var queryC2 = new CLGaussian(c2);
inference.QueryDistributions.Add(queryC2);
inference.Query(queryOptions, queryOutput); // note that this can raise an exception (see help for details)
Console.WriteLine("P(C2|C1=4) = (mean " + queryC2.GetMean(c2) + ", variance " + queryC2.GetVariance(c2) + ")");
// Expected output ...
// P(C2|C1=4) = (mean 42.36, variance 64.46240000000002)
// Note that we could also calculate other queries such as P(C1,C2|D=True) or P(C2|C1,D=True) or P(C2,D|C1=4), etc...
}
}
}