% Matlab code for demonstarting cross-validation with BUGS % % Author: Aki Vehtari % Make indeces for cross-validation. Here we use n-fold-CV because % it does not take much more time than 10-fold-CV, if n would be % large, it would be trivial to change this to 10-fold-CV ii=1:21; for i=1:21 itst{i}=ii(i); itr{i}=setdiff(ii,itst{i}); end % This is used to simplify pairwise comparison of the models wwc=dirrand(n,1000); % load data d=load('stacks.dat'); [n,p]=size(d);p=p-1; % reserve memory for arrays lps=zeros(1000,N); lpss=zeros(1000,N,10); % make cross-validation for all 5 models for mi=1:5 fprintf('%d: ',mi); % First make model with full data % (to get full posterior and to make bias correction) mat2bugs('stacks_dat.txt','Y',d(:,1),'x',d(:,2:end),'p',p,'N',n); unix(sprintf('echo "check(''Y:/cv_vs_dic/stacks/WinBUGS/stacks%d_bug.txt'')" > stacks_scr.txt ',mi)); unix('cat stackstr_scr.txt >> stacks_scr.txt'); unix(['wine /proj/ave/c/WinBUGS/WinBUGS14.exe /PAR "Y:/cv_vs_dic/stacks/WinBUGS/stacks_scr.txt" 2> /dev/null' ]); S=bugs2mat('bugsIndex.txt','bugs1.txt'); ds=S.ds; % BUGS computed predictive deviances trlps=ds/-2; % We like to handle predictive likelihoods for i1=1:length(itr) fprintf('.'); % And CV models mat2bugs('stackscv_dat.txt','Y',d(itr{i1},1),'x',d(itr{i1},2:end),'Y2',d(itst{i1},1),1,'x2',d(itst{i1},2:end),'p',p,'N',length(itr{i1}),'N2',length(itst{i1})); unix(sprintf('echo "check(''Y:/cv_vs_dic/stacks/WinBUGS/stacks%dcv_bug.txt'')" > stacks_scr.txt ',mi)); unix('cat stackscv_scr.txt >> stacks_scr.txt'); unix(['wine /proj/ave/c/WinBUGS/WinBUGS14.exe /PAR "Y:/cv_vs_dic/stacks/WinBUGS/stacks_scr.txt" 2> /dev/null']); S=bugs2mat('bugsIndex.txt','bugs1.txt'); lps(:,itst{i1})=S.ds2/-2; % CV predictive lpss(:,itr{i1},i1)=S.ds/-2; % For bias correction lpss(:,itst{i1},i1)=S.ds2/-2;% For bias correction end fprintf('\n'); % Mean of the expected utility % for posterior predictive (train) trlC=sum(log(mean(exp(trlps)))); m(mi).trlC=trlC; % for CV-predictive cvlC=sum(log(mean(exp(lps)))); m(mi).cvlC=cvlC; % bias corrected cvclC=sum(log(mean(exp(lps))))+sum(log(mean(exp(trlps))))-mean(sum(log(mean(exp(lpss))))); m(mi).cvclC=cvclC; % corresponding DIC and peff m(mi).cvcD=-2*cvclC; m(mi).cvcp=trlC-cvclC; % reserve memory for arrays cvlCs=zeros(1000,1); cvclCs=zeros(1000,1); cvcps=zeros(1000,1); % precompute these outside of loop etrlps=exp(trlps); elps=exp(lps); elpss=exp(lpss); % sample from the distribution of the expected utility estimate % we use Bayesian Bootstrap (Rubin, 1981), that is, % we assume that the posterior probabilities for the samples % of a random variable have a Dirichlet distribution for i2=1:1000 % uncertainty from mcmc sampling w=dirrand(1000,n); lcpo=log(sum(elps.*w))'; lcpotr=log(sum(etrlps.*w))'; lcpocvtr=squeeze(log(sum(elpss.*repmat(w,[1 1 n])))); % uncertainty from not knowing the future data distribution % here we use wwc so that we have same random numbers for each model % this to makes pairwise comparison easier cvlCs(i2)=n*sum(lcpo.*wwc(:,i2)); cvclCs(i2)=n*sum(lcpo.*wwc(:,i2))+n*sum(lcpotr.*wwc(:,i2))-mean(n*sum(lcpocvtr.*repmat(wwc(:,i2),[1 n]))); end m(mi).cvlCs=cvlCs; m(mi).cvclCs=cvclCs; end fprintf('\n'); save m m % Figures lab={'1) normal','2) double exp.','3) logistic','4) {\it{}t}_4','5) {\it{}t}_4 as scale mixt.'}; set(0,'DefaultAxesLineWidth',1) set(0,'DefaultLineLineWidth',1) load ii load m n=21; % Figure 1: CV vs DIC - predictive deviance clf a4 figscale=[1 1/2]; set(gcf,'pos',[27.4 3.8 10.795.*figscale(1) 15.26.*figscale(2)]); set(gcf,'paperposition',[5.1 6.9 10.795.*figscale(1) 15.26.*figscale(2)]); set(gcf,'DefaultAxesFontSize',13) set(gcf,'DefaultTextFontSize',13) clf set(gca,'Box','on'); set(gca,'Position',[0.375 0.16 0.585 0.835]) ddic=[115.2 113.5 114.8 114.2 109.7]; dcvc=-2*[m(:).cvclC]; h(1)=line(dcvc,5:-1:1,'Color','b','Linewidth',3,'Marker','o','MarkerFaceColor','b','MarkerSize',10,'LineStyle','none'); h(2)=line(ddic,5:-1:1,'Color','r','Linewidth',3,'Marker','d','MarkerFaceColor','r','MarkerSize',10,'LineStyle','none'); set(gca,'YLim',[0.5 5.5],'YTick',[]) set(gca,'XGrid','on') set(gca,'XLim',[106 132]) tx=min(get(gca,'XLim'))-diff(get(gca,'XLim'))/1.55; for qi=1:5 text(tx,6-qi,sprintf('%s',lab{qi}),'HorizontalAlignment','left') end h=legend([h],'CV','DIC'); xlabel('Expected predictive deviance') print -depsc2 stack_dic.eps % Figure 2: CV vs DIC - p_eff clf a4 figscale=[1 1/2]; set(gcf,'pos',[27.4 3.8 10.795.*figscale(1) 15.26.*figscale(2)]); set(gcf,'paperposition',[5.1 6.9 10.795.*figscale(1) 15.26.*figscale(2)]); set(gcf,'DefaultAxesFontSize',13) set(gcf,'DefaultTextFontSize',13) clf set(gca,'Box','on'); set(gca,'Position',[0.335 0.14 0.635 0.85]) set(gca,'Position',[0.375 0.16 0.585 0.835]) pdic=[5.1 5.6 5.3 5.5 7.6]; pcvc=[m(:).cvcp]; h(1)=line(pcvc,5:-1:1,'Color','b','Linewidth',3,'Marker','o','MarkerFaceColor','b','MarkerSize',10,'LineStyle','none'); h(2)=line(pdic,5:-1:1,'Color','r','Linewidth',3,'Marker','d','MarkerFaceColor','r','MarkerSize',10,'LineStyle','none'); set(gca,'YLim',[0.5 5.5],'YTick',[]) set(gca,'XGrid','on') set(gca,'XLim',[4 10]) tx=min(get(gca,'XLim'))-diff(get(gca,'XLim'))/1.55; for qi=1:5 text(tx,6-qi,sprintf('%s',lab{qi}),'HorizontalAlignment','left') end legend([h],'CV','DIC') xlabel('Effective number of parameters') print -depsc2 stack_peff.eps % Figure 3: Pairwise comparison of models % Compute pairwise comparison of t_4 scale mixture model to others for i1=1:4 q=-2*([m(5).cvclCs-m(i1).cvclCs]); qx=min(q)-0.5:0.02:max(q)+1; p=kernelp(q,qx); qxs{i1}=qx; qps{i1}=p; end clf a4 figscale=[1 1/2]; set(gcf,'pos',[27.4 3.8 10.795.*figscale(1) 15.26.*figscale(2)]); set(gcf,'paperposition',[5.1 6.9 10.795.*figscale(1) 15.26.*figscale(2)]); set(gcf,'DefaultAxesFontSize',13) set(gcf,'DefaultTextFontSize',13) set(gca,'Box','on'); set(gca,'Position',[0.05 0.17 0.9 0.815]) qc=get(0,'DefaultAxesColorOrder'); for i1=1:4 line(qxs{i1},qps{i1},'Color',qc(i1,:),'Linewidth',3) end set(gca,'YLim',[0 0.88],'Ytick',[],'XLim',[-10 10]) line([0 0],[0 max(get(gca,'YLim'))],'LineStyle','--','Color','k') xlabel('Pairwise comparison of {\it{}t}_4 scale mixture to others') h=legend(lab{1:4}); set(h,'pos', [0.51 0.6437 0.44 0.3182]) print -depsc2 stack_pcomp.eps