To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Revision:

root / _FullBNT / BNT / CPDs / @hhmmQ_CPD / hhmmQ_CPD.m @ 8:b5b38998ef3b

History | View | Annotate | Download (4.38 KB)

1
function CPD = hhmmQ_CPD(bnet, self, varargin)
2
% HHMMQ_CPD Make the CPD for a Q node in a hierarchical HMM
3
% CPD = hhmmQ_CPD(bnet, self, ...)
4
%
5
%  Fself(t-1)   Qps(t)
6
%           \    |
7
%            \   v
8
%  Qold(t-1) ->  Q(t)
9
%            /
10
%           /
11
%  Fbelow(t-1) 
12
%
13
% Let ss = slice size = num. nodes per slice.
14
% This node is Q(t), and has mandatory parents Qold(t-1) (assumed to be numbered Q(t)-ss)
15
% and optional parents Fbelow, Fself, Qps.
16
% We require parents to be ordered (numbered) as follows:
17
% Qold, Fbelow, Fself, Qps, Q.
18
%
19
% If Fself=2, we use the transition matrix, else we use the prior matrix.
20
% If Fself node is omitted (eg. top level), we always use the transition matrix.
21
% If Fbelow=2, we may change state, otherwise we must stay in the same state.
22
% If Fbelow node is omitted (eg., bottom level), we may change state at every step.
23
% If Qps (Q parents) are specified, all parameters are conditioned on their joint value.
24
% We may choose any subset of nodes to condition on, as long as they as numbered lower than self.
25
%
26
% optional args [defaults]
27
%
28
% Fself - node number <= ss
29
% Fbelow  - node number  <= ss
30
% Qps - node numbers (all <= 2*ss) - uses 2TBN indexing
31
% transprob - transprob(i,k,j) = prob transition from i to j given Qps = k ['leftright']
32
% selfprob  - prob of a transition from i to i given Qps=k [0.1]
33
% startprob - startprob(k,j) = prob start in j given Qps = k ['leftstart']
34
% startargs - other args to be passed to the sub tabular_CPD for learning startprob
35
% transargs - other args will be passed to the sub tabular_CPD for learning transprob
36
% fullstartprob - 1 means startprob depends on Q(t-1) [0]
37
% hhmmQ_CPD is a subclass of tabular_CPD so we inherit inference methods like CPD_to_pot, etc.
38
%
39
% We create isolated tabular_CPDs with no F parents to learn transprob/startprob
40
% so we can avail of e.g., entropic or Dirichlet priors.
41
% In the future, we will be able to represent the transprob using a tree_CPD.
42
%
43
% For details, see "Linear-time inference in hierarchical HMMs", Murphy and Paskin, NIPS'01.
44

    
45

    
46
ss = bnet.nnodes_per_slice;
47
ns = bnet.node_sizes(:);
48

    
49
% set default arguments
50
Fself = [];
51
Fbelow = [];
52
Qps = [];
53
startprob = 'leftstart';
54
transprob = 'leftright';
55
startargs = {};
56
transargs = {};
57
selfprob = 0.1;
58
fullstartprob = 0;
59

    
60
for i=1:2:length(varargin)
61
  switch varargin{i},
62
   case 'Fself', Fself = varargin{i+1};
63
   case 'Fbelow', Fbelow = varargin{i+1};
64
   case 'Qps', Qps = varargin{i+1};
65
   case 'transprob', transprob = varargin{i+1}; 
66
   case 'selfprob',  selfprob = varargin{i+1}; 
67
   case 'startprob', startprob = varargin{i+1}; 
68
   case 'startargs', startargs = varargin{i+1}; 
69
   case 'transargs', transargs = varargin{i+1}; 
70
   case 'fullstartprob', fullstartprob = varargin{i+1}; 
71
  end
72
end
73

    
74
CPD.fullstartprob = fullstartprob;
75

    
76
ps = parents(bnet.dag, self);
77
ndsz = ns(:)';
78
CPD.dom_sz = [ndsz(ps) ns(self)];
79
CPD.Fself_ndx = find_equiv_posns(Fself, ps);
80
CPD.Fbelow_ndx = find_equiv_posns(Fbelow, ps);
81
%CPD.Qps_ndx = find_equiv_posns(Qps+ss, ps);
82
CPD.Qps_ndx = find_equiv_posns(Qps, ps);
83
old_self = self-ss;
84
CPD.old_self_ndx = find_equiv_posns(old_self, ps);
85

    
86
Qps = ps(CPD.Qps_ndx);
87
CPD.Qsz = ns(self);
88
CPD.Qpsz = prod(ns(Qps));
89
CPD.Qpsizes = ns(Qps);
90
Qsz = CPD.Qsz;
91
Qpsz = CPD.Qpsz;
92

    
93
if strcmp(transprob, 'leftright')
94
  LR = mk_leftright_transmat(Qsz, selfprob);
95
  transprob = repmat(reshape(LR, [1 Qsz Qsz]), [Qpsz 1 1]); % transprob(k,i,j)
96
  transprob = permute(transprob, [2 1 3]); % now transprob(i,k,j)
97
end
98
transargs{end+1} = 'CPT';
99
transargs{end+1} = transprob;
100
CPD.sub_CPD_trans = mk_isolated_tabular_CPD(ns([old_self Qps self]), transargs);
101
S = struct(CPD.sub_CPD_trans);
102
%CPD.transprob = myreshape(S.CPT, [Qsz Qpsz Qsz]);
103
CPD.transprob = S.CPT;
104

    
105

    
106
if strcmp(startprob, 'leftstart')
107
  startprob = zeros(Qpsz, Qsz);
108
  startprob(:,1) = 1;
109
end
110
if isempty(CPD.Fself_ndx)
111
  CPD.sub_CPD_start = [];
112
  CPD.startprob = [];
113
else
114
  startargs{end+1} = 'CPT';
115
  startargs{end+1} = startprob;
116
  if CPD.fullstartprob
117
    CPD.sub_CPD_start = mk_isolated_tabular_CPD(ns([self Qps self]), startargs);
118
    S = struct(CPD.sub_CPD_start);
119
    %CPD.startprob = myreshape(S.CPT, [Qsz Qpsz Qsz]);
120
    CPD.startprob = S.CPT;
121
  else
122
    CPD.sub_CPD_start = mk_isolated_tabular_CPD(ns([Qps self]), startargs);
123
    S = struct(CPD.sub_CPD_start);
124
    %CPD.startprob = myreshape(S.CPT, [CPD.Qpsizes Qsz]);
125
    CPD.startprob = S.CPT;
126
  end
127
end
128

    
129
CPD = class(CPD, 'hhmmQ_CPD', tabular_CPD(bnet, self));
130

    
131
CPD = update_CPT(CPD);
132