about summary refs log tree commit diff
path: root/sourcecodes/bnt-master/BNT/examples/dynamic/HHMM/Square/Old/mk_square_hhmm.m
blob: 608b6784b7951627a3091b7ae98ffce533fdf6bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
function bnet = mk_square_hhmm(discrete_obs, true_params, topright)

% Make a 3 level  HHMM described by the following grammar
%
% Square -> CLK | CCK % clockwise or counterclockwise
% CLK -> LR UD RL DU start on top left (1 2 3 4)
% CCK -> RL UD LR DU  if start at top right (3 2 1 4)
% CCK -> UD LR DU RL if start at top left (2 1 4 3)
%
% LR = left-right, UD = up-down, RL = right-left, DU = down-up
% LR, UD, RL, DU are sub HMMs.
%
% For discrete observations, the subHMMs are 2-state left-right.
% LR emits L then l, etc.
%
% For cts observations, the subHMMs are 1 state.
% LR emits a vector in the -> direction, with a little noise.
% Since there is no constraint that we remain in the LR state as long as the RL state,
% the sides of the square might have different lengths,
% so the result is not really a square!
%
% If true_params = 0, we use random parameters at the top 2 levels
% (ready for learning). At the bottom level, we use noisy versions
% of the "true" observations.
%
% If topright=1, counter-clockwise starts at top right, not top left
% This example was inspired by Ivanov and Bobick.

if nargin < 3, topright = 1; end

if 1 % discrete_obs
  Qsizes = [2 4 2];
else
  Qsizes = [2 4 1];
end

D = 3;
Qnodes = 1:D;
startprob = cell(1,D);
transprob = cell(1,D);
termprob = cell(1,D);

% LEVEL 1

startprob{1} = 'unif';
transprob{1} = 'unif';

% LEVEL 2

if true_params
  startprob{2} = zeros(2, 4);
  startprob{2}(1, :) = [1 0 0 0];
  if topright
    startprob{2}(2, :) = [0 0 1 0];
  else
    startprob{2}(2, :) = [0 1 0 0];
  end
  
  transprob{2} = zeros(4, 2, 4);
  
  transprob{2}(:,1,:) = [0 1 0 0
		    0 0 1 0
		    0 0 0 1
		    0 0 0 1]; % 4->e
  if topright
    transprob{2}(:,2,:) = [0 0 0 1
		    1 0 0 0
		    0 1 0 0
		    0 0 0 1]; % 4->e
  else
    transprob{2}(:,2,:) = [0 0 0 1
		    1 0 0 0
		    0 0 1 0 % 3->e
		    0 0 1 0];
  end
  
  %termprob{2} = 'rightstop';
  termprob{2} = zeros(2,4,2);
  pfin = 0.8;
  termprob{2}(1,:,2) = [0 0 0 pfin]; % finish in state 4 (DU)
  termprob{2}(1,:,1) = 1 - [0 0 0 pfin];
  if topright
    termprob{2}(2,:,2) = [0 0 0 pfin];
    termprob{2}(2,:,1) = 1 - [0 0 0 pfin];
  else
    termprob{2}(2,:,2) = [0 0 pfin 0];  % finish in state 3 (RL)
    termprob{2}(2,:,1) = 1 - [0 0 pfin 0];
  end
else
  % In the unsupervised case, it is essential that we break symmetry
  % in the initial param estimates.
  %startprob{2} = 'unif';
  %transprob{2} = 'unif';
  %termprob{2} = 'unif';
  startprob{2} = 'rnd';
  transprob{2} = 'rnd';
  termprob{2} = 'rnd';
end

% LEVEL 3

if 1 |  true_params
  startprob{3} = 'leftstart';
  transprob{3}  = 'leftright';
  termprob{3} = 'rightstop';
else
  % If we want to be able to run a base-level model backwards...
  startprob{3} = 'rnd';
  transprob{3}  = 'rnd';
  termprob{3} = 'rnd';
end
 

% OBS LEVEl

if discrete_obs
  % Initialise observations of lowest level primitives in a way which we can interpret
  chars = ['L', 'l', 'U', 'u', 'R', 'r', 'D', 'd'];
  L=find(chars=='L'); l=find(chars=='l');
  U=find(chars=='U'); u=find(chars=='u');
  R=find(chars=='R'); r=find(chars=='r');
  D=find(chars=='D'); d=find(chars=='d');
  Osize = length(chars);
  
  if true_params
    p = 1; % makes each state fully observed
  else
    p = 0.9;
  end
  
  obsprob = (1-p)*ones([4 2 Osize]);
  %       Q2 Q3 O
  obsprob(1, 1, L) =  p;
  obsprob(1, 2, l) =  p;
  obsprob(2, 1, U) =  p;
  obsprob(2, 2, u) =  p;
  obsprob(3, 1, R) =  p;
  obsprob(3, 2, r) =  p;
  obsprob(4, 1, D) =  p;
  obsprob(4, 2, d) =  p;
  obsprob = mk_stochastic(obsprob);
  Oargs = {'CPT', obsprob};
else
  % Initialise means of lowest level primitives in a way which we can interpret
  % These means are little vectors in the east, south, west, north directions.
  % (left-right=east, up-down=south, right-left=west, down-up=north)
  Osize = 2;
  mu = zeros(2, Qsizes(2), Qsizes(3));
  scale = 3;
  if true_params
    noise = 0;
  else
    noise = 0.5*scale;
  end
  for q3=1:Qsizes(3)
    mu(:, 1, q3) = scale*[1;0] + noise*rand(2,1);
  end
  for q3=1:Qsizes(3)
    mu(:, 2, q3) = scale*[0;-1] + noise*rand(2,1);
  end
  for q3=1:Qsizes(3)
    mu(:, 3, q3) = scale*[-1;0] + noise*rand(2,1);
  end
  for q3=1:Qsizes(3)
    mu(:, 4, q3) = scale*[0;1] + noise*rand(2,1);
  end
  Sigma = repmat(reshape(scale*eye(2), [2 2 1 1 ]), [1 1 Qsizes(2) Qsizes(3)]);
  Oargs = {'mean', mu, 'cov', Sigma, 'cov_type', 'diag'};
end

if discrete_obs
  selfprob = 0.5;
else
  selfprob = 0.95;
  % If less than this, it won't look like a square
  % because it doesn't spend enough time in each state
  % Unfortunately, the variance on durations (lengths of each side)
  % is very large
end
bnet = mk_hhmm('Qsizes', Qsizes, 'Osize', Osize', 'discrete_obs', discrete_obs, ...
	       'Oargs', Oargs, 'Ops', Qnodes(2:3), 'selfprob', selfprob, ...
	       'startprob', startprob, 'transprob', transprob, 'termprob', termprob);