spm_dcm_diagnose.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. function DCM = spm_dcm_diagnose(DCM,varargin)
  2. % Post hoc diagnosis of DCMs (under the Laplace approximation)
  3. % FORMAT spm_dcm_diagnose(DCM,’field,’field’,…)
  4. %
  5. % DCM - DCM stricture (inverted)
  6. % field - field name(s) of parameters to consider
  7. %
  8. %--------------------------------------------------------------------------
  9. % This routine searches over all possible reduced models of a full model
  10. % (DCM) and uses post hoc model selection to select the best. Reduced
  11. % models mean all permutations of free parameter sets (parameters with non-
  12. % zero prior covariance), where models are defined in terms of their prior
  13. % covariance. The full model should be inverted prior to post hoc
  14. % optimization. If there are more than 8 free-parameter sets, this routine
  15. % will implement a greedy search: This entails searching over all
  16. % permutations of the 8 sets whose removal (shrinking the prior
  17. % variance to zero) produces the smallest reduction (greatest increase)
  18. % in model evidence. This procedure is repeated until all sets
  19. % are retained in the best model or there are no more parameters to
  20. % consider.
  21. %
  22. % A parameter set is specified implicitly by the structure (DCM.Ep). Each
  23. % set corresponds to a column of (the cell arrays or matrix) each field of
  24. % DCM.Ep.
  25. %
  26. % if only one field is specified the log-evidence is computed as a function
  27. % of the scaled prior variance. Redundant parameters have a log-evidence
  28. % that keeps increasing as the prior variance shrinks.
  29. %
  30. % The outputs of this routine are graphics reporting the model reduction
  31. % (optimisation). Red means weak evidence; blue strong evidence (> 3) and
  32. % cyan very strong evidence (> 5)
  33. %__________________________________________________________________________
  34. % Copyright (C) 2008-2011 Wellcome Trust Centre for Neuroimaging
  35. % Karl Friston
  36. % $Id: spm_dcm_diagnose.m 4261 2011-03-24 16:39:42Z karl $
  37. %-Get priors and posteriors
  38. %==========================================================================
  39. qE = DCM.Ep;
  40. qC = DCM.Cp;
  41. pE = DCM.M.pE;
  42. pC = DCM.M.pC;
  43. if isstruct(pC);
  44. pV = pC;
  45. pC = diag(spm_vec(pC));
  46. end
  47. % find the partition of parameters
  48. %--------------------------------------------------------------------------
  49. str = {};
  50. ind = {};
  51. if isstruct(qE)
  52. % get fields (parameters) to consider
  53. %----------------------------------------------------------------------
  54. if ~isempty(varargin)
  55. field = varargin;
  56. else
  57. field = fieldnames(qE);
  58. end
  59. for i = 1:length(field)
  60. q = getfield(qE,field{i});
  61. k = spm_fieldindices(qE,field{i});
  62. for j = 1:size(q,2)
  63. u = 1:length(spm_vec(q(:,j)));
  64. str{end + 1} = [field{i} '(' num2str(j) ')'];
  65. ind{end + 1} = k(u); k(u) = [];
  66. end
  67. end
  68. else
  69. field = {};
  70. k = 1:length(spm_vec(qE));
  71. for j = 1:size(qE,2)
  72. u = 1:length(spm_vec(qE(:,j)));
  73. str{end + 1} = ['qE(' num2str(j) ')'];
  74. ind{end + 1} = k(u); k(u) = [];
  75. end
  76. end
  77. % find free parameters
  78. %--------------------------------------------------------------------------
  79. ip = {};
  80. sp = {};
  81. for i = 1:length(str)
  82. j = find(diag(pC(ind{i},ind{i})));
  83. if ~isempty(j)
  84. ip{end + 1} = ind{i}(j);
  85. sp{end + 1} = str{i};
  86. end
  87. end
  88. % model search over shrinking priors
  89. % -------------------------------------------------------------------------
  90. n = length(pC);
  91. if length(field) == 1
  92. r = (0:64)/32;
  93. for j = 1:length(r)
  94. for i = 1:length(ip)
  95. R = speye(n,n) - sparse(ip{i},ip{i},1,n,n)*(1 - r(j));
  96. Z(i,j) = spm_log_evidence(qE,qC,pE,pC,pE,R*pC*R);
  97. end
  98. end
  99. subplot(2,1,1)
  100. plot(r,Z)
  101. title(['log-evidence for ' field{1}],'FontSize',16);
  102. xlabel('proportion of full prior')
  103. ylabel('negative free-energy')
  104. return
  105. end
  106. % model search over new prior without the i-th parameter set
  107. % -------------------------------------------------------------------------
  108. for i = 1:length(ip)
  109. R = speye(n,n) - sparse(ip{i},ip{i},1,n,n);
  110. Z(i) = spm_log_evidence(qE,qC,pE,pC,pE,R*pC*R);
  111. end
  112. % find parameters with the least evidence
  113. %--------------------------------------------------------------------------
  114. [Z i] = sort(-Z);
  115. ip = ip(i);
  116. sp = sp(i);
  117. % If there are too many subsets search use those with the least evidence
  118. %--------------------------------------------------------------------------
  119. if length(ip) > 8
  120. % flag a greedy search
  121. %----------------------------------------------------------------------
  122. ip = ip(1:8);
  123. repeat = 1;
  124. else
  125. repeat = 0;
  126. end
  127. % Create model space in terms of free parameter indices
  128. %--------------------------------------------------------------------------
  129. K = spm_perm_mtx(length(ip));
  130. % and get log-evidences
  131. %==========================================================================
  132. for i = 1:size(K,1)
  133. k = spm_vec(ip(find(K(i,:))));
  134. R = speye(n,n) - sparse(k,k,1,n,n);
  135. S(i) = spm_log_evidence(qE,qC,pE,pC,pE,R*pC*R);
  136. end
  137. % Find a good model with the most parameters
  138. % =========================================================================
  139. [i k] = max(S);
  140. k = find(K(k,:));
  141. nelim = length(k);
  142. repeat = repeat & nelim;
  143. % Continue greedy search if any parameters have been eliminated
  144. %--------------------------------------------------------------------------
  145. if repeat
  146. fprintf('removing %i parameter set: ',nelim)
  147. fprintf('%s, ',sp{k});fprintf('\n')
  148. % Optimise selected model (prior covariance)
  149. %----------------------------------------------------------------------
  150. k = spm_vec(ip(k));
  151. R = speye(n,n) - sparse(k,k,1,n,n);
  152. rC = R*pC*R;
  153. % Get posterior of selected model (rC)
  154. % ---------------------------------------------------------------------
  155. [F Ep Cp] = spm_log_evidence(qE,qC,pE,pC,pE,rC);
  156. DCM.M.pC = rC;
  157. DCM.Ep = Ep;
  158. DCM.Cp = Cp;
  159. DCM.F = F;
  160. DCM = spm_dcm_diagnose(DCM,field{:});
  161. return
  162. else
  163. % model posterior
  164. % ---------------------------------------------------------------------
  165. S = S - S(end);
  166. p = exp(S - max(S));
  167. p = p/sum(p);
  168. fprintf('\n%i Irrelevant parameter sets: ',length(k))
  169. fprintf('%s, ',sp{k});fprintf('\n')
  170. % Organise field names and show results
  171. % ---------------------------------------------------------------------
  172. spm_figure('Getwin','Graphics');
  173. for i = 1:4
  174. j = (1:8) + (i - 1)*8;
  175. try
  176. tsr{i,1} = sprintf('%s,',sp{j});
  177. catch
  178. tsr{i,1} = sprintf('%s,',sp{j(1):end});
  179. end
  180. end
  181. subplot(2,1,1)
  182. bar(Z,'c'),hold on
  183. bar(Z(Z < 5),'b'),hold on
  184. bar(Z(Z < 3),'r'),hold off
  185. title('relative log evidence (with vs. without)','FontSize',16)
  186. xlabel(tsr,'FontSize',16)
  187. ylabel('negative free-energy','FontSize',12)
  188. subplot(2,2,3)
  189. if size(K,1) > 32, plot(S,'k'), else, bar(S,'c'), end
  190. title('log-posterior','FontSize',16)
  191. xlabel('model','FontSize',12)
  192. ylabel('log-probability','FontSize',12)
  193. axis square
  194. subplot(2,2,4)
  195. if size(K,1) > 32, plot(p,'k'), else, bar(p,'r'), end
  196. title('model posterior','FontSize',16)
  197. xlabel('model','FontSize',12)
  198. ylabel('probability','FontSize',12)
  199. axis square
  200. end