Added new option mh_tune_jscale.
Works only with the Random Walk Metropolis Hastings algorithm. Closes #1598time-shift
parent
3f674f0f26
commit
f53be721c1
|
@ -5595,12 +5595,17 @@ variance if the acceptance ratio is too low. In some situations it may
|
|||
help to consider parameter-specific values for this scale parameter.
|
||||
This can be done in the @ref{estimated_params}- block.
|
||||
|
||||
Note that @code{mode_compute=6} will tune the scale parameter to achieve an acceptance rate of
|
||||
@ref{AcceptanceRateTarget}. The resulting scale parameter will be saved into a file
|
||||
named @file{@var{MODEL_FILENAME}_mh_scale.mat}. This file can be loaded in subsequent runs
|
||||
via the @code{posterior_sampler_options}-option @ref{scale_file}. Both @code{mode_compute=6}
|
||||
and @code{scale_file} will overwrite any value specified in @code{estimated_params} with the tuned value.
|
||||
Default: @code{0.2}
|
||||
Note that @code{mode_compute=6} will tune the scale parameter to achieve an
|
||||
acceptance rate of @ref{AcceptanceRateTarget}. The resulting scale parameter
|
||||
will be saved into a file named @file{@var{MODEL_FILENAME}_mh_scale.mat}. This
|
||||
file can be loaded in subsequent runs via the
|
||||
@code{posterior_sampler_options}-option @ref{scale_file}. Both
|
||||
@code{mode_compute=6} and @code{scale_file} will overwrite any value specified
|
||||
in @code{estimated_params} with the tuned value. Default: @code{0.2}
|
||||
|
||||
Note also that for the Random Walk Metropolis Hastings algorithm, it is
|
||||
possible to use option @ref{mh_tune_jscale}, to automatically tune the value of
|
||||
@code{mh_jscale}.
|
||||
|
||||
@item mh_init_scale = @var{DOUBLE}
|
||||
The scale to be used for drawing the initial value of the
|
||||
|
@ -5617,6 +5622,16 @@ If the @ref{nointeractive}-option has been invoked, the program will instead aut
|
|||
@code{mh_init_scale} by 10 percent after 100 futile draws and try another 100 draws. This iterative
|
||||
procedure will take place at most 10 times, at which point Dynare will abort with an error message.
|
||||
|
||||
@item mh_tune_jscale [= @var{DOUBLE}]
|
||||
@anchor{mh_tune_jscale} Automatically tunes the scale parameter of the jumping
|
||||
distribution's covariance matrix (Metropolis-Hastings), so that the overall
|
||||
acceptance ratio is close to the desired level. Default value is
|
||||
@code{0.33}. It is not possible to match exactly the desired
|
||||
acceptance ratio because of the stochastic nature of the algoirithm (the
|
||||
proposals and the initialial conditions of the markov chains if
|
||||
@code{mh_nblocks>1}). This option is only available for the Random Walk
|
||||
Metropolis Hastings algorithm.
|
||||
|
||||
@item mh_recover
|
||||
@anchor{mh_recover} Attempts to recover a Metropolis-Hastings
|
||||
simulation that crashed prematurely, starting with the last available saved
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
function Scale = calibrate_mh_scale_parameter(ObjectiveFunction, CovarianceMatrix, Parameters, MhBounds, options, varargin)
|
||||
|
||||
% Tune the MH scale parameter so that the overall acceptance ratio is close to AcceptanceTarget.
|
||||
%
|
||||
% INPUTS
|
||||
% - ObjectiveFunction [fhandle] Function (posterior kernel).
|
||||
% - CovarianceMatrix [double] n*n matrix, covariance matrix of the jumping distribution.
|
||||
% - Parameters [double] n*1 vector, parameter values.
|
||||
% - MhBounds [double] n*2 matrix, bounds on the possible values for the parameters.
|
||||
% - options [structure] content of options_.tune_mh_jscale.
|
||||
% - varargin [cell] Additional arguments to be passed to ObjectiveFunction.
|
||||
%
|
||||
% OUTPUTS
|
||||
% - Scale [double] scalar, optimal scale parameter for teh jumping distribution.
|
||||
|
||||
% Fire up the wait bar
|
||||
hh = dyn_waitbar(0,'Tuning of the scale parameter...');
|
||||
set(hh,'Name','Tuning of the scale parameter.');
|
||||
|
||||
% Intilialize various counters.
|
||||
j = 1; jj = 1; isux = 0; jsux = 0; i = 0;
|
||||
|
||||
% Evaluate the objective function.
|
||||
logpo0 = - feval(ObjectiveFunction, Parameters, varargin{:});
|
||||
logpo1 = logpo0;
|
||||
|
||||
% Get the dimension of the problem.
|
||||
n = length(Parameters);
|
||||
|
||||
% Initialize the correction on the scale factor.
|
||||
correction = 1.0;
|
||||
|
||||
% Set the initial value of the scale parameter
|
||||
Scale = options.guess;
|
||||
|
||||
% Transposition of some arrays.
|
||||
MhBounds = MhBounds';
|
||||
Parameters = Parameters';
|
||||
|
||||
% Compute the Cholesky of the covariance matrix, return an error if the
|
||||
% matrix is not positive definite.
|
||||
try
|
||||
dd = chol(CovarianceMatrix);
|
||||
catch
|
||||
error('The covariance matrix has to be a symetric positive definite matrix!')
|
||||
end
|
||||
|
||||
% Set parameters related to the proposal distribution
|
||||
if options.rwmh.proposal_distribution=='rand_multivariate_normal'
|
||||
nu = n;
|
||||
elseif options.rwmh.proposal_distribution=='rand_multivariate_student'
|
||||
nu = options.rwmh.student_degrees_of_freedom;
|
||||
end
|
||||
|
||||
% Random Walk Metropolis Hastings iterations...
|
||||
while j<=options.maxiter
|
||||
% Obtain a proposal (jump)
|
||||
proposal = feval(options.rwmh.proposal_distribution, Parameters, Scale*dd, nu);
|
||||
% If out of boundaries set the posterior kernel equal to minus infinity
|
||||
% so that the proposal will be rejected with probability one.
|
||||
if all(proposal > MhBounds(1,:)) && all(proposal < MhBounds(2,:))
|
||||
logpo0 = -feval(ObjectiveFunction, proposal(:), varargin{:});
|
||||
else
|
||||
logpo0 = -inf;
|
||||
end
|
||||
% Move if the proposal is enough likely...
|
||||
if logpo0>-inf && log(rand)<logpo0-logpo1
|
||||
Parameters = proposal;
|
||||
logpo1 = logpo0;
|
||||
isux = isux + 1;
|
||||
jsux = jsux + 1;
|
||||
end% ... otherwise I don't move.
|
||||
prtfrc = j/options.maxiter;
|
||||
% Update the waitbar
|
||||
if ~mod(j, 10)
|
||||
dyn_waitbar(prtfrc, hh, sprintf('Acceptance ratio [during last 500]: %f [%f]', isux/j, jsux/jj));
|
||||
end
|
||||
% Adjust the value of the scale parameter.
|
||||
if ~mod(j, options.stepsize)
|
||||
r1 = jsux/jj; % Local acceptance ratio
|
||||
r2 = isux/j; % Overall acceptance ratio
|
||||
% Set correction for the scale factor
|
||||
c1 = r1/options.target;
|
||||
if abs(c1-1)>.05
|
||||
correction = correction^options.rho*c1^(1-options.rho);
|
||||
else
|
||||
correction = c1;
|
||||
end
|
||||
% Apply correction
|
||||
if c1>0
|
||||
Scale = Scale*correction;
|
||||
else
|
||||
Scale = Scale/10;
|
||||
end
|
||||
% Update some counters.
|
||||
jsux = 0; jj = 0;
|
||||
if abs(r2-options.target)<options.c2 && abs(r1-options.target)<options.c1
|
||||
i = i+1;
|
||||
else
|
||||
i = 0;
|
||||
end
|
||||
% Test convergence.
|
||||
if i>options.c3
|
||||
break
|
||||
end
|
||||
end
|
||||
j = j+1;
|
||||
jj = jj + 1;
|
||||
end
|
||||
|
||||
dyn_waitbar_close(hh);
|
|
@ -228,7 +228,7 @@ if ~isequal(options_.mode_compute,0) && ~options_.mh_posterior_mode_estimation
|
|||
elseif isnumeric(options_.mode_compute) && options_.mode_compute==6 %save scaling factor
|
||||
save([M_.fname '_optimal_mh_scale_parameter.mat'],'Scale');
|
||||
options_.mh_jscale = Scale;
|
||||
bayestopt_.jscale = ones(length(xparam1),1)*Scale;
|
||||
bayestopt_.jscale(:) = options_.mh_jscale;
|
||||
end
|
||||
if ~isnumeric(options_.mode_compute) || ~isequal(options_.mode_compute,6) %always already computes covariance matrix
|
||||
if options_.cova_compute == 1 %user did not request covariance not to be computed
|
||||
|
@ -438,6 +438,21 @@ if (any(bayestopt_.pshape >0 ) && options_.mh_replic) || ...
|
|||
error(['Estimation:: Mode value(s) of ', disp_string ,' are outside parameter bounds.'])
|
||||
end
|
||||
end
|
||||
% Tunes the jumping distribution's scale parameter
|
||||
if options_.mh_tune_jscale.status
|
||||
if options_.posterior_sampler_options.posterior_sampling_method=='random_walk_metropolis_hastings'
|
||||
options = options_.mh_tune_jscale;
|
||||
options.rwmh = options_.posterior_sampler_options.rwmh;
|
||||
options_.mh_jscale = calibrate_mh_scale_parameter(objective_function, ...
|
||||
invhess, xparam1, [bounds.lb,bounds.ub], ...
|
||||
options, dataset_, dataset_info, options_, M_, estim_params_, bayestopt_, bounds, oo_);
|
||||
bayestopt_.jscale(:) = options_.mh_jscale;
|
||||
disp(sprintf('mh_jscale has been set equal to %s', num2str(options_.mh_jscale)))
|
||||
skipline()
|
||||
else
|
||||
warning('mh_tune_jscale is only available with Random Walk Metropolis Hastings!')
|
||||
end
|
||||
end
|
||||
% runs MCMC
|
||||
if options_.mh_replic || options_.load_mh_file
|
||||
posterior_sampler_options = options_.posterior_sampler_options.current_options;
|
||||
|
|
|
@ -442,6 +442,15 @@ options_.mh_conf_sig = 0.90;
|
|||
options_.prior_interval = 0.90;
|
||||
options_.mh_drop = 0.5;
|
||||
options_.mh_jscale = 0.2;
|
||||
options_.mh_tune_jscale.status = false;
|
||||
options_.mh_tune_jscale.guess = .2;
|
||||
options_.mh_tune_jscale.target = .33;
|
||||
options_.mh_tune_jscale.maxiter = 200000;
|
||||
options_.mh_tune_jscale.rho = .7;
|
||||
options_.mh_tune_jscale.stepsize = 1000;
|
||||
options_.mh_tune_jscale.c1 = .02;
|
||||
options_.mh_tune_jscale.c2 = .05;
|
||||
options_.mh_tune_jscale.c3 = 4;
|
||||
options_.mh_init_scale = 2*options_.mh_jscale;
|
||||
options_.mh_mode = 1;
|
||||
options_.mh_nblck = 2;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d686275da142e2d1e1afcdb32785c25f25b5a5a7
|
||||
Subproject commit 1ba023e37d6ee7fc8d393840e42a4542274efbb7
|
|
@ -41,6 +41,7 @@ MODFILES = \
|
|||
estimation/MH_recover/fs2000_recover_2.mod \
|
||||
estimation/MH_recover/fs2000_recover_3.mod \
|
||||
estimation/t_proposal/fs2000_student.mod \
|
||||
estimation/tune_mh_jscale/fs2000.mod \
|
||||
moments/example1_var_decomp.mod \
|
||||
moments/example1_bp_test.mod \
|
||||
moments/test_AR1_spectral_density.mod \
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2004-2018 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/>.
|
||||
*/
|
||||
|
||||
var m P c e W R k d n l gy_obs gp_obs y dA;
|
||||
varexo e_a e_m;
|
||||
|
||||
parameters alp bet gam mst rho psi del;
|
||||
|
||||
alp = 0.33;
|
||||
bet = 0.99;
|
||||
gam = 0.003;
|
||||
mst = 1.011;
|
||||
rho = 0.7;
|
||||
psi = 0.787;
|
||||
del = 0.02;
|
||||
|
||||
model;
|
||||
dA = exp(gam+e_a);
|
||||
log(m) = (1-rho)*log(mst) + rho*log(m(-1))+e_m;
|
||||
-P/(c(+1)*P(+1)*m)+bet*P(+1)*(alp*exp(-alp*(gam+log(e(+1))))*k^(alp-1)*n(+1)^(1-alp)+(1-del)*exp(-(gam+log(e(+1)))))/(c(+2)*P(+2)*m(+1))=0;
|
||||
W = l/n;
|
||||
-(psi/(1-psi))*(c*P/(1-n))+l/n = 0;
|
||||
R = P*(1-alp)*exp(-alp*(gam+e_a))*k(-1)^alp*n^(-alp)/W;
|
||||
1/(c*P)-bet*P*(1-alp)*exp(-alp*(gam+e_a))*k(-1)^alp*n^(1-alp)/(m*l*c(+1)*P(+1)) = 0;
|
||||
c+k = exp(-alp*(gam+e_a))*k(-1)^alp*n^(1-alp)+(1-del)*exp(-(gam+e_a))*k(-1);
|
||||
P*c = m;
|
||||
m-1+d = l;
|
||||
e = exp(e_a);
|
||||
y = k(-1)^alp*n^(1-alp)*exp(-alp*(gam+e_a));
|
||||
gy_obs = dA*y/y(-1);
|
||||
gp_obs = (P/P(-1))*m(-1)/dA;
|
||||
end;
|
||||
|
||||
shocks;
|
||||
var e_a; stderr 0.014;
|
||||
var e_m; stderr 0.005;
|
||||
end;
|
||||
|
||||
steady_state_model;
|
||||
dA = exp(gam);
|
||||
gst = 1/dA;
|
||||
m = mst;
|
||||
khst = ( (1-gst*bet*(1-del)) / (alp*gst^alp*bet) )^(1/(alp-1));
|
||||
xist = ( ((khst*gst)^alp - (1-gst*(1-del))*khst)/mst )^(-1);
|
||||
nust = psi*mst^2/( (1-alp)*(1-psi)*bet*gst^alp*khst^alp );
|
||||
n = xist/(nust+xist);
|
||||
P = xist + nust;
|
||||
k = khst*n;
|
||||
|
||||
l = psi*mst*n/( (1-psi)*(1-n) );
|
||||
c = mst/P;
|
||||
d = l - mst + 1;
|
||||
y = k^alp*n^(1-alp)*gst^alp;
|
||||
R = mst/bet;
|
||||
W = l/n;
|
||||
ist = y-c;
|
||||
q = 1 - d;
|
||||
|
||||
e = 1;
|
||||
|
||||
gp_obs = m/dA;
|
||||
gy_obs = dA;
|
||||
end;
|
||||
|
||||
steady;
|
||||
|
||||
check;
|
||||
|
||||
estimated_params;
|
||||
alp, beta_pdf, 0.356, 0.02;
|
||||
bet, beta_pdf, 0.993, 0.002;
|
||||
gam, normal_pdf, 0.0085, 0.003;
|
||||
mst, normal_pdf, 1.0002, 0.007;
|
||||
rho, beta_pdf, 0.129, 0.100;
|
||||
psi, beta_pdf, 0.65, 0.05;
|
||||
del, beta_pdf, 0.01, 0.005;
|
||||
stderr e_a, inv_gamma_pdf, 0.035449, inf;
|
||||
stderr e_m, inv_gamma_pdf, 0.008862, inf;
|
||||
end;
|
||||
|
||||
varobs gp_obs gy_obs;
|
||||
|
||||
estimation(order=1, datafile='../fsdat_simul', nobs=192, loglinear, mh_replic=20000, mh_nblocks=2, mh_tune_jscale=0.33);
|
||||
|
||||
mhdata = load('fs2000/metropolis/fs2000_mh_history_0.mat');
|
||||
|
||||
if any(abs(mhdata.record.AcceptanceRatio-options_.mh_tune_jscale.target)>options_.mh_tune_jscale.c1)
|
||||
error('Automagic tuning of the MCMC proposal scale parameter did not work as expected!')
|
||||
end
|
Loading…
Reference in New Issue