From a697002a4ee54b28551f3583757b7e0395121db6 Mon Sep 17 00:00:00 2001 From: Willi Mutschler Date: Thu, 14 Jan 2021 10:03:39 +0100 Subject: [PATCH 1/3] MoM: Gradient-based optimizers can use analytical Jacobian for GMM New option analytic_jacobian for mode_compute 1, 3, and 13 --- matlab/method_of_moments/method_of_moments.m | 43 ++++++- .../method_of_moments_objective_function.m | 55 +++++++-- ...ments_objective_function_gradient_helper.m | 62 ++++++++++ .../method_of_moments_standard_errors.m | 3 +- tests/Makefile.am | 1 + .../RBC/RBC_MoM_GMM_gradient_optim.mod | 115 ++++++++++++++++++ 6 files changed, 261 insertions(+), 18 deletions(-) create mode 100644 matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m create mode 100644 tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod diff --git a/matlab/method_of_moments/method_of_moments.m b/matlab/method_of_moments/method_of_moments.m index b931bb057..5ea218c29 100644 --- a/matlab/method_of_moments/method_of_moments.m +++ b/matlab/method_of_moments/method_of_moments.m @@ -93,6 +93,7 @@ function [oo_, options_mom_, M_] = method_of_moments(bayestopt_, options_, oo_, % - [ ] deal with measurement errors (once @wmutschl has implemented this in identification toolbox) % - [ ] improve check for duplicate moments by using the cellfun and unique functions % - [ ] dirname option to save output to different directory not yet implemented +% - [ ] add analytic_jacobian option for mode_compute 4 and 101 % ------------------------------------------------------------------------- % Step 0: Check if required structures and options exist % ------------------------------------------------------------------------- @@ -165,9 +166,10 @@ if strcmp(options_mom_.mom.mom_method,'GMM') error('method_of_moments: perturbation orders higher than 3 are not implemented for GMM estimation, try using SMM.\n'); end options_mom_.mom = set_default_option(options_mom_.mom,'analytic_standard_errors',false); % compute standard errors numerically (0) or analytically (1). Analytical derivatives are only available for GMM. + options_mom_.mom = set_default_option(options_mom_.mom,'analytic_jacobian',false); % use analytic Jacobian in optimization, only available for GMM and gradient-based optimizers end -options_mom_.mom.compute_derivs = false;% flag to compute derivs in objective function (needed for analytic standard errors with GMM) - +% initialize flag to compute derivs in objective function (needed for GMM with either analytic_standard_errors or analytic_jacobian ) +options_mom_.mom.compute_derivs = false; % General options that can be set by the user in the mod file, otherwise default values are provided options_mom_ = set_default_option(options_mom_,'dirname',M_.dname); % specify directory in which to store estimation output [not yet working] @@ -330,6 +332,10 @@ options_mom_.analytic_derivation_mode = 0; % needed by get_perturbation_params_d options_mom_.vector_output= false; % specifies whether the objective function returns a vector +optimizer_vec=[options_mom_.mode_compute;num2cell(options_mom_.additional_optimizer_steps)]; % at each stage one can possibly use different optimizers sequentially + +analytic_jacobian_optimizers = [1, 3, 13]; %these are currently supported, see to-do list + % ------------------------------------------------------------------------- % Step 1d: Other options that need to be initialized % ------------------------------------------------------------------------- @@ -708,6 +714,7 @@ end % Step 6: checks for objective function at initial parameters % ------------------------------------------------------------------------- objective_function = str2func('method_of_moments_objective_function'); + try % Check for NaN or complex values of moment-distance-funtion evaluated % at initial parameters and identity weighting matrix @@ -757,7 +764,7 @@ end if options_mom_.mom.penalized_estimator fprintf('\n - penalized estimation using deviation from prior mean and weighted with prior precision'); end -optimizer_vec=[options_mom_.mode_compute;num2cell(options_mom_.additional_optimizer_steps)]; % at each stage one can possibly use different optimizers sequentially + for i = 1:length(optimizer_vec) if i == 1 str = '- optimizer (mode_compute'; @@ -807,6 +814,9 @@ for i = 1:length(optimizer_vec) if options_mom_.silent_optimizer fprintf(' (silent)'); end + if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_jacobian && ismember(optimizer_vec{i},analytic_jacobian_optimizers) + fprintf(' (using analytical Jacobian)'); + end end fprintf('\n - perturbation order: %d', options_mom_.order) if options_mom_.order > 1 && options_mom_.pruning @@ -828,6 +838,7 @@ if size(options_mom_.mom.weighting_matrix,1)>1 && ~(any(strcmpi('diagonal',optio fprintf('\nYou did not specify the use of an optimal or diagonal weighting matrix. There is no point in running an iterated method of moments.\n') end +optim_opt0 = options_mom_.optim_opt; % store original options set by user for stage_iter=1:size(options_mom_.mom.weighting_matrix,1) fprintf('Estimation stage %u\n',stage_iter); Woptflag = false; @@ -873,16 +884,36 @@ for stage_iter=1:size(options_mom_.mom.weighting_matrix,1) end for optim_iter= 1:length(optimizer_vec) + options_mom_.current_optimizer = optimizer_vec{optim_iter}; if optimizer_vec{optim_iter}==0 xparam1=xparam0; %no minimization, evaluate objective at current values fval = feval(objective_function, xparam1, Bounds, oo_, estim_params_, M_, options_mom_); else if optimizer_vec{optim_iter}==13 - options_mom_.vector_output = true; + options_mom_.vector_output = true; else - options_mom_.vector_output = false; + options_mom_.vector_output = false; end - [xparam1, fval, exitflag] = dynare_minimize_objective(objective_function, xparam0, optimizer_vec{optim_iter}, options_mom_, [Bounds.lb Bounds.ub], bayestopt_laplace.name, bayestopt_laplace, [],... + if strcmp(options_mom_.mom.mom_method,'GMM') && options_mom_.mom.analytic_jacobian && ismember(optimizer_vec{optim_iter},analytic_jacobian_optimizers) %do this only for gradient-based optimizers + options_mom_.mom.compute_derivs = true; + objective_function1 = str2func('method_of_moments_objective_function_gradient_helper'); + switch optimizer_vec{optim_iter} + case 1 + options_mom_.optim_opt = [optim_opt0, ',''GradObj'',''on''']; % make sure GradObj option is on for fmincon + case 3 + options_mom_.optim_opt = [optim_opt0, ',''GradObj'',''on''']; % make sure GradObj option is on for fmincon + case 13 + options_mom_.optim_opt = [optim_opt0, ',''Jacobian'',''on''']; % make sure Jacobian option is on for lsqnonlin + end + if strcmp(options_mom_.optim_opt(1),',') + options_mom_.optim_opt(1) = []; %remove the comma if optim_opt was empty + end + else + options_mom_.mom.compute_derivs = false; + objective_function1 = objective_function; + end + + [xparam1, fval, exitflag] = dynare_minimize_objective(objective_function1, xparam0, optimizer_vec{optim_iter}, options_mom_, [Bounds.lb Bounds.ub], bayestopt_laplace.name, bayestopt_laplace, [],... Bounds, oo_, estim_params_, M_, options_mom_); if options_mom_.vector_output fval = fval'*fval; diff --git a/matlab/method_of_moments/method_of_moments_objective_function.m b/matlab/method_of_moments/method_of_moments_objective_function.m index 41c3dcc79..3a8548e76 100644 --- a/matlab/method_of_moments/method_of_moments_objective_function.m +++ b/matlab/method_of_moments/method_of_moments_objective_function.m @@ -1,4 +1,4 @@ -function [fval, info, exit_flag, junk1, junk2, oo_, M_, options_mom_] = method_of_moments_objective_function(xparam1, Bounds, oo_, estim_params_, M_, options_mom_) +function [fval, info, exit_flag, junk1, junk2, oo_, M_, options_mom_, df] = method_of_moments_objective_function(xparam1, Bounds, oo_, estim_params_, M_, options_mom_) % [fval, info, exit_flag, junk1, junk2, oo_, M_, options_mom_] = method_of_moments_objective_function(xparam1, Bounds, oo_, estim_params_, M_, options_mom_) % ------------------------------------------------------------------------- % This function evaluates the objective function for GMM/SMM estimation @@ -21,9 +21,12 @@ function [fval, info, exit_flag, junk1, junk2, oo_, M_, options_mom_] = method_o % - mom.model_moments [numMom x 1] vector with model moments % - mom.Q value of the quadratic form of the moment difference % o M_: Matlab's structure describing the model +% o options_mom_: structure information about all settings (specified by the user, preprocessor, and taken from global options_) +% o df: analytical parameter Jacobian of the quadratic form of the moment difference (for GMM only) % ------------------------------------------------------------------------- % This function is called by % o method_of_moments.m +% o dynare_minimize_objective.m % ------------------------------------------------------------------------- % This function calls % o check_bounds_and_definiteness_estimation @@ -56,7 +59,15 @@ function [fval, info, exit_flag, junk1, junk2, oo_, M_, options_mom_] = method_o %------------------------------------------------------------------------------ % 0. Initialization of the returned variables and others... %------------------------------------------------------------------------------ - +if options_mom_.vector_output == 1 + if options_mom_.mom.penalized_estimator + df = nan(size(oo_.mom.data_moments,1)+length(xparam1),length(xparam1)); + else + df = nan(size(oo_.mom.data_moments,1),length(xparam1)); + end +else + df = nan(1,length(xparam1)); +end junk1 = []; junk2 = []; @@ -112,7 +123,7 @@ if strcmp(options_mom_.mom.mom_method,'GMM') %-------------------------------------------------------------------------- % 3. Set up pruned state-space system and compute model moments %-------------------------------------------------------------------------- - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) indpmodel = []; %initialize index for model parameters if ~isempty(estim_params_.param_vals) indpmodel = estim_params_.param_vals(:,1); %values correspond to parameters declaration order, row number corresponds to order in estimated_params @@ -146,7 +157,7 @@ if strcmp(options_mom_.mom.mom_method,'GMM') E_y = pruned_state_space.E_y; E_y_nbr = nnz(options_mom_.mom.index.E_y); oo_.mom.model_moments(offset+1:E_y_nbr,1) = E_y(options_mom_.mom.index.E_y); - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) oo_.mom.model_moments_params_derivs(offset+1:E_y_nbr,:) = pruned_state_space.dE_y(options_mom_.mom.index.E_y,:); end offset = offset + E_y_nbr; @@ -156,12 +167,12 @@ if strcmp(options_mom_.mom.mom_method,'GMM') if isfield(options_mom_.mom.index,'E_yy') && nnz(options_mom_.mom.index.E_yy) > 0 if options_mom_.prefilter E_yy = pruned_state_space.Var_y; - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) dE_yy = pruned_state_space.dVar_y; end else E_yy = pruned_state_space.Var_y + pruned_state_space.E_y*pruned_state_space.E_y'; - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) dE_yy = pruned_state_space.dVar_y; for jp=1:totparam_nbr dE_yy(:,:,jp) = dE_yy(:,:,jp) + pruned_state_space.dE_y(:,jp)*pruned_state_space.E_y' + pruned_state_space.E_y*pruned_state_space.dE_y(:,jp)'; @@ -170,7 +181,7 @@ if strcmp(options_mom_.mom.mom_method,'GMM') end E_yy_nbr = nnz(tril(options_mom_.mom.index.E_yy)); oo_.mom.model_moments(offset+(1:E_yy_nbr),1) = E_yy(tril(options_mom_.mom.index.E_yy)); - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) oo_.mom.model_moments_params_derivs(offset+(1:E_yy_nbr),:) = reshape(dE_yy(repmat(tril(options_mom_.mom.index.E_yy),[1 1 totparam_nbr])),E_yy_nbr,totparam_nbr); end offset = offset + E_yy_nbr; @@ -179,12 +190,12 @@ if strcmp(options_mom_.mom.mom_method,'GMM') if isfield(options_mom_.mom.index,'E_yyt') && nnz(options_mom_.mom.index.E_yyt) > 0 if options_mom_.prefilter E_yyt = pruned_state_space.Var_yi; - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) dE_yyt = pruned_state_space.dVar_yi; end else E_yyt = pruned_state_space.Var_yi + repmat(pruned_state_space.E_y*pruned_state_space.E_y',[1 1 size(pruned_state_space.Var_yi,3)]); - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) dE_yyt = pruned_state_space.dVar_yi; for jp=1:totparam_nbr dE_yyt(:,:,:,jp) = dE_yyt(:,:,:,jp) + repmat(pruned_state_space.dE_y(:,jp)*pruned_state_space.E_y',[1 1 size(pruned_state_space.Var_yi,3)])... @@ -194,7 +205,7 @@ if strcmp(options_mom_.mom.mom_method,'GMM') end E_yyt_nbr = nnz(options_mom_.mom.index.E_yyt); oo_.mom.model_moments(offset+(1:E_yyt_nbr),1) = E_yyt(options_mom_.mom.index.E_yyt); - if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_standard_errors + if options_mom_.mom.compute_derivs && ( options_mom_.mom.analytic_standard_errors || options_mom_.mom.analytic_jacobian ) oo_.mom.model_moments_params_derivs(offset+(1:E_yyt_nbr),:) = reshape(dE_yyt(repmat(options_mom_.mom.index.E_yyt,[1 1 1 totparam_nbr])),E_yyt_nbr,totparam_nbr); end end @@ -265,6 +276,30 @@ else end end +if options_mom_.mom.compute_derivs && options_mom_.mom.analytic_jacobian + if options_mom_.mom.penalized_estimator + dxparam1 = eye(length(xparam1)); + end + + for jp=1:length(xparam1) + dmoments_difference = - oo_.mom.model_moments_params_derivs(:,jp); + dresiduals = sqrt(options_mom_.mom.weighting_matrix_scaling_factor)*oo_.mom.Sw*dmoments_difference; + + if options_mom_.vector_output == 1 % lsqnonlin requires vector output + if options_mom_.mom.penalized_estimator + df(:,jp)=[dresiduals;dxparam1(:,jp)./sqrt(diag(oo_.prior.variance))]; + else + df(:,jp) = dresiduals; + end + else + df(:,jp) = dresiduals'*residuals + residuals'*dresiduals; + if options_mom_.mom.penalized_estimator + df(:,jp)=df(:,jp)+(dxparam1(:,jp))'/oo_.prior.variance*(xparam1-oo_.prior.mean)+(xparam1-oo_.prior.mean)'/oo_.prior.variance*(dxparam1(:,jp)); + end + end + end +end + end%main function end diff --git a/matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m b/matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m new file mode 100644 index 000000000..cc30f2665 --- /dev/null +++ b/matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m @@ -0,0 +1,62 @@ +function [out1, out2] = method_of_moments_objective_function_gradient_helper(xparam1, Bounds, oo_, estim_params_, M_, options_mom_) +% [out1, out2] = method_of_moments_objective_function_gradient_helper(xparam1, Bounds, oo_, estim_params_, M_, options_mom_) +% ------------------------------------------------------------------------- +% This helper function evaluates the objective function for GMM/SMM estimation and +% outputs the function value fval at first and the gradient df at second place, +% needed for gradient-based optimizers if analytic_jacobian option is set +% ========================================================================= +% INPUTS +% o xparam1: current value of estimated parameters as returned by set_prior() +% o Bounds: structure containing parameter bounds +% o oo_: structure for results +% o estim_params_: structure describing the estimated_parameters +% o M_ structure describing the model +% o options_mom_: structure information about all settings (specified by the user, preprocessor, and taken from global options_) +% ------------------------------------------------------------------------- +% OUTPUTS: dependent on the optimizer calling this function, see below +% ------------------------------------------------------------------------- +% This function calls +% o method_of_moments_objective_function.m +% ========================================================================= +% Copyright (C) 2020-2021 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 . +% ------------------------------------------------------------------------- +% This function is called by +% o method_of_moments.m +% o dynare_minimize_objective.m +% ------------------------------------------------------------------------- +% This function calls +% o method_of_moments_objective_function +% ------------------------------------------------------------------------- +% Author(s): +% o Willi Mutschler (willi@mutschler.eu) +% ========================================================================= +[fval, info, exit_flag, junk1, junk2, oo_, M_, options_mom_, df] = method_of_moments_objective_function(xparam1, Bounds, oo_, estim_params_, M_, options_mom_); + +switch options_mom_.current_optimizer + case 1 %fmincon + out1=fval; out2=df; + case 3 %fminunc + out1=fval; out2=df; + case 13 %lsqnonlin + out1=fval; out2=df; + otherwise + error('Method of Moments: analytic_jacobian option is currently only supported by mode_compute 1, 3 and 13'); +end + +end%main function end + diff --git a/matlab/method_of_moments/method_of_moments_standard_errors.m b/matlab/method_of_moments/method_of_moments_standard_errors.m index 459f583f7..ea302d52d 100644 --- a/matlab/method_of_moments/method_of_moments_standard_errors.m +++ b/matlab/method_of_moments/method_of_moments_standard_errors.m @@ -25,8 +25,7 @@ function [SE_values, Asympt_Var] = method_of_moments_standard_errors(xparam, obj % This function calls: % o get_the_name % o get_error_message -% o GMM_objective_function -% o SMM_objective_function.m +% o method_of_moments_objective_function % o method_of_moments_optimal_weighting_matrix % ========================================================================= % Copyright (C) 2020-2021 Dynare Team diff --git a/tests/Makefile.am b/tests/Makefile.am index ef844e1bd..37825c1cc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -56,6 +56,7 @@ MODFILES = \ estimation/method_of_moments/RBC/RBC_MoM_SMM_ME.mod \ estimation/method_of_moments/RBC/RBC_MoM_prefilter.mod \ estimation/method_of_moments/RBC/RBC_MoM_optimizer.mod \ + estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod \ estimation/method_of_moments/AFVRR/AFVRR_M0.mod \ estimation/method_of_moments/AFVRR/AFVRR_MFB.mod \ estimation/method_of_moments/AFVRR/AFVRR_MFB_RRA.mod \ diff --git a/tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod b/tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod new file mode 100644 index 000000000..a0c86593b --- /dev/null +++ b/tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod @@ -0,0 +1,115 @@ +% Test whether gradient-based optimizers are able to use analytical +% Jacobian of moments in GMM estimation +% +% Copyright (C) 2021 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 . +% ========================================================================= +@#include "RBC_MoM_common.inc" + +shocks; +var u_a; stderr 0.0072; +end; + +varobs c iv n; + +%-------------------------------------------------------------------------- +% Method of Moments Estimation +%-------------------------------------------------------------------------- +matched_moments; +c; +n; +iv; +c*c; +c*iv; +iv*n; +iv*iv; +n*c; +n*n; +c*c(-1); +n*n(-1); +iv*iv(-1); +end; + + +@#for estimParams in [0, 1, 2] + clear estim_params_; + + @#if estimParams == 0 + estimated_params; + %DELTA, 0.025; + %BETTA, 0.984; + %B, 0.5; + %ETAc, 2; + ALFA, 0.667; + RHOA, 0.979; + stderr u_a, 0.0072; + end; + @#endif + + @#if estimParams == 1 + estimated_params; + %DELTA, , 0, 1; + %BETTA, , 0, 1; + %B, , 0, 1; + %ETAc, , 0, 10; + ALFA, , 0, 1; + RHOA, , 0, 1; + stderr u_a, , 0, 1; + end; + @#endif + + @#if estimParams == 2 + estimated_params; + %DELTA, 0.025, 0, 1, normal_pdf, 0.02, 0.5; + %BETTA, 0.98, 0, 1, beta_pdf, 0.90, 0.25; + %B, 0.45, 0, 1, normal_pdf, 0.40, 0.5; + %ETAl, 1, 0, 10, normal_pdf, 0.25, 0.0.1; + %ETAc, 1.8, 0, 10, normal_pdf, 1.80, 0.5; + ALFA, 0.65, 0, 1, normal_pdf, 0.60, 0.5; + RHOA, 0.95, 0, 1, normal_pdf, 0.90, 0.5; + stderr u_a, 0.01, 0, 1, normal_pdf, 0.01, 0.5; + %THETA, 3.48, 0, 10, normal_pdf, 0.25, 0.0.1; + end; + @#endif + + estimated_params_init(use_calibration); + end; + %1 3 13 + @#for optimizer in [1,3, 13] + method_of_moments( + mom_method = GMM % method of moments method; possible values: GMM|SMM + , datafile = 'RBC_Andreasen_Data_2.mat' % name of filename with data + , order = 2 % order of Taylor approximation in perturbation + , weighting_matrix = ['OPTIMAL'] % weighting matrix in moments distance objective function; possible values: OPTIMAL|IDENTITY_MATRIX|DIAGONAL|filename. Size of cell determines stages in iterated estimation, e.g. two state with ['DIAGONAL','OPTIMAL'] + , nodisplay + , nograph + , mode_compute = @{optimizer} % specifies the optimizer for minimization of moments distance + %, additional_optimizer_steps = [1 3 13] +% , optim = ('TolFun', 1e-6 +% ,'TolX', 1e-6 +% ,'MaxIter', 3000 +% ,'MaxFunEvals', 1D6 +% ,'UseParallel' , 1 +% ,'Jacobian' , 'on' +% ,'GradObj','on' +% ) % a list of NAME and VALUE pairs to set options for the optimization routines. Available options depend on mode_compute + , silent_optimizer % run minimization of moments distance silently without displaying results or saving files in between + , analytic_jacobian + ); + @#endfor + +@#endfor \ No newline at end of file From 0a880825a1d079c8925ead47a4fa89caa00e12ab Mon Sep 17 00:00:00 2001 From: Willi Mutschler Date: Thu, 14 Jan 2021 10:04:10 +0100 Subject: [PATCH 2/3] MoM: Testsuite fixes for Octave --- .../method_of_moments/AFVRR/AFVRR_M0.mod | 2 ++ .../method_of_moments/AFVRR/AFVRR_MFB.mod | 2 ++ .../method_of_moments/AFVRR/AFVRR_MFB_RRA.mod | 2 ++ .../RBC/RBC_MoM_GMM_gradient_optim.mod | 16 +++++++++++++--- .../method_of_moments/RBC/RBC_MoM_optimizer.mod | 11 +++++++++++ 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/tests/estimation/method_of_moments/AFVRR/AFVRR_M0.mod b/tests/estimation/method_of_moments/AFVRR/AFVRR_M0.mod index 8e51ac513..cd19168cc 100644 --- a/tests/estimation/method_of_moments/AFVRR/AFVRR_M0.mod +++ b/tests/estimation/method_of_moments/AFVRR/AFVRR_M0.mod @@ -256,11 +256,13 @@ dev_Q = AndreasenEtAl.Q@{orderApp} - oo_.mom.Q; dev_datamoments = str2double(AndreasenEtAl.moments@{orderApp}(:,5)) - oo_.mom.data_moments; dev_modelmoments = str2double(AndreasenEtAl.moments@{orderApp}(:,6)) - oo_.mom.model_moments; +if ~isoctave %there is no table command in Octave table([AndreasenEtAl.Q@{orderApp} ; str2double(AndreasenEtAl.moments@{orderApp}(:,5)) ; str2double(AndreasenEtAl.moments@{orderApp}(:,6))],... [oo_.mom.Q ; oo_.mom.data_moments ; oo_.mom.model_moments ],... [dev_Q ; dev_datamoments ; dev_modelmoments ],... 'VariableNames', {'Andreasen et al', 'Dynare', 'dev'},... 'RowNames', ['Q'; strcat('Data_', M_.matched_moments(:,4)); strcat('Model_', M_.matched_moments(:,4))]) +end if norm(dev_modelmoments)> 1e-4 error('Something wrong in the computation of moments at order @{orderApp}') diff --git a/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB.mod b/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB.mod index 450739ad3..535dc8470 100644 --- a/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB.mod +++ b/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB.mod @@ -257,11 +257,13 @@ dev_Q = AndreasenEtAl.Q@{orderApp} - oo_.mom.Q; dev_datamoments = str2double(AndreasenEtAl.moments@{orderApp}(:,5)) - oo_.mom.data_moments; dev_modelmoments = str2double(AndreasenEtAl.moments@{orderApp}(:,6)) - oo_.mom.model_moments; +if ~isoctave %there is no table command in Octave table([AndreasenEtAl.Q@{orderApp} ; str2double(AndreasenEtAl.moments@{orderApp}(:,5)) ; str2double(AndreasenEtAl.moments@{orderApp}(:,6))],... [oo_.mom.Q ; oo_.mom.data_moments ; oo_.mom.model_moments ],... [dev_Q ; dev_datamoments ; dev_modelmoments ],... 'VariableNames', {'Andreasen et al', 'Dynare', 'dev'},... 'RowNames', ['Q'; strcat('Data_', M_.matched_moments(:,4)); strcat('Model_', M_.matched_moments(:,4))]) +end if norm(dev_modelmoments)> 1e-4 warning('Something wrong in the computation of moments at order @{orderApp}') diff --git a/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB_RRA.mod b/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB_RRA.mod index 9c069d3a3..d86c7b353 100644 --- a/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB_RRA.mod +++ b/tests/estimation/method_of_moments/AFVRR/AFVRR_MFB_RRA.mod @@ -256,11 +256,13 @@ dev_Q = AndreasenEtAl.Q@{orderApp} - oo_.mom.Q; dev_datamoments = str2double(AndreasenEtAl.moments@{orderApp}(:,5)) - oo_.mom.data_moments; dev_modelmoments = str2double(AndreasenEtAl.moments@{orderApp}(:,6)) - oo_.mom.model_moments; +if ~isoctave %there is no table command in Octave table([AndreasenEtAl.Q@{orderApp} ; str2double(AndreasenEtAl.moments@{orderApp}(:,5)) ; str2double(AndreasenEtAl.moments@{orderApp}(:,6))],... [oo_.mom.Q ; oo_.mom.data_moments ; oo_.mom.model_moments ],... [dev_Q ; dev_datamoments ; dev_modelmoments ],... 'VariableNames', {'Andreasen et al', 'Dynare', 'dev'},... 'RowNames', ['Q'; strcat('Data_', M_.matched_moments(:,4)); strcat('Model_', M_.matched_moments(:,4))]) +end if norm(dev_modelmoments)> 1e-4 warning('Something wrong in the computation of moments at order @{orderApp}') diff --git a/tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod b/tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod index a0c86593b..39a58b674 100644 --- a/tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod +++ b/tests/estimation/method_of_moments/RBC/RBC_MoM_GMM_gradient_optim.mod @@ -88,8 +88,13 @@ end; estimated_params_init(use_calibration); end; - %1 3 13 - @#for optimizer in [1,3, 13] + + @#for optimizer in [1, 3, 13] + @#if estimParams == 2 && optimizer == 13 + %skip due to buggy behavior in Octave + if ~isoctave + @#endif + method_of_moments( mom_method = GMM % method of moments method; possible values: GMM|SMM , datafile = 'RBC_Andreasen_Data_2.mat' % name of filename with data @@ -110,6 +115,11 @@ end; , silent_optimizer % run minimization of moments distance silently without displaying results or saving files in between , analytic_jacobian ); - @#endfor + + @#if estimParams == 2 && optimizer == 13 + %skip due to buggy behavior in Octave + end + @#endif + @#endfor @#endfor \ No newline at end of file diff --git a/tests/estimation/method_of_moments/RBC/RBC_MoM_optimizer.mod b/tests/estimation/method_of_moments/RBC/RBC_MoM_optimizer.mod index 08b1ed882..b9d9dc96c 100644 --- a/tests/estimation/method_of_moments/RBC/RBC_MoM_optimizer.mod +++ b/tests/estimation/method_of_moments/RBC/RBC_MoM_optimizer.mod @@ -118,6 +118,12 @@ options_.solveopt.TolXConstraint=1e-3; end; @#for optimizer in OPTIMIZERS + + @#if estimParams == 2 && optimizer == 13 + %skip due to buggy behavior in Octave + if ~isoctave + @#endif + method_of_moments( mom_method = GMM % method of moments method; possible values: GMM|SMM , datafile = 'RBC_Andreasen_Data_2.mat' % name of filename with data @@ -139,6 +145,11 @@ options_.solveopt.TolXConstraint=1e-3; @#endif %, silent_optimizer % run minimization of moments distance silently without displaying results or saving files in between ); + + @#if estimParams == 2 && optimizer == 13 + %skip due to buggy behavior in Octave + end + @#endif @#endfor @#endfor From 52a57eaf60618915d0c777100ad8a6bf60a0877e Mon Sep 17 00:00:00 2001 From: Willi Mutschler Date: Thu, 14 Jan 2021 14:17:55 +0100 Subject: [PATCH 3/3] MoM: Remove duplicate check in gradient helper function --- ..._of_moments_objective_function_gradient_helper.m | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m b/matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m index cc30f2665..f1c88af49 100644 --- a/matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m +++ b/matlab/method_of_moments/method_of_moments_objective_function_gradient_helper.m @@ -47,16 +47,9 @@ function [out1, out2] = method_of_moments_objective_function_gradient_helper(xpa % ========================================================================= [fval, info, exit_flag, junk1, junk2, oo_, M_, options_mom_, df] = method_of_moments_objective_function(xparam1, Bounds, oo_, estim_params_, M_, options_mom_); -switch options_mom_.current_optimizer - case 1 %fmincon - out1=fval; out2=df; - case 3 %fminunc - out1=fval; out2=df; - case 13 %lsqnonlin - out1=fval; out2=df; - otherwise - error('Method of Moments: analytic_jacobian option is currently only supported by mode_compute 1, 3 and 13'); -end +% mode_compute=1|3|13 require the gradient as second output argument +out1=fval; +out2=df; end%main function end