DLM demo no 1
Generate synthetic and ideal data and fit a DLM smoother. The command dlmgensys generates system evolution matrix G and obs operator F. We use local level and trend model with 12 seasons.
[G,F] = dlmgensys(struct('order',1,'fullseas',1,'ns',12)); % p = number of data sets = 1, % m = number of internal states = 13 [p,m] = size(F);
Generate data.
t = (1:1:(6*12))'; % time n = length(t); s = 0.1; % obs error std V = ones(n,p)*s; % V is matrix of std's x0 = [0;0.001;sin((1:11)/12*pi*2)']; % initial state C0 = 0.02*eye(m)*s^2; % initial state uncertainty W = zeros(m); % "model error" W(1,1) = 0.000002^2; W(2,2) = 0.002.^2; W(3,3) = 0.02.^2;
Observations are generated using the state space recursion.
y = zeros(n,1); x = x0; for i=1:n y(i) = F*x + randn(1,1)*s; x = G*x + randn(m,1).*sqrt(diag(W)); end
Function dlmsmo calculates the estimated states using Kalman smoother.
out = dlmsmo(y,F,V,x0,G,W,C0);
x0 = out.x(:,1); % save smoothed estimate of x0
Plot observations and the fitted level with 95% (time wise) confidence bands.
figure(1); clf plot(t,out.yhat,'*') hold on confband(t,out.x(1,:)',out.xstd(:,1)); errorbar(t,y,2*V,'ok-') hold off
figure(2); clf
confband(t,out.x(2,:)',out.xstd(:,2)); grid; title('Trend')
MCMC
Gibbs sampling for the variance parameters using conjugate prior distributions. This takes some time.
nsimu = 1000; chain = zeros(nsimu,4); W0 = W; % prior W n0 = 5; % prior weight V0 = s; nv0 = 10; doplot = 1; plotint = 100;
hw = waitbar(0,'MCMC running, please wait'); for isimu = 1:nsimu waitbar(isimu/nsimu,hw); % Gibbs step for variance parameters % residual std for V, conjugate distribution is inverse chi squared sigV = sqrt(invchir(1,1,n+nv0,(out.ssy+V0.^2*nv0)/(n+nv0))); V = ones(n,p)*sigV; out = dlmsmo(y,F,V,x0,G,W,C0); % recalculate with new V % variances in diag(W) c = zeros(1,3); % fit 3 first variances for i=1:3 c(i) = invchir(1,1,n+n0-1,(W0(i,i).*n0+out.ss(i))./(n+n0-1)); W(i,i) = c(i); out = dlmsmo(y,F,V,x0,G,W,C0); % recalculate smoother end chain(isimu,:) = [sigV,sqrt(c(1:3))]; if doplot & (isimu/plotint == fix(isimu/plotint)) % plot every plotint'th MCMC sampled state figure(1); hold on plot(t,out.xr(1,:),'-r') hold off end end close(hw);
figure(3); clf mcmcplot(chain,[],{'V','W1','W2','W3'}); hold on subplot(2,2,1); h=hline(s);set(h,'linestyle','-','linewidth',2) subplot(2,2,2); h=hline(sqrt(W0(1,1)));set(h,'linestyle','-','linewidth',2) subplot(2,2,3); h=hline(sqrt(W0(2,2)));set(h,'linestyle','-','linewidth',2) subplot(2,2,4); h=hline(sqrt(W0(3,3)));set(h,'linestyle','-','linewidth',2) hold off V = ones(n,p)*sqrt(mean(chain(:,1).^2)); for i=1:3; W(i,i) = mean(chain(:,i+1).^2); end out = dlmsmo(y,F,V,x0,G,W,C0);
Add estimated over the initial trend.
figure(2); ind = 2; % xxx = out.x(ind,:)'; hold on plot(t,xxx) plot(t,xxx-2*out.xstd(:,ind),'g-') plot(t,xxx+2*out.xstd(:,ind),'g-') hold off