123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- function [B, W] = spm_robust_glm(Y, X, dim, ks)
- % Apply robust GLM
- % FORMAT [B, W] = spm_robust_glm(Y, X, dim, ks)
- % Y - data matrix
- % X - design matrix
- % dim - the dimension along which the function will work
- % ks - offset of the weighting function (default: 3)
- %
- % OUTPUT:
- % B - parameter estimates
- % W - estimated weights
- %
- % Implementation of:
- % Wager TD, Keller MC, Lacey SC, Jonides J.
- % Increased sensitivity in neuroimaging analyses using robust regression.
- % Neuroimage. 2005 May 15;26(1):99-113
- %__________________________________________________________________________
- % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
- % James Kilner, Vladimir Litvak
- % $Id: spm_robust_glm.m 4407 2011-07-26 12:13:00Z vladimir $
- if nargin < 3 || isempty(ks)
- ks = 3;
- end
- if nargin < 2 || isempty(dim)
- dim = 1;
- end
- %-Remember the original data size and size of the mean
- %--------------------------------------------------------------------------
- origsize = size(Y);
- borigsize = origsize;
- borigsize(dim) = size(X, 2);
- %-Convert the data to repetitions x points matrix
- %--------------------------------------------------------------------------
- if dim > 1
- Y = shiftdim(Y, dim-1);
- end
- if length(origsize) > 2
- Y = reshape(Y, size(Y, 1), []);
- end
- %-Check the design matrix and compute leverages
- %--------------------------------------------------------------------------
- if size(X, 1) ~= size(Y, 1)
- error('The number of rows in the design matrix should match dimension of interest.');
- end
- H = diag(X*inv(X'*X)*X');
- H = repmat(H(:), 1, size(Y, 2));
- %-Rescale the data
- %--------------------------------------------------------------------------
- [Y, scalefactor] = spm_cond_units(Y);
- %-Actual robust GLM
- %--------------------------------------------------------------------------
- ores=1;
- nres=10;
- n=0;
- YY = Y;
- YY(isnan(YY)) = 0;
- while max(abs(ores-nres))>sqrt(1E-8)
- ores=nres;
- n=n+1;
- if n == 1
- W = ones(size(Y));
- W(isnan(Y)) = 0;
- end
-
- B = zeros(size(X, 2), size(Y, 2));
-
- for i = 1:size(Y, 2);
- B(:, i) = inv(X'*diag(W(:, i))*X)*X'*diag(W(:, i))*YY(:, i);
- end
- if n > 200
- warning('Robust GLM could not converge. Maximal number of iterations exceeded.');
- break;
- end
- res = Y-X*B;
- mad = nanmedian(abs(res-repmat(nanmedian(res), size(res, 1), 1)));
- res = res./repmat(mad, size(res, 1), 1);
- res = res.*H;
- res = abs(res)-ks;
- res(res<0)=0;
- nres= (sum(res(~isnan(res)).^2));
- W = (abs(res)<1) .* ((1 - res.^2).^2);
- W(isnan(Y)) = 0;
- W(Y == 0) = 0; %Assuming X is a real measurement
- end
- disp(['Robust GLM finished after ' num2str(n) ' iterations.']);
- %-Restore the betas and weights to the original data dimensions
- %--------------------------------------------------------------------------
- B = B./scalefactor;
- if length(origsize) > 2
- B = reshape(B, circshift(borigsize, [1 -(dim-1)]));
- W = reshape(W, circshift(origsize, [1 -(dim-1)]));
- end
- if dim > 1
- B = shiftdim(B, length(origsize)-dim+1);
- W = shiftdim(W, length(origsize)-dim+1);
- end
- %-Helper function
- %--------------------------------------------------------------------------
- function Y = nanmedian(X)
- if ~any(any(isnan(X)))
- Y = median(X);
- else
- Y = zeros(1, size(X,2));
- for i = 1:size(X, 2)
- Y(i) = median(X(~isnan(X(:, i)), i));
- end
- end
|