-
Notifications
You must be signed in to change notification settings - Fork 249
/
fixed_lag_smoother.m
65 lines (56 loc) · 2.05 KB
/
fixed_lag_smoother.m
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
function [alpha, obslik, gamma, xi] = fixed_lag_smoother(d, alpha, obslik, obsvec, transmat, act)
% FIXED_LAG_SMOOTHER Computed smoothed posterior estimates within a window given previous filtered window.
% [alpha, obslik, gamma, xi] = fixed_lag_smoother(d, alpha, obslik, obsvec, transmat, act)
%
% d >= 2 is the desired window width.
% Actually, we use d=min(d, t0), where t0 is the current time.
%
% alpha(:, t0-d:t0-1) - length d window, excluding t0 (Columns indexed 1..d)
% obslik(:, t0-d:t0-1) - length d window
% obsvec - likelihood vector for current observation
% transmat - transition matrix
% If we specify the optional 'act' argument, transmat{a} should be a cell array, and
% act(t0-d:t0) - length d window, last column = current action
%
% Output:
% alpha(:, t0-d+1:t0) - last column = new filtered estimate
% obslik(:, t0-d+1:t0) - last column = obsvec
% xi(:, :, t0-d+1:t0-1) - 2 slice smoothed window
% gamma(:, t0-d+1:t0) - smoothed window
%
% As usual, we define (using T=d)
% alpha(i,t) = Pr(Q(t)=i | Y(1:t))
% gamma(i,t) = Pr(Q(t)=i | Y(1:T))
% xi(i,j,t) = Pr(Q(t)=i, Q(t+1)=j | Y(1:T))
%
% obslik(i,t) = Pr(Y(t) | Q(t)=i)
% transmat{a}(i,j) = Pr(Q(t)=j | Q(t-1)=i, A(t)=a)
[S n] = size(alpha);
d = min(d, n+1);
if d < 2
error('must keep a window of length at least 2');
end
if ~exist('act')
act = ones(1, n+1);
transmat = { transmat };
end
% pluck out last d-1 components from the history
alpha = alpha(:, n-d+2:n);
obslik = obslik(:, n-d+2:n);
% Extend window by 1
t = d;
obslik(:,t) = obsvec;
xi = zeros(S, S, d-1);
xi(:,:,t-1) = normalise((alpha(:,t-1) * obslik(:,t)') .* transmat{act(t)});
alpha(:,t) = sum(xi(:,:,t-1), 1)';
% Now smooth backwards inside the window
beta = ones(S, d);
T = d;
%fprintf('smooth from %d to 1, i.e., %d to %d\n', d, t0, t0-d+1);
gamma(:,T) = alpha(:,T);
for t=T-1:-1:1
b = beta(:,t+1) .* obslik(:,t+1);
beta(:,t) = normalise(transmat{act(t)} * b);
gamma(:,t) = normalise(alpha(:,t) .* beta(:,t));
xi(:,:,t) = normalise((transmat{act(t)} .* (alpha(:,t) * b')));
end