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/online/@hmm_2TBN_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/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)); + |
