diff options
Diffstat (limited to 'sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine')
16 files changed, 285 insertions, 0 deletions
diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries new file mode 100644 index 00000000..9d562fd8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries @@ -0,0 +1,9 @@ +/back.m/1.1.1.1/Wed May 29 15:59:56 2002// +/backT.m/1.1.1.1/Wed May 29 15:59:56 2002// +/fwd.m/1.1.1.1/Wed May 29 15:59:56 2002// +/fwd1.m/1.1.1.1/Wed May 29 15:59:56 2002// +/hmm_2TBN_inf_engine.m/1.1.1.1/Thu Nov 14 20:03:50 2002// +/marginal_family.m/1.1.1.1/Thu Nov 14 20:05:36 2002// +/marginal_nodes.m/1.1.1.1/Thu Nov 14 20:02:46 2002// +/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries.Log new file mode 100644 index 00000000..b2cd71e0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries.Log @@ -0,0 +1 @@ +A D/private//// diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Repository new file mode 100644 index 00000000..858ed017 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/back.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/back.m new file mode 100644 index 00000000..8ad416f7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/back.m @@ -0,0 +1,21 @@ +function b = back(engine, bfuture, f, t) + +if f.t ~= t + error('mixed up time stamps') +end + +b.t = t; +b.obslik = f.obslik; +bb_future = bfuture.beta .* bfuture.obslik; +if engine.maximize + B = repmat(bb_future(:)', length(bfuture.beta), 1); + b.beta = normalise(max(engine.transprob .* B, [], 2)); +else + b.beta = normalise((engine.transprob * bb_future)); +end +b.gamma = normalise(f.alpha .* b.beta); +if t > 1 + bb_t = b.beta .* b.obslik; + b.xi = normalise((engine.transprob .* (f.past_alpha * bb_t'))); % t-1,t +end + diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/backT.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/backT.m new file mode 100644 index 00000000..ffeb6628 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/backT.m @@ -0,0 +1,11 @@ +function b = backT(engine, f, t) + +b.t = t; +b.obslik = f.obslik; +Q = length(f.alpha); +b.beta = ones(Q,1); +b.gamma = f.alpha; +if t > 1 + bb_t = b.obslik; + b.xi = normalise((engine.transprob .* (f.past_alpha * bb_t'))); % T-1,T +end diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/fwd.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/fwd.m new file mode 100644 index 00000000..3afdf714 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/fwd.m @@ -0,0 +1,17 @@ +function [f, logscale] = fwd(engine, fpast, ev, t) +% Forwards pass. + +f.obslik = mk_hmm_obs_lik_vec(engine, ev); +transmat = engine.transprob; +f.past_alpha = fpast.alpha; +if engine.maximize + Q = length(fpast.alpha); + A = repmat(fpast.alpha, [1 Q]); + m = max(transmat .* A, [], 1); + [f.alpha, scale] = normalise(m(:) .* f.obslik); +else + [f.alpha, scale] = normalise((transmat' * fpast.alpha) .* f.obslik); +end +logscale = log(scale); +%f.xi = normalise((fpast.alpha * obslik') .* transmat); % t-1,t +f.t = t; diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/fwd1.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/fwd1.m new file mode 100644 index 00000000..ec16db4b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/fwd1.m @@ -0,0 +1,11 @@ +function [f, logscale] = fwd1(engine, ev, t) +% Forwards pass for slice 1. + +if t ~= 1 + error('mixed up time stamps') +end +prior = engine.startprob(:); +f.obslik = mk_hmm_obs_lik_vec(engine, ev); +[f.alpha, lik] = normalise(prior .* f.obslik); +logscale = log(lik); +f.t = t; diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/hmm_2TBN_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/hmm_2TBN_inf_engine.m new file mode 100644 index 00000000..8504124b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/hmm_2TBN_inf_engine.m @@ -0,0 +1,86 @@ +function engine = hmm_2TBN_inf_engine(bnet, varargin) +% HMM_2TBN_INF_ENGINE Inference engine for DBNs which uses the forwards-backwards algorithm. +% engine = hmm_2TBN_inf_engine(bnet, ...) +% +% The DBN is converted to an HMM with a single meganode, but the observed nodes remain factored. +% This can be faster than jtree if the num. hidden nodes is low, because of lower constant factors. +% +% All hidden nodes must be discrete. +% All observed nodes are assumed to be leaves. +% The parents of each observed leaf are assumed to be a subset of the hidden nodes within the same slice. +% The only exception is if bnet is an AR-HMM, where the parents are assumed to be self in the +% previous slice (continuous), plus all the discrete nodes in the current slice. + + +%% Optional arguments +%% ndx_type - 'B', 'D', or 'SD', used in marginal_family [ 'SD' ] + +ndx_type = 'SD'; +ss = bnet.nnodes_per_slice; + +% parse optional params +args = varargin; +nargs = length(args); +if nargs > 0 + for i=1:2:nargs + switch args{i}, + %case 'ndx_type', ndx_type = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +% Stuff to do with speeding up marginal_family +%engine.ndx_type = ndx_type; + +[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter); +engine.persist_bitv = zeros(1, ss); +engine.persist_bitv(engine.persist) = 1; + + +ns = bnet.node_sizes(:); +ns(bnet.observed) = 1; +ns(bnet.observed+ss) = 1; +engine.eff_node_sizes = ns; + +% for n=1:ss +% dom = 1:(2*ss); % domain of xi(:,:,1) +% fam = family(bnet.dag, n+ss); +% engine.marg_fam2_ndx_id(n) = add_ndx(dom, fam, ns, ndx_type); + +% dom = 1:ss; % domain of gamma(:,:,1) +% fam = family(bnet.dag, n); +% engine.marg_fam1_ndx_id(n) = add_ndx(dom, fam, ns, ndx_type); + +% engine.marg_singleton_ndx_id(n) = add_ndx(dom, n, ns, ndx_type); +% end + +for o=bnet.observed(:)' + %if bnet.equiv_class(o,1) ~= bnet.equiv_class(o,2) + % error(['observed node ' num2str(o) ' is not tied']) + %end + cs = children(bnet.dag, o); + if ~isempty(cs) + error(['observed node ' num2str(o) ' is not allowed children']) + end +end + +[engine.startprob, engine.transprob, engine.obsprob] = dbn_to_hmm(bnet); + +% This is where we will store the results between enter_evidence and marginal_nodes +engine.one_slice_marginal = []; +engine.two_slice_marginal = []; + +ss = length(bnet.intra); +engine.maximize = []; +engine.evidence = []; +engine.node_sizes = []; + +% avoid the need to do bnet_from_engine, which is slow +engine.slice_size = ss; +engine.parents = bnet.parents; + +engine.bel = []; +engine = class(engine, 'hmm_2TBN_inf_engine', inf_engine(bnet)); + diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_family.m new file mode 100644 index 00000000..cd8a6997 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_family.m @@ -0,0 +1,35 @@ +function marginal = marginal_family(engine, b, i, t, add_ev) +% MARGINAL_FAMILY Compute the marginal on the specified family (hmm_2TBN) +% marginal = marginal_family(engine, b, i, t, add_ev) + +ns = engine.eff_node_sizes(:); +ss = engine.slice_size; + +if t==1 % | ~engine.persist_bitv(i) + bigT = b.gamma; + ps = engine.parents{i}; + dom = [ps i]; + %id = engine.marg_fam1_ndx_id(i); + bigdom = 1:ss; + bigsz = ns(bigdom); + bigdom = bigdom + (t-1)*ss; +else % some parents are in previous slice + bigT = b.xi; % (t-1,t) + ps = engine.parents{i+ss}; + dom = [ps i+ss] + (t-2)*ss; + %id = engine.marg_fam2_ndx_id(i); + bigdom = 1:(2*ss); % domain of xi(:,:,t) + bigsz = ns(bigdom); + bigdom = bigdom + (t-2)*ss; +end +marginal.domain = dom; + +%ndx = get_ndx(id, engine.ndx_type); +%marginal.T = marg_table_ndx(bigT, engine.maximize, ndx, engine.ndx_type); +%global SD_NDX +%ndx = SD_NDX{id}; +%marginal.T = marg_table_ndxSD(bigT, engine.maximize, ndx); +marginal.T = marg_table(bigT, bigdom, bigsz, dom, engine.maximize); + +assert(~add_ev); + diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..6fa6c2b3 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_nodes.m @@ -0,0 +1,27 @@ +function marginal = marginal_nodes(engine, b, nodes, t, add_ev) +% MARGINAL_NODES Compute the marginal on the specified nodes (hmm_2TBN) +% marginal = marginal_nodes(engine, b, nodes, t, add_ev) +% +% nodes must be a singleton set + +assert(length(nodes)==1) +ss = engine.slice_size; + +i = nodes(1); +bigT = b.gamma; +dom = i + (t-1)*ss; + +%id = engine.marg_singleton_ndx_id(i); +%global SD_NDX +%ndx = SD_NDX{id}; +%marginal.T = marg_table_ndxSD(bigT, engine.maximize, ndx); + +ns = engine.eff_node_sizes(:); +bigdom = 1:ss; +marginal.T = marg_table(bigT, bigdom + (t-1)*ss, ns(bigdom), dom, engine.maximize); + +marginal.domain = dom; +assert(~add_ev); +%if add_ev +% marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes); +%end diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Entries new file mode 100644 index 00000000..c37a30a9 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Entries @@ -0,0 +1,2 @@ +/mk_hmm_obs_lik_vec.m/1.1.1.1/Sun May 4 21:47:44 2003// +D diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Repository new file mode 100644 index 00000000..81419e91 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Root b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/mk_hmm_obs_lik_vec.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/mk_hmm_obs_lik_vec.m new file mode 100644 index 00000000..915a2f39 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/private/mk_hmm_obs_lik_vec.m @@ -0,0 +1,53 @@ +function obslik = mk_hmm_obs_lik_vec(engine, evidence) + +% P(o1,o2| h) = P(o1|h) * P(o2|h) where h = Q1,Q2,... + +bnet = bnet_from_engine(engine); +ss = length(bnet.intra); +onodes = bnet.observed; +hnodes = mysetdiff(1:ss, onodes); +ns = bnet.node_sizes(:); +ns(onodes) = 1; + +Q = length(engine.startprob); +obslik = ones(Q, 1); + +for i=1:length(onodes) + o = onodes(i); + %data = cell2num(evidence(o,1)); + data = evidence{o,1}; + if myismember(o, bnet.dnodes) + %obslik_i = eval_pdf_cond_multinomial(data, engine.obsprob{i}.CPT); + obslik_i = multinomial_prob(data, engine.obsprob{i}.CPT); + else + if bnet.auto_regressive(o) + error('can''t handle AR nodes') + end + %% calling mk_ghmm_obs_lik, which calls gaussian_prob, is slow, so we inline it + %% and use the pre-computed inverse matrix + %obslik_i = mk_ghmm_obs_lik(data, engine.obsprob{i}.mu, engine.obsprob{i}.Sigma); + x = data(:); + m = engine.obsprob{i}.mu; + Qi = size(m, 2); + obslik_i = size(Qi, 1); + invC = engine.obsprob{i}.inv_Sigma; + denom = engine.obsprob{i}.denom; + for j=1:Qi + numer = exp(-0.5 * (x-m(:,j))' * invC(:,:,j) * (x-m(:,j))); + obslik_i(j) = numer / denom(j); + end + end + % convert P(o|ps) into P(o|h) by multiplying onto a (h,o) potential of all 1s + ps = bnet.parents{o}; + dom = [ps o]; + obspot_i = dpot(dom, ns(dom), obslik_i); + dom = [hnodes o]; + obspot = dpot(dom, ns(dom)); + obspot = multiply_by_pot(obspot, obspot_i); + % compute p(oi|h) * p(oj|h) + S = struct(obspot); + obslik = obslik .* S.T(:); +end + + + diff --git a/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/update_engine.m b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/update_engine.m new file mode 100644 index 00000000..e6cd1f79 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/online/@hmm_2TBN_inf_engine/update_engine.m @@ -0,0 +1,8 @@ +function engine = update_engine(engine, newCPDs) +% UPDATE_ENGINE Update the engine to take into account the new parameters (hmm) +% engine = update_engine(engine, newCPDs) + +%engine.inf_engine.bnet.CPD = newCPDs; +engine.inf_engine = update_engine(engine.inf_engine, newCPDs); +[engine.startprob, engine.transprob, engine.obsprob] = dbn_to_hmm(bnet_from_engine(engine)); + |
