From 79b6184d876d2a43107c67dd4094351b8c34462e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Adjemian=20=28Argos=29?= <stepan@adjemian.eu> Date: Mon, 24 Mar 2025 12:30:07 +0100 Subject: [PATCH] Make SIS (particle filter) compatible with linear models. --- matlab/estimation/dynare_estimation_1.m | 62 +++++++++---------- .../estimation/non_linear_dsge_likelihood.m | 29 +++++---- .../sequential_importance_particle_filter.m | 51 ++++++++------- 3 files changed, 73 insertions(+), 69 deletions(-) diff --git a/matlab/estimation/dynare_estimation_1.m b/matlab/estimation/dynare_estimation_1.m index e82e4389dd..1c42b50992 100644 --- a/matlab/estimation/dynare_estimation_1.m +++ b/matlab/estimation/dynare_estimation_1.m @@ -12,7 +12,7 @@ function dynare_estimation_1(var_list_,dname) % SPECIAL REQUIREMENTS % none -% Copyright © 2003-2024 Dynare Team +% Copyright © 2003-2025 Dynare Team % % This file is part of Dynare. % @@ -68,35 +68,31 @@ else end % Set particle filter flag. -if options_.order > 1 - if options_.particle.status - skipline() - disp('Estimation using a non linear filter!') - skipline() - if ~options_.nointeractive && ismember(options_.mode_compute,[1,3,4]) && ~strcmpi(options_.particle.filter_algorithm,'gf')% Known gradient-based optimizers - disp('You are using a gradient-based mode-finder. Particle filtering introduces discontinuities in the') - disp('objective function w.r.t the parameters. Thus, should use a non-gradient based optimizer.') - fprintf('\nPlease choose a mode-finder:\n') - fprintf('\t 0 - Continue using gradient-based method (it is most likely that you will no get any sensible result).\n') - fprintf('\t 6 - Monte Carlo based algorithm\n') - fprintf('\t 7 - Nelder-Mead simplex based optimization routine (Matlab optimization toolbox required)\n') - fprintf('\t 8 - Nelder-Mead simplex based optimization routine (Dynare''s implementation)\n') - fprintf('\t 9 - CMA-ES (Covariance Matrix Adaptation Evolution Strategy) algorithm\n') - choice = []; - while isempty(choice) - choice = input('Please enter your choice: '); - if isnumeric(choice) && isint(choice) && ismember(choice,[0 6 7 8 9]) - if choice - options_.mode_compute = choice; - end - else - fprintf('\nThis is an invalid choice (you have to choose between 0, 6, 7, 8 and 9).\n') - choice = []; +if options_.particle.status + skipline() + disp('Estimation using a non linear filter!') + skipline() + if ~options_.nointeractive && ismember(options_.mode_compute,[1,3,4]) && ~strcmpi(options_.particle.filter_algorithm,'gf')% Known gradient-based optimizers + disp('You are using a gradient-based mode-finder. Particle filtering introduces discontinuities in the') + disp('objective function w.r.t the parameters. Thus, should use a non-gradient based optimizer.') + fprintf('\nPlease choose a mode-finder:\n') + fprintf('\t 0 - Continue using gradient-based method (it is most likely that you will no get any sensible result).\n') + fprintf('\t 6 - Monte Carlo based algorithm\n') + fprintf('\t 7 - Nelder-Mead simplex based optimization routine (Matlab optimization toolbox required)\n') + fprintf('\t 8 - Nelder-Mead simplex based optimization routine (Dynare''s implementation)\n') + fprintf('\t 9 - CMA-ES (Covariance Matrix Adaptation Evolution Strategy) algorithm\n') + choice = []; + while isempty(choice) + choice = input('Please enter your choice: '); + if isnumeric(choice) && isint(choice) && ismember(choice,[0 6 7 8 9]) + if choice + options_.mode_compute = choice; end + else + fprintf('\nThis is an invalid choice (you have to choose between 0, 6, 7, 8 and 9).\n') + choice = []; end end - else - error('For estimating the model with a second order approximation using a non linear filter, one should have options_.particle.status=true;') end end @@ -579,14 +575,14 @@ end %Run and store classical smoother if needed if options_.smoother && ... %Bayesian smoother requested before - (any(bayestopt_.pshape > 0) && options_.mh_replic || ... % Bayesian with MCMC run - any(bayestopt_.pshape > 0) && options_.load_mh_file) % Bayesian with loaded MCMC - % nothing to do + (any(bayestopt_.pshape > 0) && options_.mh_replic || ... % Bayesian with MCMC run + any(bayestopt_.pshape > 0) && options_.load_mh_file) % Bayesian with loaded MCMC + % nothing to do elseif options_.partial_information ||... - options_.order>1 %no particle smoother - % smoothing not yet supported + options_.order>1 %no particle smoother + % smoothing not yet supported else - %% ML estimation, or posterior mode without Metropolis-Hastings or Metropolis without Bayesian smoothed variables + % ML estimation, or posterior mode without Metropolis-Hastings or Metropolis without Bayesian smoothed variables oo_=save_display_classical_smoother_results(xparam1,M_,oo_,options_,bayestopt_,dataset_,dataset_info,estim_params_); end diff --git a/matlab/estimation/non_linear_dsge_likelihood.m b/matlab/estimation/non_linear_dsge_likelihood.m index a7b13c1798..0ee495f431 100644 --- a/matlab/estimation/non_linear_dsge_likelihood.m +++ b/matlab/estimation/non_linear_dsge_likelihood.m @@ -120,7 +120,10 @@ state_variables_idx = restrict_variables_idx(mf0); number_of_state_variables = length(mf0); ReducedForm.steadystate = dr.ys(dr.order_var(restrict_variables_idx)); -ReducedForm.constant = ReducedForm.steadystate + .5*dr.ghs2(restrict_variables_idx); +ReducedForm.constant = ReducedForm.steadystate; +if options_.order==2 + ReducedForm.constant = ReducedForm.constant + .5*dr.ghs2(restrict_variables_idx); +end ReducedForm.state_variables_steady_state = dr.ys(dr.order_var(state_variables_idx)); ReducedForm.Q = Q; ReducedForm.H = H; @@ -138,17 +141,19 @@ else ReducedForm.use_k_order_solver = false; ReducedForm.ghx = dr.ghx(restrict_variables_idx,:); ReducedForm.ghu = dr.ghu(restrict_variables_idx,:); - ReducedForm.ghxx = dr.ghxx(restrict_variables_idx,:); - ReducedForm.ghuu = dr.ghuu(restrict_variables_idx,:); - ReducedForm.ghxu = dr.ghxu(restrict_variables_idx,:); - ReducedForm.ghs2 = dr.ghs2(restrict_variables_idx,:); - if options_.order==3 - ReducedForm.ghxxx = dr.ghxxx(restrict_variables_idx,:); - ReducedForm.ghuuu = dr.ghuuu(restrict_variables_idx,:); - ReducedForm.ghxxu = dr.ghxxu(restrict_variables_idx,:); - ReducedForm.ghxuu = dr.ghxuu(restrict_variables_idx,:); - ReducedForm.ghxss = dr.ghxss(restrict_variables_idx,:); - ReducedForm.ghuss = dr.ghuss(restrict_variables_idx,:); + if options_.order>1 + ReducedForm.ghxx = dr.ghxx(restrict_variables_idx,:); + ReducedForm.ghuu = dr.ghuu(restrict_variables_idx,:); + ReducedForm.ghxu = dr.ghxu(restrict_variables_idx,:); + ReducedForm.ghs2 = dr.ghs2(restrict_variables_idx,:); + if options_.order==3 + ReducedForm.ghxxx = dr.ghxxx(restrict_variables_idx,:); + ReducedForm.ghuuu = dr.ghuuu(restrict_variables_idx,:); + ReducedForm.ghxxu = dr.ghxxu(restrict_variables_idx,:); + ReducedForm.ghxuu = dr.ghxuu(restrict_variables_idx,:); + ReducedForm.ghxss = dr.ghxss(restrict_variables_idx,:); + ReducedForm.ghuss = dr.ghuss(restrict_variables_idx,:); + end end end diff --git a/matlab/nonlinear-filters/sequential_importance_particle_filter.m b/matlab/nonlinear-filters/sequential_importance_particle_filter.m index 0ac02e8f7d..2bfb281676 100644 --- a/matlab/nonlinear-filters/sequential_importance_particle_filter.m +++ b/matlab/nonlinear-filters/sequential_importance_particle_filter.m @@ -2,7 +2,7 @@ function [LIK,lik] = sequential_importance_particle_filter(ReducedForm,Y,start,P % Evaluates the likelihood of a nonlinear model with a particle filter (optionally with resampling). -% Copyright © 2011-2022 Dynare Team +% Copyright © 2011-2025 Dynare Team % % This file is part of Dynare (particles module). % @@ -47,20 +47,21 @@ else % 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; - ghs2 = ReducedForm.ghs2; - if order == 3 - % Set local state space model (third order approximation). - ghxxx = ReducedForm.ghxxx; - ghuuu = ReducedForm.ghuuu; - ghxxu = ReducedForm.ghxxu; - ghxuu = ReducedForm.ghxuu; - ghxss = ReducedForm.ghxss; - ghuss = ReducedForm.ghuss; + if order>1 + ghxx = ReducedForm.ghxx; + ghuu = ReducedForm.ghuu; + ghxu = ReducedForm.ghxu; + ghs2 = ReducedForm.ghs2; + if order == 3 + % Set local state space model (third order approximation). + ghxxx = ReducedForm.ghxxx; + ghuuu = ReducedForm.ghuuu; + ghxxu = ReducedForm.ghxxu; + ghxuu = ReducedForm.ghxuu; + ghxss = ReducedForm.ghxss; + ghuss = ReducedForm.ghuss; + end end end @@ -126,20 +127,22 @@ for t=1:sample_size if ReducedForm.use_k_order_solver tmp = local_state_space_iteration_k(yhat, epsilon, dr, M_, options_, udr); else - if order == 2 + switch order + case 1 + tmp = NaN(rows(ghx), columns(yhat)); + parfor i=1:columns(yhat) + tmp(:,i) = constant + ghx*yhat(:,i) + ghu*epsilon(:,i) + end + case 2 tmp = local_state_space_iteration_2(yhat,epsilon,ghx,ghu,constant,ghxx,ghuu,ghxu,ThreadsOptions.local_state_space_iteration_2); - elseif order == 3 + case 3 tmp = local_state_space_iteration_3(yhat, epsilon, ghx, ghu, ghxx, ghuu, ghxu, ghs2, ghxxx, ghuuu, ghxxu, ghxuu, ghxss, ghuss, steadystate, ThreadsOptions.local_state_space_iteration_3, pruning); - else + otherwise error('Order > 3: use_k_order_solver should be set to true'); end end end - %PredictedObservedMean = tmp(mf1,:)*transpose(weights); PredictionError = bsxfun(@minus,Y(:,t),tmp(ReducedForm.mf1,:)); - %dPredictedObservedMean = bsxfun(@minus,tmp(mf1,:),PredictedObservedMean); - %PredictedObservedVariance = bsxfun(@times,dPredictedObservedMean,weights)*dPredictedObservedMean' + H; - %PredictedObservedVariance = H; if rcond(H) > 1e-16 lnw = -.5*(const_lik+sum(PredictionError.*(H\PredictionError),1)); else @@ -150,13 +153,13 @@ for t=1:sample_size wtilde = weights.*exp(lnw-dfac); lik(t) = log(sum(wtilde))+dfac; weights = wtilde/sum(wtilde); - if (ParticleOptions.resampling.status.generic && neff(weights)<ParticleOptions.resampling.threshold*sample_size) || ParticleOptions.resampling.status.systematic + if (ParticleOptions.resampling.status.generic && neff(weights)<ParticleOptions.resampling.threshold*number_of_particles) || ParticleOptions.resampling.status.systematic if pruning - temp = resample([tmp(ReducedForm.mf0,:)' tmp_(mf0_,:)'],weights',ParticleOptions); + temp = resample([tmp(ReducedForm.mf0,:)' tmp_(mf0_,:)'], weights', ParticleOptions); StateVectors = temp(:,1:number_of_state_variables)'; StateVectors_ = temp(:,number_of_state_variables+1:end)'; else - StateVectors = resample(tmp(ReducedForm.mf0,:)',weights',ParticleOptions)'; + StateVectors = resample(tmp(ReducedForm.mf0,:)', weights', ParticleOptions)'; end weights = ones(1,number_of_particles)/number_of_particles; elseif ParticleOptions.resampling.status.none -- GitLab