function [p,pc,R2] = spm_mvb_cvk2(MVB,k) % k-fold cross validation of a multivariate Bayesian model % FORMAT [p_value,percent,R2] = spm_mvb_cvk(MVB,k) % % MVB - Multivariate Bayes structure % k - k-fold cross-validation ('0' implies a leave-one-out scheme) % % p - p-value: under a null GLM % percent: proportion correct (median threshold) % R2 - coefficient of determination % % spm_mvb_cvk performs a k-fold cross-validation by trying to predict % the target variable using training and test partitions on orthogonal % mixtures of data (from null space of confounds). % This version uses the optimised covariance model from spm_mvb. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston % $Id: spm_mvb_cvk2.m 5219 2013-01-29 17:07:07Z spm $ %-partition order %-------------------------------------------------------------------------- try k; catch str = 'k-fold cross-validation'; k = spm_input(str,'!+1','b',{'2','4','8','loo'},[2 4 8 0]); end %-Get figure handles and set title %-------------------------------------------------------------------------- Fmvb = spm_figure('GetWin','MVB'); spm_clf(Fmvb); % get MVB results %========================================================================== try MVB; catch mvb = spm_select(1,'mat','please select models',[],pwd,'MVB_*'); MVB = load(mvb(1,:)); MVB = MVB.MVB; end % whiten target and predictor (X) variables (Y) (i.e., remove correlations) %-------------------------------------------------------------------------- X = MVB.X; X0 = MVB.X0; V = MVB.V; % residual forming matrix %-------------------------------------------------------------------------- Ns = length(X); R = speye(Ns) - X0*pinv(X0); % leave-one-out %-------------------------------------------------------------------------- if ~k k = Ns; end pX = zeros(Ns,1); qX = zeros(Ns,1); qE = zeros(size(MVB.Y,2),k); % k-fold cross-validation %========================================================================== for i = 1:k [px,qx,qe] = mvb_cv(MVB,i,k); pX = pX + px; qX = qX + qx; qE(:,i) = qe; end % parametric inference %========================================================================== % test correlation %-------------------------------------------------------------------------- [T,df] = spm_ancova(X,V,qX,1); p = 1 - spm_Tcdf(T,df(2)); % percent correct (after projection) %-------------------------------------------------------------------------- pX = R*X; qX = R*qX; T = sign(pX - median(pX)) == sign(qX - median(qX)); pc = 100*sum(T)/length(T); R2 = corrcoef(pX,qX); R2 = 100*(R2(1,2)^2); % assign in base memory %-------------------------------------------------------------------------- MVB.p_value = p; MVB.percent = pc; MVB.R2 = R2; MVB.cvk = struct('qX',qX,'qE',qE); % save results %-------------------------------------------------------------------------- save(MVB.name,'MVB', spm_get_defaults('mat.format')) assignin('base','MVB',MVB) % display and plot validation %-------------------------------------------------------------------------- spm_mvb_cvk_display(MVB) return %========================================================================== function [X,qX,qE] = mvb_cv(MVB,n,k) %========================================================================== % MVB - multivariate structure % n - subset % k - partition % Unpack MVB and create test subspace %-------------------------------------------------------------------------- V = MVB.V; U = MVB.M.U; X = MVB.X; Y = MVB.Y; X0 = MVB.X0; h = MVB.M.h; Cp = MVB.M.Cp; % Specify indices of training and test data %-------------------------------------------------------------------------- Ns = length(X); ns = floor(Ns/k); test = [1:ns] + (n - 1)*ns; tran = [1:Ns]; tran(test) = []; test = full(sparse(test,test,1,Ns,Ns)); tran = full(sparse(tran,tran,1,Ns,Ns)); % Training - add test space to confounds %========================================================================== R = speye(Ns) - [X0 test]*pinv([X0 test]); R = spm_svd(R); L = R'*Y*U; % get error covariance %-------------------------------------------------------------------------- Ce = sparse(Ns,Ns); if isstruct(V) for i = 1:length(V) Ce = Ce + h(i)*V{i}; end else Ce = V*h(1); end Ce = R'*Ce*R; % MAP estimates of pattern weights from training data %---------------------------------------------------------------------- MAP = Cp*L'*inv(Ce + L*Cp*L'); qE = MAP*R'*X; % Test - add training space to confounds and get predicted X %========================================================================== R = speye(Ns) - [X0 tran]*pinv([X0 tran]); X = R*X; % test data qE = U*qE; % weights qX = R*Y*qE; % prediction