Commit 25179aba authored by Frédéric Karamé's avatar Frédéric Karamé
Browse files

add a routine to build the proposal distribution for the conditional particle filter

parent e2b01dd1
function [ProposalStateVector,Weights] = conditional_filter_proposal(ReducedForm,obs,StateVectors,SampleWeights,Q_lower_triangular_cholesky,H_lower_triangular_cholesky,H,DynareOptions,normconst2)
%
% Computes the proposal for each past particle using Gaussian approximations
% for the state errors and the Kalman filter
%
% INPUTS
% reduced_form_model [structure] Matlab's structure describing the reduced form model.
% reduced_form_model.measurement.H [double] (pp x pp) variance matrix of measurement errors.
% reduced_form_model.state.Q [double] (qq x qq) variance matrix of state errors.
% reduced_form_model.state.dr [structure] output of resol.m.
% Y [double] pp*smpl matrix of (detrended) data, where pp is the maximum number of observed variables.
%
% OUTPUTS
% LIK [double] scalar, likelihood
% lik [double] vector, density of observations in each period.
%
% REFERENCES
%
% NOTES
% The vector "lik" is used to evaluate the jacobian of the likelihood.
% Copyright (C) 2012-2013 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
%
% AUTHOR(S) frederic DOT karame AT univ DASH lemans DOT fr
% stephane DOT adjemian AT univ DASH lemans DOT fr
persistent init_flag2 mf0 mf1
persistent number_of_state_variables number_of_observed_variables
persistent number_of_structural_innovations
% Set local state space model (first-order approximation).
ghx = ReducedForm.ghx;
ghu = ReducedForm.ghu;
% Set local state space model (second-order approximation).
ghxx = ReducedForm.ghxx;
ghuu = ReducedForm.ghuu;
ghxu = ReducedForm.ghxu;
if any(any(isnan(ghx))) || any(any(isnan(ghu))) || any(any(isnan(ghxx))) || any(any(isnan(ghuu))) || any(any(isnan(ghxu))) || ...
any(any(isinf(ghx))) || any(any(isinf(ghu))) || any(any(isinf(ghxx))) || any(any(isinf(ghuu))) || any(any(isinf(ghxu))) ...
any(any(abs(ghx)>1e4)) || any(any(abs(ghu)>1e4)) || any(any(abs(ghxx)>1e4)) || any(any(abs(ghuu)>1e4)) || any(any(abs(ghxu)>1e4))
ghx
ghu
ghxx
ghuu
ghxu
end
constant = ReducedForm.constant;
state_variables_steady_state = ReducedForm.state_variables_steady_state;
% Set persistent variables.
if isempty(init_flag2)
mf0 = ReducedForm.mf0;
mf1 = ReducedForm.mf1;
number_of_state_variables = length(mf0);
number_of_observed_variables = length(mf1);
number_of_structural_innovations = length(ReducedForm.Q);
init_flag2 = 1;
end
if strcmpi(DynareOptions.particle.IS_approximation_method,'cubature') || strcmpi(DynareOptions.particle.IS_approximation_method,'monte-carlo')
[nodes,weights] = spherical_radial_sigma_points(number_of_structural_innovations) ;
weights_c = weights ;
end
if strcmpi(DynareOptions.particle.IS_approximation_method,'quadrature')
[nodes,weights] = nwspgr('GQN',number_of_structural_innovations,DynareOptions.particle.smolyak_accuracy) ;
weights_c = weights ;
end
if strcmpi(DynareOptions.particle.IS_approximation_method,'unscented')
[nodes,weights,weights_c] = unscented_sigma_points(number_of_structural_innovations,DynareOptions) ;
end
epsilon = Q_lower_triangular_cholesky*(nodes') ;
yhat = repmat(StateVectors-state_variables_steady_state,1,size(epsilon,2)) ;
tmp = local_state_space_iteration_2(yhat,epsilon,ghx,ghu,constant,ghxx,ghuu,ghxu,DynareOptions.threads.local_state_space_iteration_2);
PredictedStateMean = tmp(mf0,:)*weights ;
PredictedObservedMean = tmp(mf1,:)*weights;
if strcmpi(DynareOptions.particle.IS_approximation_method,'cubature') || ...
strcmpi(DynareOptions.particle.IS_approximation_method,'monte-carlo')
PredictedStateMean = sum(PredictedStateMean,2) ;
PredictedObservedMean = sum(PredictedObservedMean,2) ;
dState = bsxfun(@minus,tmp(mf0,:),PredictedStateMean)'.*sqrt(weights) ;
dObserved = bsxfun(@minus,tmp(mf1,:),PredictedObservedMean)'.*sqrt(weights);
big_mat = [dObserved dState ; [H_lower_triangular_cholesky zeros(number_of_observed_variables,number_of_state_variables)] ] ;
[mat1,mat] = qr2(big_mat,0) ;
mat = mat' ;
clear('mat1');
PredictedObservedVarianceSquareRoot = mat(1:number_of_observed_variables,1:number_of_observed_variables) ;
CovarianceObservedStateSquareRoot = mat(number_of_observed_variables+(1:number_of_state_variables),1:number_of_observed_variables) ;
StateVectorVarianceSquareRoot = mat(number_of_observed_variables+(1:number_of_state_variables),number_of_observed_variables+(1:number_of_state_variables)) ;
StateVectorMean = PredictedStateMean + (CovarianceObservedStateSquareRoot/PredictedObservedVarianceSquareRoot)*(obs - PredictedObservedMean) ;
end
if strcmpi(DynareOptions.particle.IS_approximation_method,'quadrature') || ...
strcmpi(DynareOptions.particle.IS_approximation_method,'unscented')
dState = bsxfun(@minus,tmp(mf0,:),PredictedStateMean);
dObserved = bsxfun(@minus,tmp(mf1,:),PredictedObservedMean);
PredictedStateVariance = dState*diag(weights_c)*dState';
PredictedObservedVariance = dObserved*diag(weights_c)*dObserved' + H;
PredictedStateAndObservedCovariance = dState*diag(weights_c)*dObserved';
KalmanFilterGain = PredictedStateAndObservedCovariance/PredictedObservedVariance ;
StateVectorMean = PredictedStateMean + KalmanFilterGain*(obs - PredictedObservedMean);
StateVectorVariance = PredictedStateVariance - KalmanFilterGain*PredictedObservedVariance*KalmanFilterGain';
StateVectorVariance = .5*(StateVectorVariance+StateVectorVariance');
StateVectorVarianceSquareRoot = reduced_rank_cholesky(StateVectorVariance)';
end
ProposalStateVector = StateVectorVarianceSquareRoot*randn(size(StateVectorVarianceSquareRoot,2),1)+StateVectorMean ;
ypred = measurement_equations(ProposalStateVector,ReducedForm,DynareOptions) ;
foo = H_lower_triangular_cholesky \ (obs - ypred) ;
likelihood = exp(-0.5*(foo)'*foo)/normconst2 + 1e-99 ;
Weights = SampleWeights.*likelihood ;
function [LIK,lik] = conditional_particle_filter(ReducedForm,Y,start,DynareOptions)
%
% Evaluates the likelihood of a non-linear model with a particle filter
% - the proposal is built using the Kalman updating step for each particle.
% - we need draws in the errors distributions
% Whether we use Monte-Carlo draws from a multivariate gaussian distribution
% as in Amisano & Tristani (JEDC 2010).
% Whether we use multidimensional Gaussian sparse grids approximations:
% - a univariate Kronrod-Paterson Gaussian quadrature combined by the Smolyak
% operator (ref: Winschel & Kratzig, 2010).
% - a spherical-radial cubature (ref: Arasaratnam & Haykin, 2009a,2009b).
% - a scaled unscented transform cubature (ref: Julier & Uhlmann 1997, van der
% Merwe & Wan 2003).
%
% Pros:
% - Allows using current observable information in the proposal
% - The use of sparse grids Gaussian approximation is much faster than the Monte-Carlo approach
% Cons:
% - The use of the Kalman updating step may biais the proposal distribution since
% it has been derived in a linear context and is implemented in a nonlinear
% context. That is why particle resampling is performed.
%
% INPUTS
% reduced_form_model [structure] Matlab's structure describing the reduced form model.
% reduced_form_model.measurement.H [double] (pp x pp) variance matrix of measurement errors.
% reduced_form_model.state.Q [double] (qq x qq) variance matrix of state errors.
% reduced_form_model.state.dr [structure] output of resol.m.
% Y [double] pp*smpl matrix of (detrended) data, where pp is the maximum number of observed variables.
% start [integer] scalar, likelihood evaluation starts at 'start'.
% smolyak_accuracy [integer] scalar.
%
% OUTPUTS
% LIK [double] scalar, likelihood
% lik [double] vector, density of observations in each period.
%
% REFERENCES
%
% NOTES
% The vector "lik" is used to evaluate the jacobian of the likelihood.
% Copyright (C) 2009-2010 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
% AUTHOR(S) frederic DOT karame AT univ DASH lemans DOT fr
% stephane DOT adjemian AT univ DASH lemans DOT fr
persistent init_flag mf0 mf1
persistent number_of_particles
persistent sample_size number_of_state_variables number_of_observed_variables
% Set default
if isempty(start)
start = 1;
end
% Set persistent variables.
if isempty(init_flag)
mf0 = ReducedForm.mf0;
mf1 = ReducedForm.mf1;
sample_size = size(Y,2);
number_of_state_variables = length(mf0);
number_of_observed_variables = length(mf1);
init_flag = 1;
number_of_particles = DynareOptions.particle.number_of_particles ;
end
% Get covariance matrices
Q = ReducedForm.Q;
H = ReducedForm.H;
if isempty(H)
H = 0;
H_lower_triangular_cholesky = 0;
else
H_lower_triangular_cholesky = reduced_rank_cholesky(H)';
end
% Get initial condition for the state vector.
StateVectorMean = ReducedForm.StateVectorMean;
StateVectorVarianceSquareRoot = reduced_rank_cholesky(ReducedForm.StateVectorVariance)';
state_variance_rank = size(StateVectorVarianceSquareRoot,2);
Q_lower_triangular_cholesky = reduced_rank_cholesky(Q)';
% Set seed for randn().
set_dynare_seed('default');
% Initialization of the likelihood.
normconst2 = log(2*pi)*number_of_observed_variables*prod(diag(H_lower_triangular_cholesky)) ;
lik = NaN(sample_size,1);
LIK = NaN;
ks = 0 ;
StateParticles = bsxfun(@plus,StateVectorVarianceSquareRoot*randn(state_variance_rank,number_of_particles),StateVectorMean);
SampleWeights = ones(1,number_of_particles)/number_of_particles ;
for t=1:sample_size
for i=1:number_of_particles
[StateParticles(:,i),SampleWeights(i)] = ...
conditional_filter_proposal(ReducedForm,Y(:,t),StateParticles(:,i),SampleWeights(i),Q_lower_triangular_cholesky,H_lower_triangular_cholesky,H,DynareOptions,normconst2) ;
end
SumSampleWeights = sum(SampleWeights) ;
lik(t) = log(SumSampleWeights) ;
SampleWeights = SampleWeights./SumSampleWeights ;
if (strcmp(DynareOptions.particle.resampling.status,'generic') && neff(SampleWeights)<DynareOptions.particle.resampling.neff_threshold*sample_size ) || ...
strcmp(DynareOptions.particle.resampling.status,'systematic')
ks = ks + 1 ;
StateParticles = resample(StateParticles',SampleWeights,DynareOptions)';
SampleWeights = ones(1,number_of_particles)/number_of_particles ;
end
end
LIK = -sum(lik(start:end));
......@@ -44,6 +44,8 @@ persistent start_param sample_size number_of_observed_variables number_of_struct
%set_dynare_seed('mt19937ar',1234) ;
set_dynare_seed('default') ;
pruning = DynareOptions.particle.pruning;
second_resample = 1 ;
variance_update = 1 ;
% initialization of state particles
[ys,trend_coeff,exit_flag,info,Model,DynareOptions,BayesInfo,DynareResults,ReducedForm] = ...
......@@ -61,10 +63,10 @@ if isempty(init_flag)
number_of_structural_innovations = length(ReducedForm.Q);
liu_west_delta = DynareOptions.particle.liu_west_delta ;
liu_west_chol_sigma_bar = DynareOptions.particle.liu_west_chol_sigma_bar*eye(number_of_parameters) ;
start_param = xparam1 ;
%start_param = xparam1 ;
% Conditions initiales
%liu_west_chol_sigma_bar = bsxfun(@times,eye(number_of_parameters),BayesInfo.p2) ;
%start_param = BayesInfo.p1 ;
start_param = BayesInfo.p1 ;
bounds = [BayesInfo.lb BayesInfo.ub] ;
init_flag = 1;
end
......@@ -78,22 +80,26 @@ if pruning
StateVectors_ = StateVectors;
end
% Initialization of parameter particles
% parameters for the Liu & West filter
h_square = (3*liu_west_delta-1)/(2*liu_west_delta) ;
h_square = 1-h_square*h_square ;
small_a = sqrt(1-h_square) ;
% Initialization of parameter particles
xparam = zeros(number_of_parameters,number_of_particles) ;
%candidate = prior_draw(1) ;
stderr = sqrt(bsxfun(@power,bounds(:,2)+bounds(:,1),2)/12)/1000 ;
i = 1 ;
while i<=number_of_particles
candidate = start_param + liu_west_chol_sigma_bar*rand(number_of_parameters,1) ;
%candidate = prior_draw(0) ;
candidate = start_param + 10*liu_west_chol_sigma_bar*randn(number_of_parameters,1) ;
%candidate = start_param + bsxfun(@times,stderr,randn(number_of_parameters,1)) ;
if all(candidate(:) >= bounds(:,1)) && all(candidate(:) <= bounds(:,2))
xparam(:,i) = candidate(:) ;
i = i+1 ;
end
end
%xparam = bsxfun(@plus,bounds(:,1),bsxfun(@times,(bounds(:,2)-bounds(:,1)),rand(number_of_parameters,number_of_particles))) ;
% Initialization of the weights of particles.
weights = ones(1,number_of_particles)/number_of_particles ;
......@@ -112,7 +118,9 @@ for t=1:sample_size
m_bar = xparam*(weights') ;
temp = bsxfun(@minus,xparam,m_bar) ;
sigma_bar = (bsxfun(@times,weights,temp))*(temp') ;
chol_sigma_bar = chol(h_square*sigma_bar)' ;
if variance_update==1
chol_sigma_bar = chol(h_square*sigma_bar)' ;
end
% Prediction (without shocks)
ObservedVariables = zeros(number_of_observed_variables,number_of_particles) ;
for i=1:number_of_particles
......@@ -159,7 +167,7 @@ for t=1:sample_size
% draw in the new distributions
i = 1 ;
while i<=number_of_particles
candidate = xparam(:,i) + chol_sigma_bar*rand(number_of_parameters,1) ;
candidate = xparam(:,i) + chol_sigma_bar*randn(number_of_parameters,1) ;
if all(candidate >= bounds(:,1)) && all(candidate <= bounds(:,2))
xparam(:,i) = candidate ;
% model resolution for new parameters particles
......@@ -175,7 +183,7 @@ for t=1:sample_size
ghuu = ReducedForm.ghuu;
ghxu = ReducedForm.ghxu;
% Get covariance matrices and structural shocks
epsilon = chol(ReducedForm.Q)'*rand(number_of_structural_innovations,1) ;
epsilon = chol(ReducedForm.Q)'*randn(number_of_structural_innovations,1) ;
% compute particles likelihood contribution
yhat = bsxfun(@minus,StateVectors(:,i),state_variables_steady_state);
if pruning
......@@ -199,25 +207,57 @@ for t=1:sample_size
wtilde = lnw./wtilde ;
% normalization
weights = wtilde/sum(wtilde);
% final resampling (advised)
indx = index_resample(0,weights,DynareOptions);
StateVectors = StateVectors(:,indx) ;
if pruning
StateVectors_ = StateVectors_(:,indx) ;
if (variance_update==1) && (neff(weights)<DynareOptions.particle.resampling.neff_threshold*sample_size)
variance_update = 0 ;
end
xparam = xparam(:,indx) ;
weights = ones(1,number_of_particles)/number_of_particles ;
%
mean_xparam(:,t) = mean(xparam,2);
mat_var_cov = bsxfun(@minus,xparam,mean_xparam(:,t)) ;
mat_var_cov = (mat_var_cov*mat_var_cov')/(number_of_particles-1) ;
std_xparam(:,t) = sqrt(diag(mat_var_cov)) ;
for i=1:number_of_parameters
temp = sortrows(xparam(i,:)') ;
lb95_xparam(i,t) = temp(0.025*number_of_particles) ;
median_xparam(i,t) = temp(0.5*number_of_particles) ;
ub95_xparam(i,t) = temp(0.975*number_of_particles) ;
% final resampling (advised)
if second_resample==1
indx = index_resample(0,weights,DynareOptions);
StateVectors = StateVectors(:,indx) ;
if pruning
StateVectors_ = StateVectors_(:,indx) ;
end
xparam = xparam(:,indx) ;
weights = ones(1,number_of_particles)/number_of_particles ;
mean_xparam(:,t) = mean(xparam,2);
mat_var_cov = bsxfun(@minus,xparam,mean_xparam(:,t)) ;
mat_var_cov = (mat_var_cov*mat_var_cov')/(number_of_particles-1) ;
std_xparam(:,t) = sqrt(diag(mat_var_cov)) ;
for i=1:number_of_parameters
temp = sortrows(xparam(i,:)') ;
lb95_xparam(i,t) = temp(0.025*number_of_particles) ;
median_xparam(i,t) = temp(0.5*number_of_particles) ;
ub95_xparam(i,t) = temp(0.975*number_of_particles) ;
end
end
if second_resample==0
mean_xparam(:,t) = xparam*(weights') ;
mat_var_cov = bsxfun(@minus,xparam,mean_xparam(:,t)) ;
mat_var_cov = mat_var_cov*(bsxfun(@times,mat_var_cov,weights)') ;
std_xparam(:,t) = sqrt(diag(mat_var_cov)) ;
for i=1:number_of_parameters
temp = sortrows([xparam(i,:)' weights'],1) ;
cumulated_weights = cumsum(temp(:,2)) ;
pass1=1 ;
pass2=1 ;
pass3=1 ;
for j=1:number_of_particles
if cumulated_weights(j)>0.025 && pass1==1
lb95_xparam(i,t) = (temp(j-1,1)+temp(j,1))/2 ;
pass1 = 2 ;
end
if cumulated_weights(j)>0.5 && pass2==1
median_xparam(i,t) = (temp(j-1,1)+temp(j,1))/2 ;
pass2 = 2 ;
end
if cumulated_weights(j)>0.975 && pass3==1
ub95_xparam(i,t) = (temp(j-1,1)+temp(j,1))/2 ;
pass3 = 2 ;
end
end
end
end
disp([lb95_xparam(:,t) mean_xparam(:,t) ub95_xparam(:,t)])
end
xparam = mean_xparam(:,sample_size) ;
std_param = std_xparam(:,sample_size) ;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment