DBN example for SMILE

The engine.
Post Reply
windtalker
Posts: 3
Joined: Mon Apr 28, 2008 1:43 pm

DBN example for SMILE

Post by windtalker »

hi,
i try to create a simple DBN using SMILE, but fail to set temporal probs. The main difficulty for now is seems cant retrieve the proper temporal node and to call SetTemporalProbabilities.

The example code looks somewhat like this:
DSL_network theNet;
theNet.ReadFile("test.xdsl");
int success= theNet.FindNode("Success");
theNet.SetTemporalType( success, dsl_plateNode);
theNet.AddTemporalArc(success, success, 1);
theProbs.SetSize(4);
theProbs[0] = 0.9;
theProbs[1] = 0.1;
theProbs[2] = 0.4;
theProbs[3] = 0.6;

//following two lines are the only way i found to use //SetTemporalProbabilities(), but seg fault here
DSL_cpt* cptNode = (DSL_cpt*) theNet.GetNode(success)->Definition();
cptNode->SetTemporalProbabilities(1, theProbs);

How should i setup temporal probabilities?
Is there recent SMILE example to show how to use DBN functions?

many thanks.

li
shooltz[BayesFusion]
Site Admin
Posts: 1417
Joined: Mon Nov 26, 2007 5:51 pm

Re: DBN example for SMILE

Post by shooltz[BayesFusion] »

Since you mention the segfault, I believe the 'success' variable, which is the result of DSL_network::FindNode call, is a valid node handle. You're passing this variable to DSL_network::GetNode later and probably GetNode returns NULL. Further call to DSL_node::Definition causes the segfault.

Note that calls to DSL_network::AddTemporalArc and DSL_network::SetTemporalType will validate the node handle and return error code if it's not correct. GetNode will also validate it, but return value is NULL (not the integer error code).

DSL_network::FindNode is case-sensitive, so maybe you just need to change the string literal to lowercase - check the .xdsl file to make sure what exactly is the node ID.
windtalker
Posts: 3
Joined: Mon Apr 28, 2008 1:43 pm

Post by windtalker »

hi shooltz,
that really prompt reply is (!!!) which encourage me continuing with another one and half hour debugging before i can further discuss sth meaningful and now problem solved! great thanks!

yes u quite right it is a naive mistake in test.xdsl where the identifier of "Success" mysteriously becomes "node2" rather than "Success". easy.

encounter another strange issue which appears the root node cant be added into temporal plate---it turned out the order of adding nodes to plate IS CRUCIAL! first child then parent, as explicitly indicated in genie document.

the only unimportant bit left is the not very good-looking pointer cast, as several classes derived from DSL_nodeDefinition and Definition() only return the base class from DSL_node. is there some functions like CptDefinition() can be used?

cheers
shooltz[BayesFusion]
Site Admin
Posts: 1417
Joined: Mon Nov 26, 2007 5:51 pm

Post by shooltz[BayesFusion] »

windtalker wrote:encounter another strange issue which appears the root node cant be added into temporal plate---it turned out the order of adding nodes to plate IS CRUCIAL! first child then parent, as explicitly indicated in genie document.
That's because GeNIe/SMILE network must be always in consistent state. Consistency rules for DBNs forbid the non-temporal arcs to go out of plate into any non-anchor node. If you create your models with your own program, you generally should call SetTemporalType before adding non-temporal arcs. The other approach, used by GeNIe, is to move nodes into plate using reverse partial ordering (see DSL_network::PartialOrdering).

the only unimportant bit left is the not very good-looking pointer cast, as several classes derived from DSL_nodeDefinition and Definition() only return the base class from DSL_node. is there some functions like CptDefinition() can be used?
The cast is going to stay, because there are multiple classes derived from DSL_nodeDefinition. You can always make it more C++-like and use static_cast instead of old-style C cast.
windtalker
Posts: 3
Joined: Mon Apr 28, 2008 1:43 pm

Post by windtalker »

as experiment proceeds, questions proceed....

1. after SetTemporalProbabilities, SetTemporalEvidence, UpdateBeliefs all performed successfully, how can i get final belief of inferred node (even for each time slice)?

what's the difference between
DSL_Dmatrix* DSL_nodeValue::GetMatrix()
DSL_Dmatrix& DSL_beliefVector::GetBeliefs()

2. after UpdateBeliefs i saved the dbn to test.xdsl and opened in genie, but the configured evidences and updated beliefs are not reflected in genie

3. UnrollNetwork(DSL_network &unrolled, std::vector<int> &unrollMap)
what should i pass to the second para?

its 2morrow's worries anyway:) many thanks
shooltz[BayesFusion]
Site Admin
Posts: 1417
Joined: Mon Nov 26, 2007 5:51 pm

Post by shooltz[BayesFusion] »

windtalker wrote:as experiment proceeds, questions proceed....

1. after SetTemporalProbabilities, SetTemporalEvidence, UpdateBeliefs all performed successfully, how can i get final belief of inferred node (even for each time slice)?
The beliefs of the plate nodes are all stored in the matrix which you can access with DSL_nodeValue::GetMatrix or DSL_beliefVector::GetBeliefs. For plate nodes the matrix will have two dimensions. First dimension represents the slice, second is the outcome index. You can access its elements with DSL_Dmatrix::operator[](const DSL_intArray&] or you can trivially generate a linear index by multiplying outcome count by slice index. For the last timeslice, you'll need to access the indices in the range [(maxslice - 1) * outcomeCount, maxSlice * outcomeCount - 1].

what's the difference between
DSL_Dmatrix* DSL_nodeValue::GetMatrix()
DSL_Dmatrix& DSL_beliefVector::GetBeliefs()
There's no difference in the context of belief vector. The first method will work for all classes dervided from DSL_nodeValue (it's virtual). The second one is specific to DSL_beliefVector.
2. after UpdateBeliefs i saved the dbn to test.xdsl and opened in genie, but the configured evidences and updated beliefs are not reflected in genie
That's by design. SMILE doesn't save/load anything which is stored in DSL_nodeValue and derived classes. If you have some evidence set(s) you'd like to use often, have a look at DSL_simpleCase class and related methods in DSL_network. Related feature in GeNIe is called 'Case Manager' (see the 'View' menu).
3. UnrollNetwork(DSL_network &unrolled, std::vector<int> &unrollMap)
what should i pass to the second para?
That's an output parameter, so it doesn't matter what's there when you call the function. After return, it'll contain the node handles of plate nodes and their counterparts in subsequent slices of unrolled network. For example, if you have S slices and P plate nodes, the vector will have S times P elements. [0..P-1] will contain handles of original plate nodes in source DBN. It's guaranteed that unrolled network has the same handles for nodes in 0th slice. [P..2*P-1] contains handles of nodes in slice 1 and so on. If you have a plate node with handle H in original DBN, then you can obtain the handles of all S unrolled nodes representing H by the following procedure:

1) find index K of H in unrollMap. It's guaranteed that it's in the [0..P-1] range.

2) for each slice J in [1..S-1] read unrollMap[J*P+K]


Disclaimer: as stated in the docs, UnrollNetwork is just an explanatory tool. There's no need to call it explicitly unless you want to have a look at temporary representation of DBN created just for inference purposes - UpdateBeliefs calls this function for DBNs.
Post Reply