wolffd@0: % make a factor graph corresponding to an HMM, where we absorb the evidence up front, wolffd@0: % and then eliminate the observed nodes. wolffd@0: % Compare this with not absorbing the evidence. wolffd@0: wolffd@0: seed = 1; wolffd@0: rand('state', seed); wolffd@0: randn('state', seed); wolffd@0: wolffd@0: T = 3; wolffd@0: Q = 3; wolffd@0: O = 2; wolffd@0: cts_obs = 0; wolffd@0: param_tying = 1; wolffd@0: bnet = mk_hmm_bnet(T, Q, O, cts_obs, param_tying); wolffd@0: N = 2*T; wolffd@0: onodes = bnet.observed; wolffd@0: hnodes = mysetdiff(1:N, onodes); wolffd@0: wolffd@0: data = sample_bnet(bnet); wolffd@0: wolffd@0: init_factor = bnet.CPD{1}; wolffd@0: obs_factor = bnet.CPD{3}; wolffd@0: edge_factor = bnet.CPD{2}; % trans matrix wolffd@0: wolffd@0: nfactors = T; wolffd@0: nvars = T; % hidden only wolffd@0: G = zeros(nvars, nfactors); wolffd@0: G(1,1) = 1; wolffd@0: for t=1:T-1 wolffd@0: G(t:t+1, t+1)=1; wolffd@0: end wolffd@0: wolffd@0: node_sizes = Q*ones(1,T); wolffd@0: wolffd@0: % We tie params as follows: wolffd@0: % the first hidden node use init_factor (number 1) wolffd@0: % all hidden nodes on the backbone use edge_factor (number 2) wolffd@0: % all observed nodes use the same factor, namely obs_factor wolffd@0: wolffd@0: small_fg = mk_fgraph_given_ev(G, node_sizes, {init_factor, edge_factor}, {obs_factor}, data(onodes), ... wolffd@0: 'equiv_class', [1 2*ones(1,T-1)], 'ev_equiv_class', ones(1,T)); wolffd@0: wolffd@0: small_bnet = fgraph_to_bnet(small_fg); wolffd@0: wolffd@0: % don't pre-process evidence wolffd@0: big_fg = bnet_to_fgraph(bnet); wolffd@0: big_bnet = fgraph_to_bnet(big_fg); wolffd@0: wolffd@0: wolffd@0: wolffd@0: engine = {}; wolffd@0: engine{1} = jtree_inf_engine(bnet); wolffd@0: engine{2} = belprop_fg_inf_engine(small_fg, 'max_iter', 2*T); wolffd@0: engine{3} = jtree_inf_engine(small_bnet); wolffd@0: engine{4} = belprop_fg_inf_engine(big_fg, 'max_iter', 3*T); wolffd@0: engine{5} = jtree_inf_engine(big_bnet); wolffd@0: nengines = length(engine); wolffd@0: wolffd@0: wolffd@0: % on BN, use the original evidence wolffd@0: evidence = cell(1, 2*T); wolffd@0: evidence(onodes) = data(onodes); wolffd@0: tic; [engine{1}, ll(1)] = enter_evidence(engine{1}, evidence); toc wolffd@0: wolffd@0: wolffd@0: % on small_fg, we have already included the evidence wolffd@0: evidence = cell(1,T); wolffd@0: tic; [engine{2}, ll(2)] = enter_evidence(engine{2}, evidence); toc wolffd@0: wolffd@0: wolffd@0: % on small_bnet, we must add evidence to the dummy nodes wolffd@0: V = small_fg.nvars; wolffd@0: dummy = V+1:V+small_fg.nfactors; wolffd@0: N = max(dummy); wolffd@0: evidence = cell(1, N); wolffd@0: evidence(dummy) = {1}; wolffd@0: tic; [engine{3}, ll(3)] = enter_evidence(engine{3}, evidence); toc wolffd@0: wolffd@0: wolffd@0: % on big_fg, use the original evidence wolffd@0: evidence = cell(1, 2*T); wolffd@0: evidence(onodes) = data(onodes); wolffd@0: tic; [engine{4}, ll(4)] = enter_evidence(engine{4}, evidence); toc wolffd@0: wolffd@0: wolffd@0: % on big_bnet, we must add evidence to the dummy nodes wolffd@0: V = big_fg.nvars; wolffd@0: assert(V == 2*T); wolffd@0: dummy = V+1:V+big_fg.nfactors; wolffd@0: N = max(dummy); wolffd@0: evidence = cell(1, N); wolffd@0: evidence(onodes) = data(onodes); wolffd@0: evidence(dummy) = {1}; wolffd@0: tic; [engine{5}, ll(5)] = enter_evidence(engine{5}, evidence); toc wolffd@0: wolffd@0: wolffd@0: marg = zeros(T, nengines, Q); % marg(t,e,:) wolffd@0: for t=1:T wolffd@0: for e=1:nengines wolffd@0: m = marginal_nodes(engine{e}, t); wolffd@0: marg(t,e,:) = m.T; wolffd@0: end wolffd@0: end wolffd@0: marg(:,:,1)