diff options
| author | ziejd2 | 2017-09-28 15:04:40 -0500 |
|---|---|---|
| committer | ziejd2 | 2017-09-28 15:04:40 -0500 |
| commit | 8070dc963753142bb86c4ed698d91fd623ed28e7 (patch) | |
| tree | d0f6dd8fc46a49b819aa55c1a90faa14d8448883 /sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine | |
| parent | 7cc31810d53176e805532b2789955f4eedbce6bb (diff) | |
| download | BNW-8070dc963753142bb86c4ed698d91fd623ed28e7.tar.gz | |
BNW using Octave instead of Matlab.
This version of BNW should perform the same as the original version. The only difference is that it uses Octave instead of Matlab when running BayesNet Toolbox during parameter learning. I am calling this BNW_1.02. It can be accessed at: compbio.uthsc.edu/BNW_1.02
Diffstat (limited to 'sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine')
12 files changed, 216 insertions, 0 deletions
diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Entries new file mode 100644 index 00000000..dce274e1 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Entries @@ -0,0 +1,5 @@ +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/kalman_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002// +/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +D/private//// diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Repository new file mode 100644 index 00000000..674f2eea --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/dynamic/@kalman_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/enter_evidence.m new file mode 100644 index 00000000..4ba51942 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/enter_evidence.m @@ -0,0 +1,83 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (kalman) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector) +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% maximize - if 1, does max-product (same as sum-product for Gaussians!), else sum-product [0] +% filter - if 1, do filtering, else smoothing [0] +% +% e.g., engine = enter_evidence(engine, ev, 'maximize', 1) + +maximize = 0; +filter = 0; + +% parse optional params +args = varargin; +nargs = length(args); +if nargs > 0 + for i=1:2:nargs + switch args{i}, + case 'maximize', maximize = args{i+1}; + case 'filter', filter = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +assert(~maximize); + +bnet = bnet_from_engine(engine); +n = length(bnet.intra); +onodes = bnet.observed; +hnodes = mysetdiff(1:n, onodes); +T = size(evidence, 2); +ns = bnet.node_sizes; +O = sum(ns(onodes)); +data = reshape(cat(1, evidence{onodes,:}), [O T]); + +A = engine.trans_mat; +C = engine.obs_mat; +Q = engine.trans_cov; +R = engine.obs_cov; +init_x = engine.init_state; +init_V = engine.init_cov; + +if filter + [x, V, VV, loglik] = kalman_filter(data, A, C, Q, R, init_x, init_V); +else + [x, V, VV, loglik] = kalman_smoother(data, A, C, Q, R, init_x, init_V); +end + + +% Wrap the posterior inside a potential, so it can be marginalized easily +engine.one_slice_marginal = cell(1,T); +engine.two_slice_marginal = cell(1,T); +ns(onodes) = 0; +ns(onodes+n) = 0; +ss = length(bnet.intra); +for t=1:T + dom = (1:n); + engine.one_slice_marginal{t} = mpot(dom+(t-1)*ss, ns(dom), 1, x(:,t), V(:,:,t)); +end +% for t=1:T-1 +% dom = (1:(2*n)); +% mu = [x(:,t); x(:,t)]; +% Sigma = [V(:,:,t) VV(:,:,t+1)'; +% VV(:,:,t+1) V(:,:,t+1)]; +% engine.two_slice_marginal{t} = mpot(dom+(t-1)*ss, ns(dom), 1, mu, Sigma); +% end +for t=2:T + %dom = (1:(2*n)); + current_slice = hnodes; + next_slice = hnodes + ss; + dom = [current_slice next_slice]; + mu = [x(:,t-1); x(:,t)]; + Sigma = [V(:,:,t-1) VV(:,:,t)'; + VV(:,:,t) V(:,:,t)]; + engine.two_slice_marginal{t-1} = mpot(dom+(t-2)*ss, ns(dom), 1, mu, Sigma); +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/kalman_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/kalman_inf_engine.m new file mode 100644 index 00000000..df03a56f --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/kalman_inf_engine.m @@ -0,0 +1,23 @@ +function engine = kalman_inf_engine(bnet) +% KALMAN_INF_ENGINE Inference engine for Linear-Gaussian state-space models. +% engine = kalman_inf_engine(bnet) +% +% 'onodes' specifies which nodes are observed; these must be leaves. +% The remaining nodes are all hidden. All nodes must have linear-Gaussian CPDs. +% The hidden nodes must be persistent, i.e., they must have children in +% the next time slice. In addition, they may not have any children within the current slice, +% except to the observed leaves. In other words, the topology must be isomorphic to a standard LDS. +% +% There are many derivations of the filtering and smoothing equations for Linear Dynamical +% Systems in the literature. I particularly like the following +% - "From HMMs to LDSs", T. Minka, MIT Tech Report, (no date), available from +% ftp://vismod.www.media.mit.edu/pub/tpminka/papers/minka-lds-tut.ps.gz + +[engine.trans_mat, engine.trans_cov, engine.obs_mat, engine.obs_cov, engine.init_state, engine.init_cov] = ... + dbn_to_lds(bnet); + +% This is where we will store the results between enter_evidence and marginal_nodes +engine.one_slice_marginal = []; +engine.two_slice_marginal = []; + +engine = class(engine, 'kalman_inf_engine', inf_engine(bnet)); diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..738c30dc --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/marginal_nodes.m @@ -0,0 +1,25 @@ +function marginal = marginal_nodes(engine, nodes, t) +% MARGINAL_NODES Compute the marginal on the specified query nodes (kalman) +% marginal = marginal_nodes(engine, nodes, t) +% +% 't' specifies the time slice of the earliest node in 'nodes'. +% 'nodes' cannot span more than 2 time slices. +% +% Example: +% Consider a DBN with 2 nodes per slice. +% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3, +% i.e., nodes 3 and 5 in the unrolled network, + +if nargin < 3, t = 1; end + +bnet = bnet_from_engine(engine); +ss = length(bnet.intra); +if all(nodes <= ss) + bigpot = engine.one_slice_marginal{t}; +else + bigpot = engine.two_slice_marginal{t}; +end + +nodes = nodes + (t-1)*ss; +pot = marginalize_pot(bigpot, nodes); +marginal = pot_to_marginal(pot); diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Entries new file mode 100644 index 00000000..9a351a87 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Entries @@ -0,0 +1,3 @@ +/dbn_to_lds.m/1.1.1.1/Wed May 29 15:59:56 2002// +/extract_params_from_gbn.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Repository new file mode 100644 index 00000000..3f67aee0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Root b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/dbn_to_lds.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/dbn_to_lds.m new file mode 100644 index 00000000..6249ac0d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/dbn_to_lds.m @@ -0,0 +1,26 @@ +function [trans_mat, trans_cov, obs_mat, obs_cov, init_state, init_cov] = dbn_to_lds(bnet) +% DBN_TO_LDS Compute the Linear Dynamical System parameters from the Gaussian DBN. +% [trans_mat, trans_cov, obs_mat, obs_cov, init_state, init_cov] = dbn_to_lds(bnet) + +onodes = bnet.observed; +ss = length(bnet.intra); +num_nodes = ss*2; +assert(isequal(bnet.cnodes_slice, 1:ss)); +[W,D,mu] = extract_params_from_gbn(bnet); + +hnodes = mysetdiff(1:ss, onodes); +bs = bnet.node_sizes(:); % block sizes + +obs_mat = W(block(hnodes,bs), block(onodes,bs))'; +u = block(onodes,bs); +obs_cov = D(u,u); + +trans_mat = W(block(hnodes,bs), block(hnodes + ss, bs))'; +u = block(hnodes + ss, bs); +trans_cov = D(u,u); + +u = block(hnodes,bs); +init_cov = D(u,u); +init_state = mu(u); + + diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/extract_params_from_gbn.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/extract_params_from_gbn.m new file mode 100644 index 00000000..86345830 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/private/extract_params_from_gbn.m @@ -0,0 +1,38 @@ +function [B,D,mu] = extract_params_from_gbn(bnet) +% Extract all the local parameters of each Gaussian node, and collect them into global matrices. +% [B,D,mu] = extract_params_from_gbn(bnet) +% +% B(i,j) is a block matrix that contains the transposed weight matrix from node i to node j. +% D(i,i) is a block matrix that contains the noise covariance matrix for node i. +% mu(i) is a block vector that contains the shifted noise mean for node i. + +% In Shachter's model, the mean of each node in the global gaussian is +% the same as the node's local unconditional mean. +% In Alag's model (which we use), the global mean gets shifted. + + +num_nodes = length(bnet.dag); +bs = bnet.node_sizes(:); % bs = block sizes +N = sum(bs); % num scalar nodes + +B = zeros(N,N); +D = zeros(N,N); +mu = zeros(N,1); + +for i=1:num_nodes % in topological order + ps = parents(bnet.dag, i); + e = bnet.equiv_class(i); + %[m, Sigma, weights] = extract_params_from_CPD(bnet.CPD{e}); + s = struct(bnet.CPD{e}); % violate privacy of object + m = s.mean; Sigma = s.cov; weights = s.weights; + if length(ps) == 0 + mu(block(i,bs)) = m; + else + mu(block(i,bs)) = m + weights * mu(block(ps,bs)); + end + B(block(ps,bs), block(i,bs)) = weights'; + D(block(i,bs), block(i,bs)) = Sigma; +end + + + diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/update_engine.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/update_engine.m new file mode 100644 index 00000000..d89605e7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@kalman_inf_engine/update_engine.m @@ -0,0 +1,9 @@ +function engine = update_engine(engine, newCPDs) +% UPDATE_ENGINE Update the engine to take into account the new parameters (kalman) +% engine = update_engine(engine, newCPDs) + +engine.inf_engine = update_engine(engine.inf_engine, newCPDs); +[engine.trans_mat, engine.trans_cov, engine.obs_mat, engine.obs_cov, engine.init_state, engine.init_cov] = ... + dbn_to_lds(bnet_from_engine(engine)); + + |
