12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- function [D,C,K] = spm_dcm_KL(M)
- % Computes the distance between two models based on prior responses
- % FORMAT [D,C,K] = spm_dcm_KL(Mi,Mj)
- %
- % M{1:n} - structure array of models
- %
- % D(n x n) - distance matrix (KL divergence)
- % C{1:n} - response covariances
- % K{1:n} - response means
- %__________________________________________________________________________
- % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
-
- % Karl Friston
- % $Id: spm_dcm_KL.m 5219 2013-01-29 17:07:07Z spm $
-
-
- % Volterra kernels
- %==========================================================================
-
- % time bins (if not specified)
- %--------------------------------------------------------------------------
- try
- dt = M{1}.dt;
- N = M{1}.N;
- catch
-
- % Bilinear representation
- %----------------------------------------------------------------------
- M0 = spm_bireduce(M{1},P{1});
- s = real(eig(full(M0)));
- s = max(s(find(s < 0)));
- N = 32;
- dt = -4/(s*N);
-
- end
-
- % get covariances of prior responses
- %==========================================================================
- m = length(M);
- for i = 1:m
-
- % Get parameters (adding a little to prevent expansion around zero)
- %----------------------------------------------------------------------
- P = M{i}.pE;
- pC = M{i}.pC;
- P = spm_vec(P) + sqrt(diag(pC))/8;
- P = spm_unvec(P,M{i}.pE);
-
- % add a little to inputs (to prevent expansion around zero)
- %----------------------------------------------------------------------
- M{i}.u = ones(M{i}.m,1)/8;
-
- % get eigen-space of parameters for computational efficiency
- %----------------------------------------------------------------------
- V = spm_svd(pC);
- pC = V'*pC*V;
-
- % get derivative of kernels w.r.t. parameters
- %----------------------------------------------------------------------
- [dkdp,k] = spm_diff('spm_kernel',M{i},P,N,dt,2,{[],V});
-
- % prior mean and covariance of kernels
- %----------------------------------------------------------------------
- k = spm_vec(k);
- dk = sparse(length(k),length(dkdp));
- for j = 1:length(dkdp)
- dk(:,j) = spm_vec(dkdp{j});
- end
- K{i} = k;
- C{i} = dk*pC*dk';
- n(i) = length(pC);
-
- end
-
-
- % evaluate KL divergence
- %--------------------------------------------------------------------------
- for i = 1:m
- for j = 1:m
- Pi = spm_pinv(C{i});
- k = K{i} - K{j};
- d = spm_logdet(C{i}) - spm_logdet(C{j}) + ...
- trace(Pi*C{j}) + k'*Pi*k - n(i);
- D(i,j) = d/2;
- end
- end
- % ensure D is symmetric
- %--------------------------------------------------------------------------
- D = (D + D')/2;
|