Skip to content

Commit 2d7d1d0

Browse files
committed
refactorized MATLAB code. Harmonised code and settings between implemenations.
Former-commit-id: 682f903
1 parent 515771e commit 2d7d1d0

40 files changed

Lines changed: 1303 additions & 1040 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.vscode/
22
.R~
3+
.m~
34

45
# Byte-compiled / optimized / DLL files
56
__pycache__/

matlab/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# MATLAB code for PMH tutorial
2+
3+
This MATLAB code implements the Kalman filter (KF), particle filter (PF) and particle Metropolis-Hastings (PMH) algorithm for two different dynamical models: a linear Gaussian state-space (LGSS) model and a stochastic volatilty (SV) model. Note that the Kalman filter can only be employed for the first of these two models. The details of the code is described in the tutorial paper available at: < http://arxiv.org/pdf/1511.01707 >.
4+
5+
Note that the MATLAB code in this folder covers the basic implementations in the paper. See the R code in r/ for all the implementations and to recreate the results in the tutorial.
6+
7+
Requirements
8+
--------------
9+
The code is written and tested for MATLAB 2016b and makes use of the statistics toolbox and the Quandl package. See < https://github.com/quandl/Matlab > for more installation and to download the toolbox. Note that urlread2 is required by the Quandl toolbox and should be installed as detailed in the README file of the Quandl toolbox.
10+
11+
Main script files
12+
--------------
13+
These are the main script files that implement the various algorithms discussed in the tutorial.
14+
15+
**example1_lgss.m** State estimation in a LGSS model using the KM and a fully-adapted PF (faPF). The code is discussed in Section 3.1 and the results are presented in Section 3.2 as Figure 4 and Table 1.
16+
17+
**example2_lgss.m** Parameter estimation of one parameter in the LGSS model using PMH with the faPF as the likelihood estimator. The code is discussed in Section 4.1 and the results are presented in Section 4.2 as Figure 5.
18+
19+
**example3_sv.m** Parameter estimation of three parameters in the SV model using PMH with the bootstrap PF as the likelihood estimator. The code is discussed in Section 5.1 and the results are presented in Section 5.2 as Figure 6. The code takes about an hour to run.
20+
21+
Supporting files
22+
--------------
23+
**generateData.m** Implements data generation for the LGSS model.
24+
**kalmanFilter.m** Implements the Kalman filter for the LGSS model.
25+
**particleFilter.m** Implements the faPF for the LGSS model.
26+
**particleFilterSVmodel.m** Implements the bPF for the SV model.
27+
**particleMetropolisHastings.m** Implements the PMH algorithm for the LGSS model.
28+
**particleMetropolisHastingsSVmodel.m** Implements the PMH algorithm for the SV model.
29+
30+
Adapting the code for another model
31+
--------------
32+
See the discussion in *README.MD* in the directory *r/*.

matlab/example1_lgss.m

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
22
%
3-
% Example of fully-adapted particle filtering
4-
% in a linear Gaussian state space model
3+
% Example of state estimation in a LGSS model
4+
% using particle filters and Kalman filters
55
%
6-
% Copyright (C) 2015 Johan Dahlin < johan.dahlin (at) liu.se >
6+
% Copyright (C) 2017 Johan Dahlin < liu (at) johandahlin.com.nospam >
77
%
88
% This program is free software; you can redistribute it and/or modify
99
% it under the terms of the GNU General Public License as published by
@@ -21,59 +21,66 @@
2121
%
2222
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2323

24+
% Set random seed
25+
rng(0)
26+
2427
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2528
% Define the model
2629
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2730

2831
% Here, we use the following model
2932
%
30-
% x[tt+1] = phi * x[tt] + sigmav * v[tt]
31-
% y[tt] = x[tt] + sigmae * e[tt]
33+
% x[t + 1] = phi * x[t] + sigmav * v[t]
34+
% y[t] = x[t] + sigmae * e[t]
3235
%
33-
% where v[tt] ~ N(0,1) and e[tt] ~ N(0,1)
36+
% where v[t] ~ N(0, 1) and e[t] ~ N(0, 1)
3437

3538
% Set the parameters of the model
36-
phi = 0.75;
39+
phi = 0.75;
3740
sigmav = 1.00;
3841
sigmae = 0.10;
42+
theta = [phi sigmav sigmae];
3943

4044
% Set the number of time steps to simulate
41-
T = 250;
45+
T = 250;
4246

4347
% Set the initial state
44-
x0 = 0;
48+
initialState = 0;
4549

4650
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4751
% Generate data
4852
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4953

50-
[x,y] = generateData(phi,sigmav,sigmae,T,x0);
54+
[x, y] = generateData(theta, T, initialState);
5155

5256
% Plot the measurements and latent states
53-
subplot(3,1,1); plot(y(2:(T+1)),'LineWidth',1.5,'Color',[27 158 119]/256);
54-
xlabel('time'); ylabel('measurement');
57+
subplot(3,1,1);
58+
plot(y(2:(T + 1)), 'LineWidth', 1.5, 'Color', [27 158 119] / 256);
59+
xlabel('time');
60+
ylabel('measurement');
5561

56-
subplot(3,1,2); plot(x(2:(T+1)),'LineWidth',1.5,'Color',[217 95 2]/256);
57-
xlabel('time'); ylabel('latent state');
62+
subplot(3,1,2);
63+
plot(x(2:(T + 1)), 'LineWidth', 1.5, 'Color', [217 95 2] / 256);
64+
xlabel('time');
65+
ylabel('latent state');
5866

5967
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60-
% State estimation using the particle filter
68+
% State estimation
6169
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6270

6371
% Using N = 20 particles and plot the estimate of the latent state
64-
N = 20;
65-
outPF = sm(y,phi,sigmav,sigmae,N,T,x0);
72+
outPF = particleFilter(y, theta, 20, initialState);
6673

67-
subplot(3,1,3); plot(1:(T-1),outPF(2:T),'LineWidth',1.5,'Color',[117 112 179]/256);
68-
xlabel('time'); ylabel('state estimate');
74+
% Kalman filter
75+
outKF = kalmanFilter(y, theta, initialState, 0.01);
6976

70-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71-
% State estimation using the Kalman filter
72-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77+
% Plot the difference
78+
subplot(3,1,3);
79+
difference = outPF(2:T) - outKF(2:T);
80+
plot(1:(T - 1), difference, 'LineWidth', 1.5, 'Color', [117 112 179] / 256);
81+
xlabel('time');
82+
ylabel('difference in state estimate');
7383

74-
outKF = kf(y,phi,sigmav,sigmae,T,x0,0.01);
75-
hold on;
76-
plot(1:(T-1),outKF(2:T),'k.','LineWidth',1.5);
7784

7885
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7986
% End of file

matlab/example2_lgss.m

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
22
%
3-
% Example of PMH in a LGSS model
3+
% Example of particle Metropolis-Hastings in a LGSS model.
44
%
5-
% Main script
6-
%
7-
% Copyright (C) 2015 Johan Dahlin < johan.dahlin (at) liu.se >
5+
% Copyright (C) 2017 Johan Dahlin < liu (at) johandahlin.com.nospam >
86
%
97
% This program is free software; you can redistribute it and/or modify
108
% it under the terms of the GNU General Public License as published by
@@ -22,86 +20,100 @@
2220
%
2321
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2422

23+
% Set random seed
24+
rng(0)
25+
2526
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2627
% Define the model
2728
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2829

2930
% Here, we use the following model
3031
%
31-
% x[tt+1] = phi * x[tt] + sigmav * v[tt]
32-
% y[tt] = x[tt] + sigmae * e[tt]
32+
% x[t + 1] = phi * x[t] + sigmav * v[t]
33+
% y[t] = x[t] + sigmae * e[t]
3334
%
34-
% where v[tt] ~ N(0,1) and e[tt] ~ N(0,1)
35+
% where v[t] ~ N(0, 1) and e[t] ~ N(0, 1)
3536

3637
% Set the parameters of the model
37-
phi = 0.75;
38+
phi = 0.75;
3839
sigmav = 1.00;
3940
sigmae = 0.10;
41+
theta = [phi sigmav sigmae];
4042

4143
% Set the number of time steps to simulate
42-
T = 500;
44+
T = 250;
4345

4446
% Set the initial state
45-
x0 = 0;
47+
initialState = 0;
4648

4749
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4850
% Generate data
4951
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5052

51-
[x,y] = generateData(phi,sigmav,sigmae,T,x0);
53+
[x, y] = generateData(theta, T, initialState);
5254

5355
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5456
% Parameter estimation using PMH
5557
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5658

5759
% The inital guess of the parameter
58-
initPar = 0.50;
60+
initialPhi = 0.50;
5961

60-
% No. particles in the particle filter ( choose nPart ~ T )
61-
nPart = 100;
62+
% No. particles in the particle filter (choose noParticles ~ T)
63+
noParticles = 100;
6264

63-
% The length of the burn-in and the no. iterations of PMH ( nBurnIn < nRuns )
64-
nBurnIn = 1000;
65-
nRuns = 5000;
65+
% The length of the burn-in and the no. iterations of PMH
66+
% (noBurnInIterations < noIterations)
67+
noBurnInIterations = 1000;
68+
noIterations = 5000;
6669

6770
% The standard deviation in the random walk proposal
6871
stepSize = 0.10;
6972

7073
% Run the PMH algorithm
71-
res = pmh(y,initPar,sigmav,sigmae,nPart,T,x0,nRuns,stepSize);
74+
res = particleMetropolisHastings(y, initialPhi, [sigmav sigmae],...
75+
noParticles, initialState,...
76+
noIterations, stepSize);
7277

7378
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7479
% Plot the results
7580
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7681

82+
noBins = floor(sqrt(noIterations - noBurnInIterations));
83+
grid = noBurnInIterations:noIterations;
84+
resPhi = res(noBurnInIterations:noIterations);
85+
7786
% Plot the parameter posterior estimate
7887
% Solid black line indicate posterior mean
79-
subplot(3,1,1);
80-
hist(res(nBurnIn:nRuns), floor(sqrt(nRuns-nBurnIn)) );
81-
xlabel('phi'); ylabel('posterior density estimate');
88+
subplot(3, 1, 1);
89+
hist(resPhi, noBins);
90+
xlabel('phi');
91+
ylabel('posterior density estimate');
8292

83-
h = findobj(gca,'Type','patch');
84-
set(h,'FaceColor',[117 112 179]/256,'EdgeColor','w');
93+
h = findobj(gca, 'Type', 'patch');
94+
set(h, 'FaceColor', [117 112 179] / 256, 'EdgeColor', 'w');
8595

8696
hold on;
87-
plot([1 1] * mean(res(nBurnIn:nRuns)), [0 500], 'LineWidth', 1);
97+
plot([1 1] * mean(resPhi), [0 200], 'LineWidth', 3);
8898
hold off;
8999

90100
% Plot the trace of the Markov chain after burn-in
91101
% Solid black line indicate posterior mean
92-
subplot(3,1,2);
93-
plot(nBurnIn:nRuns,res(nBurnIn:nRuns), 'Color', [117 112 179]/256, 'LineWidth', 1);
94-
xlabel('iteration'); ylabel('phi');
102+
subplot(3, 1, 2);
103+
plot(grid, resPhi, 'Color', [117 112 179] / 256, 'LineWidth', 1);
104+
xlabel('iteration');
105+
ylabel('phi');
95106

96107
hold on;
97-
plot([nBurnIn,nRuns], [1 1] * mean(res(nBurnIn:nRuns)), 'k', 'LineWidth', 1);
108+
plot([grid(1) grid(end)], [1 1] * mean(resPhi), 'k', 'LineWidth', 3);
98109
hold off;
99110

100111
% Plot ACF of the Markov chain after burn-in
101-
subplot(3,1,3);
102-
macf = acf( res(nBurnIn:nRuns), 100, 0 );
103-
plot(2:101, macf, 'Color', [117 112 179]/256, 'LineWidth', 2);
104-
xlabel('lag'); ylabel('ACF of phi');
112+
subplot(3, 1, 3);
113+
[acf, lags] = xcorr(resPhi - mean(resPhi), 100, 'coeff');
114+
stem(lags(101:200), acf(101:200), 'Color', [117 112 179] / 256, 'LineWidth', 2);
115+
xlabel('lag');
116+
ylabel('ACF of phi');
105117

106118
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107119
% End of file

0 commit comments

Comments
 (0)