Repository navigation
Expand file tree
/
Copy pathswitch_obs.m
More file actions
292 lines (226 loc) · 10.6 KB
/
Copy pathswitch_obs.m
File metadata and controls
292 lines (226 loc) · 10.6 KB
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
function [Mf,Ms,Sf,Ss,xf,xs,outpars,LL] = ...
switch_obs(y,M,p,r,pars,control,equal,fixed,scale)
%--------------------------------------------------------------------------
% Title: Parameter estimation and inference in state-space models with regime switching
% (switching observations model)
%
% Function: Infer hidden state vectors and regmes by switching Kalman filtering/smoothing
% (aka Hamilton filtering or Kim filtering) and estimate model parameters by
% maximum likelihood (EM algorithm).
%
% Usage: [Mf,Ms,Sf,Ss,xf,xs,outpars,LL] = ...
% switch_obs(y,M,p,pars,control,equal,fixed,scale)
%
% Inputs: y - Time series (size NxT)
% M - number of regimes
% p - order of VAR model for state vector
% pars - optional 'struct' of EM starting values
% A - Initial estimates of VAR matrices A(l,j) in system equation
% x(t,j) = sum(l=1:p) A(l,j) x(t-l,j) + v(t,j), j=1:M (size rxrxpxM)
% C - Initial estimates of observation matrices C(j) in equation
% y(t) = C(j) x(t,j) + w(t), j=1:M (size NxrxM)
% Q - Initial estimates of state noise covariance Cov(v(t,j)) (size rxrxM)
% R - Pilot estimate of observation noise covariance Cov(w(t)) (size NxN)
% mu - Pilot estimate of mean state mu(j)=E(x(t,j)) for t=1:p (size rxM)
% Sigma - Pilot estimate of covariance Sigma(j)=Cov(x(t,j)) for t=1:p (size rxrxM)
% Pi - Initial state probability (size Mx1)
% Z - Pilot Markov transition probability matrix (size MxM)
% control - optional struct variable with fields:
% 'eps': tolerance for EM termination; defaults to 1e-8
% 'ItrNo': number of EM iterations; dfaults to 100
% 'beta0': initial inverse temperature parameter for deterministic annealing; default 1
% 'betarate': decay rate for temperature; default 1
% 'safe': if true, regularizes variance matrices to be well-conditioned
% before taking inverse. If false, no regularization (faster but less safe)
% 'abstol': absolute tolerance for eigenvalues in matrix inversion (only effective if safe = true)
% 'reltol': relative tolerance for eigenvalues in matrix inversion
% = inverse condition number (only effective if safe = true)
% equal - optional struct variable with fields:
% 'A': if true, VAR transition matrices A(l,j) are equal across regimes j=1,...,M
% 'C': if true, observation matrices C(j) are equal across regimes
% 'Q': if true, VAR innovation matrices Q(j) are equal across regimes
% 'mu': if true, initial mean state vectors mu(j) are equal across regimes
% 'Sigma': if true, initial variance matrices Sigma(j) are equal across regimes
% fixed - optional struct variable with fields 'A','C','Q','R','mu','Sigma'.
% If not empty, each field must contain a matrix with 2 columns, the first for
% the location of fixed coefficients and the second for their values.
% scale - optional struct variable with fields:
% 'A': upper bound for norm of eigenvalues of A matrices. Must be in (0,1).
% 'C': value of the (euclidean) column norms of the matrices C(j). Must be positive.
%
% Outputs: Mf - State probability estimated by switching Kalman Filter (size MxT)
% Ms - State probability estimated by switching Kalman Smoother (size MxT)
% Sf - Estimated states (Kalman Filter)
% Ss - Estimated states (Kalman Smoother)
% xf - Filtered state vector (size rxT)
% xs - Smoothed state vector (size MxT)
% outpars - 'struct'
% A - Estimated system matrix (size rxrxpxM)
% C - Estimated observation matrix (size Nxr)
% Q - Estimated state noise covariance (size rxrxM)
% R - Estimated observation noise covariance (size NxN)
% mu - Estimated initial mean of state vector (size rxM)
% Sigma - Estimated initial variance of state vector (size rxrxM)
% LL - Sequence of log-likelihood values
%
% Author: David Degras, david.degras@umb.edu
% University of Massachusetts Boston
%
% Contributors: Ting Chee Ming, cmting@utm.my
% Siti Balqis Samdin
% Centre for Biomedical Engineering, Universiti Teknologi Malaysia.
%
% Version: January 8, 2021
%--------------------------------------------------------------------------
%-------------------------------------------------------------------------%
% Initialization %
%-------------------------------------------------------------------------%
narginchk(4,9);
% Data dimensions
[N,T] = size(y);
% Center data
y = y - mean(y,2);
% x(t,j): state vector for j-th process at time t (size r)
% x(t) = x(t,1),...,x(t,M): state vector for all processes at time t (size M*r)
% X(t,j) = x(t,j),...,x(t-p+1,j)): state vector for process j at times t,...,t-p+1 (size p*r)
% X(t) = X(t,1),...,X(t,M): state vector for all processes at times t,...,t-p+1 (size M*p*r)
% Assumption: initial vectors x(1),...,x(1-p+1) are iid ~ N(mu,Sigma)
%@@@@@ Initialize optional arguments if not specified
if ~exist('fixed','var')
fixed = struct();
end
if ~exist('equal','var')
equal = struct();
end
if ~exist('control','var')
control = struct();
end
if ~exist('scale','var')
scale = struct();
end
% Trivial case M = 1
if M == 1
if ~exist('pars','var')
pars = [];
end
S = ones(1,T); Mf = S; Ms = S; Sf = S; Ss = S;
[xf,xs,outpars,LL] = fast_obs(y,M,p,r,S,pars,control,equal,fixed,scale);
return
end
%@@@@ Initialize estimators @@@@%
pars0 = struct('A',[], 'C',[], 'Q',[], 'R',[], 'mu',[], 'Sigma',[], ...
'Pi',[], 'Z',[]);
if exist('pars','var') && isstruct(pars)
fname = fieldnames(pars0);
for i = 1:8
name = fname{i};
if isfield(pars,name)
pars0.(name) = pars.(name);
end
end
end
if any(structfun(@isempty,pars0))
pars = init_obs(y,M,p,r,pars0,control,equal,pars0,scale);
end
[pars,control,equal,fixed,scale,skip] = ...
preproc_obs(M,N,p,r,pars,control,equal,fixed,scale);
abstol = control.abstol;
reltol = control.reltol;
betarate = control.betarate;
eps = control.eps;
ItrNo = control.ItrNo;
verbose = control.verbose;
safe = control.safe;
% Initial parameters 'A','C',... are expanded from r-space (x(t)) to
% (p*r)-space (X(t)). The new parameters 'Ahat','Chat',... have dimensions:
% Ahat: (p*r)x(p*r)xM, Chat: Nx(p*r)xM, Qhat: (p*r)x(p*r)xM, Rhat: NxN,
% muhat: (p*r)xM, Sigmahat: (p*r)x(p*r)xM. These parameters respect the
% fixed coefficients and equality constraints (either default values or
% user-specified ones).
% The structure 'fixed' has fields 'fixed.A',... (one field per model
% parameter). Each field is a matrix with two columns containing the
% locations and values of fixed coefficients in the corresponding
% parameter.
% The structure 'equal' has fields 'equal.A',... representing equality
% constraints on parameters across regimes j=1,...,M. By default, equality
% constraints are: A: false, C: false, Q: false, (R: not applicable), mu:
% true, Sigma: true. In other words, only the initial parameters mu and
% Sigma are assumed to be common across regimes. If provided, user values
% will override default values.
% Various control parameters ('eps','ItrNo',...) are set either to their
% default values or to user-specified values through argument 'control'.
%@@@@@ Initialize other quantities @@@@@%
LL = zeros(1,ItrNo); % Log-likelihood
LLbest = -Inf; % best attained log-likelihood
LLflag = 0; % counter for monitoring progress of log-likelihood
sum_yy = y * y.'; % sum(t=1:T) y(t)*y(t)'
beta = control.beta0; % initial temperature for deterministic annealing
% Function for switching Kalman filtering and smoothing
if p == 1
skfs_fun = @skfs_p1_obs;
else
skfs_fun = @skfs_obs;
end
for i=1:ItrNo
%-------------------------------------------------------------------------%
% E-step %
%-------------------------------------------------------------------------%
% Kim/Hamilton filtering and smoothing
[Mf,Ms,xf,xs,x0,P0,L,sum_CP,sum_MP,sum_Ms2,sum_Mxy,sum_P,sum_Pb] = ...
skfs_fun(y,M,p,pars,beta,safe,abstol,reltol);
% Log-likelihood
LL(i) = L;
if verbose
fprintf('Iteration-%d Log-likelihood = %g\n',i,LL(i));
Qval = Q_obs(pars,Ms,P0,sum_CP,sum_MP,sum_Ms2,sum_Mxy,sum_P,...
sum_Pb,sum_yy,x0);
fprintf('Q-function before M-step = %g\n',Qval);
end
% Check if current solution is best to date
if i == 1 || LL(i) > LLbest
LLbest = LL(i);
outpars = pars;
Mfbest = Mf;
Msbest = Ms;
xfbest = xf;
xsbest = xs;
end
% Monitor progress of log-likelihood
if i>1 && LL(i)-LL(i-1) < eps * abs(LL(i-1))
LLflag = LLflag + 1;
else
LLflag = 0;
end
% Terminate EM algorithm if no sufficient reduction in log-likelihood
% for 10 successive iterations
if LLflag == 5
break;
end
% Update inverse temperature parameter (DAEM)
beta = min(beta * betarate, 1);
%-------------------------------------------------------------------------%
% M-step %
%-------------------------------------------------------------------------%
pars = M_obs(pars,Ms,P0,sum_CP,sum_MP,sum_Ms2,sum_Mxy,sum_P,...
sum_Pb,sum_yy,x0,control,equal,fixed,scale,skip);
% Evaluate and display Q-function value if required
if verbose
Qval = Q_obs(pars,Ms,P0,sum_CP,sum_MP,sum_Ms2,sum_Mxy,sum_P,...
sum_Pb,sum_yy,x0);
fprintf('Q-function after M-step = %g\n',Qval);
end
end % END MAIN LOOP
%-------------------------------------------------------------------------%
% Output %
%-------------------------------------------------------------------------%
% Return best estimates (i.e. with highest log-likelihood)
% after reshaping them to original size
outpars.A = reshape(outpars.A,r,r,p,M);
Mf = Mfbest;
Ms = Msbest;
[~,Sf] = max(Mf);
[~,Ss] = max(Ms);
xf = xfbest;
xs = xsbest;
LL = LL(1:i);
end