使用贝叶斯服务器c#库在Unity3d中实现动态贝叶斯网络

时间:2018-11-01 05:49:34

标签: c# unity3d bayesian hidden-markov-models bayesian-networks

我正在尝试在Unity游戏中使用C#中的Bayes server创建一个动态的贝叶斯网络来进行参数学习。该实现基于此article

下图所示模型的简要说明:当玩家开始玩关卡时,我给他们分配了0.5的初始概率,他们已经知道他们正在学习的东西,在所示的网络中被表示为Prior节点。与相关的变量称为priorKnowledge。该先验节点链接到知识节点,该知识节点是表示潜在变量LearnRate的隐藏节点,需要在游戏过程中学习。该节点又连接到“问题”节点,该节点具有两种状态正确或不正确,具体取决于玩家是否正确回答了问题。根据先前节点和问题节点的状态,一旦清除了先前的级别,就可以计算学习率并将其用作下一级别的先验。 enter image description here

我有以下代码段,这些代码使用贝叶斯服务器库表示C#中的网络。

BayesServer.Network beliefnet;
Variable priorKnowledge;
Node priorKnowledgeNode;
Variable learnRate;
Node knowledgeNode;
Node questionNode;
ParameterLearning learning;
ParameterLearningOptions learningOptions;

// numberOfDistractors and levelId will be used later for added complexity in modeling
void InitializeNetworkForLevel(int numberOfDistractors, int levelId)
{
    beliefnet = new BayesServer.Network();

    // add an intial knowledge node
    priorKnowledge = new Variable("PriorKnowledge", VariableValueType.Continuous, VariableKind.Probability);
    // initialize the priorKnowledge value to 0.5 if level = 1, else set it to learn rate (may be here, or in the queryNetwork method)
    priorKnowledgeNode = new Node("Prior", priorKnowledge);
    beliefnet.Nodes.Add(priorKnowledgeNode);

    // add a knowledge node which is a latent variable (parameter to be learned from observed values
    learnRate = new Variable("LearnRate", VariableValueType.Continuous, VariableKind.Probability);
    knowledgeNode = new Node("Knowledge", learnRate);
    beliefnet.Nodes.Add(knowledgeNode);

    // add a link from prior node to knowledge node
    beliefnet.Links.Add(new Link(priorKnowledgeNode, 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
    State correct = new State("Correct");
    State inCorrect = new State("Inorrect");
    questionNode = new Node("Question", correct, inCorrect);
    beliefnet.Nodes.Add(questionNode);

    // add a link from knowledge node to question node
    beliefnet.Links.Add(new Link(knowledgeNode, questionNode));

    // We will use the RelevanceTree algorithm here, as it is optimized for parameter learning
    learning = new ParameterLearning(beliefnet, new RelevanceTreeInferenceFactory());
    learningOptions = new ParameterLearningOptions();
}

此外,下面是QueryNetwork()方法。但是,我也不清楚在评论中也提到过很多有关它的事情。首先,我需要创建一个用于参数学习的EvidenceReaderCommand对象,该对象需要3个参数:readerCommand以读取非时间数据,variableList用于非时间变量,以及ReaderOptionsvariableList需要一个变量列表,但我不确定在这种情况下应该使用什么变量。 readerCommand需要一个带有行和列的表,我不确定在这种情况下该怎么做。谁能帮助我更好地阐明这两个方面以及如何为该网络正确构建它们?

void QueryNetwork()
{
    DataColumn column;
    DataRow row;

    // don't know which nodes go into this table :(
    // is this supposed to be the conditional probability table? where will the probabilities come from?
    // most probably I'd need to add more columns, but not sure right now
    DataTable table = new DataTable("ParentTable");
    column = new DataColumn();
    column.DataType = System.Type.GetType("System.Double");
    column.ColumnName = "LearnRate";
    column.ReadOnly = true;
    column.Unique = true;
    // i am not sure but table needs to have some rows of data as well, which will be their conditional probabilities
    table.Columns.Add(column);

    IDataReaderCommand readerCommand = new DataTableDataReaderCommand(table);

    // don't know which variables should be a part of this variableList
    IList<VariableReference> variableList = new List<VariableReference>();
    variableList.Add(new VariableReference(learnRate, ColumnValueType.Value, "LearnRate"));

    EvidenceReaderCommand evidenceReaderCommand = new EvidenceReaderCommand(readerCommand, variableList, new ReaderOptions(null));
    ParameterLearningOutput result = learning.Learn(evidenceReaderCommand, learningOptions);
    Debug.Log(result.LogLikelihood.Value);
}

1 个答案:

答案 0 :(得分:0)

以下代码演示了如何创建一个简单的动态贝叶斯网络,类似于您的图像中显示的那样。

var network = new Network();

var knowledge = new Variable("Knowledge", new string[] { "False", "True" });
var nodeKnowledge = new Node(knowledge)
{
    TemporalType = TemporalType.Temporal // this is a time series node, hence re-used for each time slice
};
network.Nodes.Add(nodeKnowledge);

var question = new Variable("Question", new string[] { "Incorrect", "Correct" });
var nodeQuestion = new Node(question)
{
    TemporalType = TemporalType.Temporal  // this is a time series node, hence re-used for each time slice
};
network.Nodes.Add(nodeQuestion);

network.Links.Add(new Link(nodeKnowledge, nodeKnowledge, 1));   // time series link (order/lag 1)
network.Links.Add(new Link(nodeKnowledge, nodeQuestion, 0));

这将创建一个DBN,如下图所示。 (这实际上只是一个简单的“隐马尔可夫”模型,但可以扩展以创建更复杂的模型)

Simple DBN

如果要展开此DBN(推理不需要),它将看起来像这样(在紧凑视图中):

Simple DBN unrolled

为了了解网络的参数,请参见以下链接,可以对其进行修改以了解该网络。

Parameter learning code example in C#

要查看如何布局数据,请参见以下链接:

Data and temporal data layout