I am trying to build a Dynamic Bayesian Network using the BayesServer library in C# for my Unity3D game. I have the following method which implements the network
// numberOfDistractors and levelId will be used later for added complexity in modeling
void InitializeNetworkForLevel(int numberOfDistractors, int levelId)
{
beliefNet = new BayesServer.Network();
// add a knowledge node which is a latent variable (parameter to be learned from observed values
KTrue = new State("KTrue");
KFalse = new State("KFalse");
knowledge = new Variable("Knowledge", KTrue, KFalse);
knowledgeNode = new Node(knowledge)
{
TemporalType = TemporalType.Temporal // this is a time series node, hence re-used for each time slice
};
beliefNet.Nodes.Add(knowledgeNode);
// add a question node, which denotes the oberved variable whether the question is answered correctly or not
// this node has two states, namely correct or incorrect
QTrue = new State("QTrue");
QFalse = new State("QFalse");
question = new Variable("Question", QTrue, QFalse);
questionNode = new Node(question)
{
TemporalType = TemporalType.Temporal // this is a time series node, hence re-used for each time slice
};
beliefNet.Nodes.Add(questionNode);
// add a link from knowledge node to question node
beliefNet.Links.Add(new Link(knowledgeNode, questionNode, 0));
for (int i = 1; i <= 5; i++)
beliefNet.Links.Add(new Link(knowledgeNode, knowledgeNode, i)); // time series link (order/lag i)
QueryNetwork(true);
}
and then another method for making inference:
void QueryNetwork(bool isAnswerCOrrect)
{
StateContext kTrueTime0 = new StateContext(KTrue, 0);
StateContext kFalseTime0 = new StateContext(KFalse, 0);
Table priorKnowledge = knowledgeNode.NewDistribution(0).Table;
priorKnowledge[kTrueTime0] = 0.5;
priorKnowledge[kFalseTime0] = 0.5;
// NewDistribution does not assign the new distribution, so it still must be assigned
knowledgeNode.Distribution = priorKnowledge;
// the second is specified for time >= 1
Table learnRate = knowledgeNode.NewDistribution(1).Table;
// when specifying temporal distributions, variables which belong to temporal nodes must have times associated
// NOTE: Each time is specified relative to the current point in time which is defined as zero,
// therefore the time for variables at the previous time step is -1
StateContext kTrueTime1 = new StateContext(KTrue, -1);
StateContext kFalseTime1 = new StateContext(KFalse, -1);
learnRate[kTrueTime1, kTrueTime0] = 0.5;
learnRate[kFalseTime1, kTrueTime0] = 0.5;
learnRate[kTrueTime1, kFalseTime0] = 0.5;
learnRate[kFalseTime1, kFalseTime0] = 0.5;
knowledgeNode.Distributions[1] = learnRate;
Table answerStatus = questionNode.NewDistribution().Table;
StateContext qTrue = new StateContext(QTrue, 0);
StateContext qFalse = new StateContext(QFalse, 0);
answerStatus[qTrue, kTrueTime0] = 0.5;
answerStatus[qFalse, kTrueTime0] = 0.5;
answerStatus[qTrue, kFalseTime0] = 0.5;
answerStatus[qFalse, kFalseTime0] = 0.5;
questionNode.Distribution = answerStatus;
// optional check to validate network
beliefNet.Validate(new ValidationOptions());
// at this point the network has been fully specified
// we will now perform some queries on the network
RelevanceTreeInference inference = new RelevanceTreeInference(beliefNet);
RelevanceTreeQueryOptions queryOptions = new RelevanceTreeQueryOptions();
RelevanceTreeQueryOutput queryOutput = new RelevanceTreeQueryOutput();
// set some temporal evidence
if (isAnswerCOrrect)
inference.Evidence.Set(question, new double?[] { 1, 0 }, 0, 0, 2);
else
inference.Evidence.Set(question, new double?[] { 0, 1 }, 0, 0, 2);
queryOptions.LogLikelihood = true; // only ask for this if you really need it
inference.Query(queryOptions, queryOutput); // note that this can raise an exception (see help for details)
Debug.Log("LogLikelihood: " + queryOutput.LogLikelihood.Value);
}
However, I am getting the following exception when trying to validate the network in QueryNetwork
method:
InvalidNetworkException: Node [Knowledge] has a null distribution.
BayesServer.Network.Validate (BayesServer.ValidationOptions options) (at :0)
BayesNet.QueryNetwork (System.Boolean isAnswerCOrrect) (at Assets/Scripts/BayesNet.cs:97)
BayesNet.InitializeNetworkForLevel (System.Int32 numberOfDistractors, System.Int32 levelId) (at Assets/Scripts/BayesNet.cs:59)
BayesNet.Start () (at Assets/Scripts/BayesNet.cs:21)
Why does it say that Knowledge Node has null distribution when I am already specifying it in the QueryNetwork
method. Although I am able to fix this using the following piece of code:
ValidationOptions opt = new ValidationOptions();
opt.AllowNullDistributions = true;
// optional check to validate network
beliefNet.Validate(opt);
Further, I have assumed all the probabilities to be 50% for the first level, how would I change these values for the second level on the basis of inference from the first level?
Eventually, I'd like to build something like the network shown in image below where the number of Distractors is different on every level (or may be same if it is too complex):