CSx641 - Exercise 3

This exercise is intended to make you familiar with the Bayes Net Toolbox for Matlab, written by Kevin Murphy. It is only a very basic introduction to make sure that everyone has access to the toolbox and knows some basics about Matlab. The toolbox will be used for assignment 2.

Please go through the example and exercise sections below, and submit a single sheet of paper with the result of the exercise section. Contact me (kaess@cc) or post to the newsgroup if you need any help installing the toolbox or using Matlab.

This document is copied in parts from How to use the Bayes Net Toolbox by Kevin Murphy.

For an introduction to Matlab and links to other tutorials, see my Another Brief Matlab Tutorial page.

Installation

The toolbox is freely available from Kevin Murphy. You can use my installation in /net/hzr1/users/kaess/FullBNT, accessible from any CoC linux/unix box (I'm not sure if it's possible to access it from Windows). Or, feel free to install it in your CoC account or on your home machine (needs about 5MB), download here

You need Matlab version 5.2 or newer to run BNT. (Versions 5.0 and 5.1 have a memory leak which seems to sometimes crash BNT.)

Test your installation

  • Start Matlab

  • Move to the BNT directory. For example, if you are on a CoC linux box, type
    >> cd /net/hzr1/users/kaess/FullBNT/BNT
    

  • Type "add_BNT_to_path". This executes the command addpath(genpath(BNT_HOME)), which adds all directories below FullBNT to the matlab path.

  • Type "test_BNT". This script might take a few minutes to complete. If all goes well, this will produce a bunch of numbers and maybe some warning messages (which you can ignore), but no error messages. (The warnings should only be of the form "Warning: Maximum number of iterations has been exceeded", and are produced by Netlab.)
  • If you are new to Matlab, you might like to check out some useful Matlab tips. For instance, this explains how to create a startup file, which can be used to set your path variable automatically, so you can avoid having to type the above commands every time.

    Example

    Consider the following network.

    Structure

    To specify this directed acyclic graph (DAG), create an adjacency matrix:

    N = 4; 
    dag = zeros(N,N);
    C = 1; S = 2; R = 3; W = 4;
    dag(C,[R S]) = 1;
    dag(R,W) = 1;
    dag(S,W)=1;
    

    We have numbered the nodes as follows: Cloudy = 1, Sprinkler = 2, Rain = 3, WetGrass = 4. The nodes must always be numbered in topological order, i.e., ancestors before descendants.

    In addition to specifying the DAG, we must specify the size and type of each node. If a node is discrete, its size is the number of possible values each node can take on; if a node is continuous, it can be a vector, and its size is the length of this vector. In this case, we will assume all nodes are discrete and binary.

    discrete_nodes = 1:N;
    node_sizes = 2*ones(1,N);
    

    We are now ready to make the Bayes net:

    bnet = mk_bnet(dag, node_sizes, 'discrete', discrete_nodes);
    
    By default, all nodes are assumed to be discrete, so we can also just write
    bnet = mk_bnet(dag, node_sizes);
    
    For more details on the parameters of mk_bnet, please see its documentation string by typing
    help mk_bnet
    

    Parameters

    A model consists of the graph structure and the parameters. The parameters are represented by CPD objects (CPD = Conditional Probability Distribution), which define the probability distribution of a node given its parents. (We will use the terms "node" and "random variable" interchangeably.) The simplest kind of CPD is a table (multi-dimensional array), which is suitable when all the nodes are discrete-valued. Note that the discrete values are not assumed to be ordered in any way; that is, they represent categorical quantities, like male and female, rather than ordinal quantities, like low, medium and high.

    Tabular CPDs, also called CPTs (conditional probability tables), are stored as multidimensional arrays, where the dimensions are arranged in the same order as the nodes, e.g., the CPT for node 4 (WetGrass) is indexed by Sprinkler (2), Rain (3) and then WetGrass (4) itself. Hence the child is always the last dimension. If a node has no parents, its CPT is a column vector representing its prior. Note that in Matlab (unlike C), arrays are indexed from 1, and are layed out in memory such that the first index toggles fastest, e.g., the CPT for node 4 (WetGrass) is as follows

    where we have used the convention that false==1, true==2. We can create this CPT in Matlab as follows

    CPT = zeros(2,2,2);
    CPT(1,1,1) = 1.0;
    CPT(2,1,1) = 0.1;
    ...
    
    Here is an easier way:
    CPT = reshape([1 0.1 0.1 0.01 0 0.9 0.9 0.99], [2 2 2]);
    
    In fact, we don't need to reshape the array, since the CPD constructor will do that for us. So we can just write
    bnet.CPD{W} = tabular_CPD(bnet, W, 'CPT', [1 0.1 0.1 0.01 0 0.9 0.9 0.99]);
    
    The other nodes are created similarly (using the old syntax for optional parameters)
    bnet.CPD{C} = tabular_CPD(bnet, C, [0.5 0.5]);
    bnet.CPD{R} = tabular_CPD(bnet, R, [0.8 0.2 0.2 0.8]);
    bnet.CPD{S} = tabular_CPD(bnet, S, [0.5 0.9 0.5 0.1]);
    bnet.CPD{W} = tabular_CPD(bnet, W, [1 0.1 0.1 0.01 0 0.9 0.9 0.99]);
    

    Inference

    Having created the BN, we can now use it for inference. There are many different algorithms for doing inference in Bayes nets, that make different tradeoffs between speed, complexity, generality, and accuracy. BNT therefore offers a variety of different inference "engines". We will discuss these in more detail below. For now, we will use the junction tree engine, which is the mother of all exact inference algorithms. This can be created as follows.
    engine = jtree_inf_engine(bnet);
    
    The other engines have similar constructors, but might take additional, algorithm-specific parameters. All engines are used in the same way, once they have been created. We illustrate this in the following sections.

    Suppose we want to compute the probability that the sprinkler was on given that the grass is wet. The evidence consists of the fact that W=2. All the other nodes are hidden (unobserved). We can specify this as follows.

    evidence = cell(1,N);
    evidence{W} = 2;
    
    We use a 1D cell array instead of a vector to cope with the fact that nodes can be vectors of different lengths. In addition, the value [] can be used to denote 'no evidence', instead of having to specify the observation pattern as a separate argument.

    We are now ready to add the evidence to the engine.

    [engine, loglik] = enter_evidence(engine, evidence);
    
    The behavior of this function is algorithm-specific, and is discussed in more detail below. In the case of the jtree engine, enter_evidence implements a two-pass message-passing scheme. The first return argument contains the modified engine, which incorporates the evidence. The second return argument contains the log-likelihood of the evidence. (Not all engines are capable of computing the log-likelihood.)

    Finally, we can compute p=P(S=2|W=2) as follows.

    marg = marginal_nodes(engine, S);
    marg.T
    ans =
          0.57024
          0.42976
    p = marg.T(2);
    
    We see that p = 0.4298.

    Exercise

    Adjust the network for another region of the world with the following properties: It is more likely to be cloudy. However, most times when it is cloudy, it is not raining. Please note that you have to make up some new values. Simply choose some values that approximate this change.

    Write down or print the commands you used to make this change to the net given in the example section above. Write down or print the probability that the sprinkler was on given that the grass is wet (use the following commands):

    engine = jtree_inf_engine(bnet);
    evidence = cell(1,N);
    evidence{W} = 2;
    [engine, loglik] = enter_evidence(engine, evidence);
    marg = marginal_nodes(engine, S);
    marg.T(2)
    

    Appendix

    For a more detailed introduction to the toolbox, see How to use the Bayes Net Toolbox by Kevin Murphy.

    Back to the class webpage