2015-08-06 08:43:44 +02:00
|
|
|
function oo = model_comparison(ModelNames,ModelPriors,oo,options_,fname)
|
|
|
|
% function oo = model_comparison(ModelNames,ModelPriors,oo,options_,fname)
|
|
|
|
% Conducts Bayesian model comparison. This function computes Odds ratios and
|
|
|
|
% estimates a posterior density over a collection of models.
|
2008-09-26 18:24:13 +02:00
|
|
|
%
|
|
|
|
% INPUTS
|
|
|
|
% ModelNames [string] m*1 cell array of string.
|
2017-05-16 15:10:20 +02:00
|
|
|
% ModelPriors [double] m*1 vector of prior probabilities
|
2015-08-06 08:43:44 +02:00
|
|
|
% oo [struct] Dynare results structure
|
2017-05-16 15:10:20 +02:00
|
|
|
% options_ [struct] Dynare options structure
|
2015-08-06 08:43:44 +02:00
|
|
|
% fname [string] name of the current mod-file
|
2008-09-26 18:24:13 +02:00
|
|
|
%
|
|
|
|
% OUTPUTS
|
2015-08-06 08:43:44 +02:00
|
|
|
% oo [struct] Dynare results structure containing the
|
|
|
|
% results in a field PosteriorOddsTable
|
|
|
|
%
|
|
|
|
% ALGORITHM
|
|
|
|
% See e.g. Koop (2003): Bayesian Econometrics
|
2008-09-26 18:24:13 +02:00
|
|
|
%
|
|
|
|
% SPECIAL REQUIREMENTS
|
|
|
|
% none
|
|
|
|
|
2022-04-13 13:15:19 +02:00
|
|
|
% Copyright © 2007-2018 Dynare Team
|
2008-09-26 18:24:13 +02:00
|
|
|
%
|
|
|
|
% 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
|
2021-06-09 17:33:48 +02:00
|
|
|
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2008-09-26 18:24:13 +02:00
|
|
|
|
|
|
|
NumberOfModels = size(ModelNames,2);
|
|
|
|
|
2013-07-10 17:12:34 +02:00
|
|
|
skipline(2)
|
2008-09-26 18:24:13 +02:00
|
|
|
if isempty(ModelPriors)
|
|
|
|
prior_flag = 0;% empty_prior=0
|
|
|
|
ModelPriors = ones(NumberOfModels,1)/NumberOfModels;
|
|
|
|
else % The prior density has to sum up to one.
|
|
|
|
prior_flag = 1;
|
|
|
|
improper = abs(sum(ModelPriors)-1)>1e-6;
|
|
|
|
if improper
|
2015-08-06 11:01:39 +02:00
|
|
|
if ~all(ModelPriors==1)
|
|
|
|
disp('model_comparison:: The user supplied prior distribution over models is improper...')
|
|
|
|
disp('model_comparison:: The distribution is automatically rescaled!')
|
|
|
|
end
|
2008-09-26 18:24:13 +02:00
|
|
|
ModelPriors=ModelPriors/sum(ModelPriors);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
% The marginal densities are based on Laplace approxiations (default) or
|
|
|
|
% modified harmonic mean estimators.
|
2015-08-06 08:43:44 +02:00
|
|
|
if isfield(options_,'mc_marginal_density')
|
|
|
|
type = options_.mc_marginal_density;
|
|
|
|
if strcmp(type,'laplace') || strcmp(type,'Laplace')
|
2008-09-26 18:24:13 +02:00
|
|
|
type = 'LaplaceApproximation';
|
2017-05-16 15:10:20 +02:00
|
|
|
title = 'Model Comparison (based on Laplace approximation)';
|
|
|
|
elseif strcmp(type,'modifiedharmonicmean') || strcmp(type,'ModifiedHarmonicMean')
|
2015-08-06 08:43:44 +02:00
|
|
|
type = 'ModifiedHarmonicMean';
|
2017-05-16 15:10:20 +02:00
|
|
|
title = 'Model Comparison (based on Modified Harmonic Mean Estimator)';
|
2008-09-26 18:24:13 +02:00
|
|
|
end
|
|
|
|
else
|
|
|
|
type = 'LaplaceApproximation';
|
2017-05-16 15:10:20 +02:00
|
|
|
title = 'Model Comparison (based on Laplace approximation)';
|
2008-09-26 18:24:13 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
% Get the estimated logged marginal densities.
|
|
|
|
MarginalLogDensity = zeros(NumberOfModels,1);
|
|
|
|
ShortModelNames = get_short_names(ModelNames);
|
|
|
|
iname = strmatch(fname,ShortModelNames,'exact');
|
|
|
|
|
|
|
|
for i=1:NumberOfModels
|
|
|
|
if i==iname
|
|
|
|
mstruct.oo_ = oo;
|
|
|
|
else
|
2023-08-29 16:14:50 +02:00
|
|
|
if length(ModelNames{i})>3 && (strcmpi(ModelNames{i}(end-3:end),'.mod') || strcmpi(ModelNames{i}(end-3:end),'.dyn'))
|
2021-07-22 17:46:08 +02:00
|
|
|
mstruct = load([ModelNames{i}(1:end-4) filesep 'Output' ModelNames{i}(1:end-4) '_results.mat' ],'oo_');
|
2008-09-26 18:24:13 +02:00
|
|
|
else
|
2021-07-22 17:46:08 +02:00
|
|
|
mstruct = load([ModelNames{i} filesep 'Output' filesep ModelNames{i} '_results.mat' ],'oo_');
|
2008-09-26 18:24:13 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
try
|
2017-05-16 15:10:20 +02:00
|
|
|
eval(['MarginalLogDensity(i) = mstruct.oo_.MarginalDensity.' type ';'])
|
2008-09-26 18:24:13 +02:00
|
|
|
catch
|
|
|
|
if strcmpi(type,'LaplaceApproximation')
|
2014-07-01 18:50:24 +02:00
|
|
|
if isfield(mstruct.oo_,'mle_mode')
|
|
|
|
disp(['MODEL_COMPARISON: Model comparison is a Bayesian approach and does not support models estimated with ML'])
|
|
|
|
else
|
|
|
|
disp(['MODEL_COMPARISON: I cant''t find the Laplace approximation associated to model ' ModelNames{i}])
|
|
|
|
end
|
2008-09-26 18:24:13 +02:00
|
|
|
return
|
|
|
|
elseif strcmpi(type,'ModifiedHarmonicMean')
|
2014-07-01 18:50:24 +02:00
|
|
|
if isfield(mstruct.oo_,'mle_mode')
|
|
|
|
disp(['MODEL_COMPARISON: Model comparison is a Bayesian approach and does not support models estimated with ML'])
|
|
|
|
else
|
|
|
|
disp(['MODEL_COMPARISON: I cant''t find the modified harmonic mean estimate associated to model ' ModelNames{i}])
|
|
|
|
end
|
2008-09-26 18:24:13 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
% In order to avoid overflow, we divide the numerator and the denominator
|
|
|
|
% of the Posterior Odds Ratio by the largest Marginal Posterior Density
|
|
|
|
lmpd = log(ModelPriors)+MarginalLogDensity;
|
|
|
|
[maxval,k] = max(lmpd);
|
|
|
|
elmpd = exp(lmpd-maxval);
|
|
|
|
|
|
|
|
% Now I display the posterior probabilities.
|
2017-10-10 10:05:59 +02:00
|
|
|
headers = vertcat('Model', ShortModelNames);
|
2008-09-26 18:24:13 +02:00
|
|
|
if prior_flag
|
2017-10-10 10:05:59 +02:00
|
|
|
labels = {'Priors'; 'Log Marginal Density'; 'Bayes Ratio'; 'Posterior Model Probability'};
|
|
|
|
field_labels={'Prior','Log_Marginal_Density','Bayes_Ratio', 'Posterior_Model_Probability'};
|
|
|
|
values = [ModelPriors';MarginalLogDensity';exp(lmpd-lmpd(1))'; elmpd'/sum(elmpd)];
|
2008-09-26 18:24:13 +02:00
|
|
|
else
|
2017-10-10 10:05:59 +02:00
|
|
|
labels = {'Priors'; 'Log Marginal Density'; 'Bayes Ratio'; 'Posterior Odds Ratio'; 'Posterior Model Probability'};
|
2017-05-16 15:10:20 +02:00
|
|
|
field_labels={'Prior','Log_Marginal_Density','Bayes_Ratio','Posterior_Odds_Ratio','Posterior_Model_Probability'};
|
2017-10-10 10:05:59 +02:00
|
|
|
values = [ModelPriors';MarginalLogDensity'; exp(MarginalLogDensity-MarginalLogDensity(1))'; exp(lmpd-lmpd(1))'; elmpd'/sum(elmpd)];
|
2008-09-26 18:24:13 +02:00
|
|
|
end
|
|
|
|
|
2017-10-10 10:05:59 +02:00
|
|
|
for model_iter = 1:NumberOfModels
|
|
|
|
for var_iter = 1:length(labels)
|
|
|
|
oo.Model_Comparison.(headers{1+model_iter}).(field_labels{var_iter}) = values(var_iter, model_iter);
|
2015-08-06 08:44:47 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-10-10 10:05:59 +02:00
|
|
|
dyntable(options_, title, headers, labels, values, 0, 15, 6);
|
2016-05-31 11:42:47 +02:00
|
|
|
if options_.TeX
|
2017-10-10 10:05:59 +02:00
|
|
|
M_temp.fname = fname;
|
|
|
|
M_temp.dname = fname;
|
|
|
|
headers_tex = {};
|
|
|
|
for ii = 1:length(headers)
|
|
|
|
headers_tex = vertcat(headers_tex, strrep(headers{ii}, '_', '\_'));
|
2016-05-31 11:42:47 +02:00
|
|
|
end
|
2017-10-10 10:05:59 +02:00
|
|
|
labels_tex = {};
|
|
|
|
for ii = 1:length(labels)
|
|
|
|
labels_tex = vertcat(labels_tex, strrep(labels{ii},' ', '\ '));
|
2016-05-31 11:42:47 +02:00
|
|
|
end
|
2017-10-10 10:05:59 +02:00
|
|
|
dyn_latex_table(M_temp, options_, title, ['model_comparison', type], headers_tex, labels_tex, values, 0, 16, 6);
|
2016-05-31 11:42:47 +02:00
|
|
|
end
|
2008-09-26 18:24:13 +02:00
|
|
|
|
|
|
|
function name = get_model_name_without_path(modelname)
|
|
|
|
idx = strfind(modelname,'\');
|
|
|
|
if isempty(idx)
|
|
|
|
idx = strfind(modelname,'/');
|
|
|
|
end
|
|
|
|
if isempty(idx)
|
|
|
|
name = modelname;
|
|
|
|
return
|
|
|
|
end
|
|
|
|
name = modelname(idx(end)+1:end);
|
|
|
|
|
|
|
|
|
|
|
|
function name = get_model_name_without_extension(modelname)
|
|
|
|
idx = strfind(modelname,'.mod');
|
|
|
|
if isempty(idx)
|
2014-07-01 18:50:24 +02:00
|
|
|
idx = strfind(modelname,'.dyn');
|
2008-09-26 18:24:13 +02:00
|
|
|
end
|
|
|
|
if isempty(idx)
|
|
|
|
name = modelname;
|
|
|
|
return
|
|
|
|
end
|
|
|
|
name = modelname(1:end-4);
|
|
|
|
|
|
|
|
|
|
|
|
function modellist = get_short_names(modelnames)
|
|
|
|
n = length(modelnames);
|
2017-10-10 10:05:59 +02:00
|
|
|
modellist = cell(n, 1);
|
2008-09-26 18:24:13 +02:00
|
|
|
for i=1:n
|
|
|
|
name = get_model_name_without_extension(modelnames{i});
|
|
|
|
name = get_model_name_without_path(name);
|
2017-10-10 10:05:59 +02:00
|
|
|
modellist(i) = {name};
|
2008-09-26 18:24:13 +02:00
|
|
|
end
|