Give access to more than one optimizer in PAC estimation (NLS).

Default is to use csminwel optimizer (because it seems to do the job and does
not rely on the Mathworks toolbox).
time-shift
Stéphane Adjemian(Charybdis) 2018-09-13 15:21:54 +02:00
parent 2e547edd26
commit 2437d7034e
1 changed files with 121 additions and 6 deletions

View File

@ -1,4 +1,4 @@
function nls(eqname, params, data, range)
function nls(eqname, params, data, range, optimizer, varargin)
% Estimates the parameters of a PAC equation by Nonlinear Least Squares.
%
@ -7,6 +7,12 @@ function nls(eqname, params, data, range)
% - params [struct] Describes the parameters to be estimated.
% - data [dseries] Database for the estimation
% - range [dates] Range of dates for the estimation.
% - optimizer [string] Set the optimization algorithm. Possible values
% are 'fmincon', 'fminunc', 'csminwel',
% 'fminsearch', 'simplex' and
% 'annealing'. Default is 'csminwel'.
% - varargin List of key/value pairs, each key must be a
% string and values can be strings or real numbers.
%
% OUTPUTS
% - none
@ -21,6 +27,20 @@ function nls(eqname, params, data, range)
% the variables appearing in the estimated equation. The residual of the
% equation must have NaN values in the object.
% [4] It is assumed that the residual is additive.
% [5] If the used optimization routines handles inequalities over the
% estimated parameters, we impose the positivity of the error correction parameter.
%
% EXAMPLE
%
% pac.estimate.nls('zpac', eparams, dbase, dates('2003Q1'):dates('2016Q3'),'fminunc', 'MaxIter', 50);
%
% where zpac is the name of the PAC equation, eparams is a structure
% containing the guess values for the estimated parameters (in each field),
% dbase is a dseries object containing the data,
% dates('2003Q1'):dates('2016Q3') is the range of the sample used for
% estimation, 'fminunc' is the name of the optimization algorithm (this one
% is available only if the matylab optimization toolbox is installed), the
% remaining inputs are the options (key/value) passed to the optimizers.
% Copyright (C) 2018 Dynare Team
%
@ -39,7 +59,7 @@ function nls(eqname, params, data, range)
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
global M_ oo_
global M_ oo_ options_
[pacmodl, lhs, rhs, pnames, enames, xnames, pid, eid, xid, ~, ipnames_, params, data, islaggedvariables] = ...
pac.estimate.init(M_, oo_, eqname, params, data, range);
@ -96,11 +116,16 @@ end
% Create a routine for evaluating the sum of squared residuals
ssrfun = ['ssr_' eqname];
fid = fopen([ssrfun '.m'], 'w');
fprintf(fid, 'function s = %s(params, data, DynareModel, DynareOutput)\n', ssrfun);
fprintf(fid, 'function [s, fake1, fake2, fake3, fake4] = %s(params, data, DynareModel, DynareOutput)\n', ssrfun);
fprintf(fid, '\n');
fprintf(fid, '%% Evaluates the sum of square residuals for equation %s.\n', eqname);
fprintf(fid, '%% File created by Dynare (%s).\n', datestr(datetime));
fprintf(fid, '\n');
fprintf(fid, 'fake1 = 0;\n');
fprintf(fid, 'fake2 = [];\n');
fprintf(fid, 'fake3 = [];\n');
fprintf(fid, 'fake4 = [];\n');
fprintf(fid, '\n');
for i=1:length(ipnames_)
fprintf(fid, 'DynareModel.params(%u) = params(%u);\n', ipnames_(i), i);
end
@ -123,11 +148,101 @@ ssr = @(p) feval(['ssr_' eqname], p, DATA, M_, oo_);
% Set initial condition.
params0 = cell2mat(struct2cell(params));
% Set optimization options.
options = optimset('Display','iter');
% Set defaults for optimizers
bounds = [];
parameter_names = [];
% Set optimizer routine.
if nargin<5 || isempty(optimizer)
% Use csminwel by default.
minalgo = 4;
else
switch optimizer
case 'fmincon'
minalgo = 1;
bounds = ones(length(params0),1)*[-10,10];
bounds(strcmp(fieldnames(params), M_.param_names(M_.pac.pacman.ec.params)),1) = .0;
case 'fminunc'
minalgo = 3;
case 'csminwel'
minalgo = 4;
case 'fminsearch'
minalgo = 7;
case 'simplex'
minalgo = 8;
case 'annealing'
minalgo = 2;
bounds = ones(length(params0),1)*[-10,10];
bounds(strcmp(fieldnames(params), M_.param_names(M_.pac.pacman.ec.params)),1) = .0;
parameter_names = fieldnames(params);
case 'particleswarm'
minalgo = 12;
bounds = ones(length(params0),1)*[-10,10];
bounds(strcmp(fieldnames(params), M_.param_names(M_.pac.pacman.ec.params)),1) = .0;
parameter_names = fieldnames(params);
otherwise
msg = sprintf('%s is not an implemented optimization routine.\n', optimizer);
msg = sprintf('%sAvailable algorithms are:\n', msg);
msg = sprintf('%s - %s\n', msg, 'fmincon');
msg = sprintf('%s - %s\n', msg, 'fminunc');
msg = sprintf('%s - %s\n', msg, 'csminwel');
msg = sprintf('%s - %s\n', msg, 'fminsearch');
msg = sprintf('%s - %s\n', msg, 'simplex');
msg = sprintf('%s - %s\n', msg, 'annealing');
error(msg)
end
end
% Set options if provided as input arguments to nls routine.
oldopt = options_.optim_opt;
if nargin>5
if mod(nargin-5, 2)
error('Options must come by key/value pairs.')
end
i = 1;
opt = '';
while i<nargin-5
if i==1
opt = sprintf('''%s'',', varargin{i});
else
opt = sprintf('%s,''%s'',', opt, varargin{i});
end
if isnumeric(varargin{i+1})
if (i+1)==(nargin-5)
opt = sprintf('%s%s', opt, varargin{i+1});
else
opt = sprintf('%s%s,', opt, varargin{i+1});
end
else
if (i+1)==(nargin-5)
opt = sprintf('%s''%s''', opt, varargin{i+1});
else
opt = sprintf('%s''%s'',', opt, varargin{i+1});
end
end
i = i+2;
end
options_.optim_opt = opt;
else
options_.optim_opt = [];
end
if nargin<5
% If default optimization algorithm is used (csminwel), do not print
% iterations.
options_.optim_opt = '''verbosity'',0';
end
% Estimate the parameters by minimizing the sum of squared residuals.
pparams1 = fminunc(ssr, params0, options);
[pparams1, SSR, exitflag] = dynare_minimize_objective(ssr, params0, ...
minalgo, ...
options_, ...
bounds, ...
parameter_names, ...
[], ...
[]);
options_.optim_opt = oldopt;
% Update M_.params
for i=1:length(pparams1)