-
Notifications
You must be signed in to change notification settings - Fork 20
/
geometric_median.m
55 lines (45 loc) · 2.39 KB
/
geometric_median.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function [geometricMedian convergenceHistory]= geometric_median(x, varargin)
% geometricMedian = geometric_median(x, {key, value pairs})
% Input
%
% x is an N x M matrix, representing N observations of a M-dimensional matrix.
%
% Key, value pairs
%
% initialGuess is optional an 1 x M matrix, representing the initial guess for the gemetrix median
%
% tolerance an scalar value. It is the maximum relative change in geometricMedian vector (size of the change in
% the last iteration divided by the size of the geometricMedian vector) that makes the
% algorithm to continue to the next iteration. If relative change is less than tolerance, it is assumed
% that convergence is achieved.
% had a relative change more than tolerance then more iterations are performed.
% default = 1e-4.
%
% Output
% geometricMedian is an 1 x m matrix.
% convergenceHistory shows the value of maximum relative chage, which is compared to tolerance in
% each iteration.
% use mean as the median as an initial guess if none is provided.
inputOptions = finputcheck(varargin, ...
{'initialGuess' 'real' [] mean(x);...
'tolerance' 'real' [0 1] 1e-6;...
'maxNumberOfIterations' 'integer' [1 Inf] 1000;...
});
geometricMedian = inputOptions.initialGuess;
for i=1:inputOptions.maxNumberOfIterations
lastGeometricMedian = geometricMedian;
differenceToEstimatedMedian = bsxfun(@minus, x, geometricMedian);
sizeOfDifferenceToEstimatedMedian = (sum(differenceToEstimatedMedian .^2, 2) .^ 0.5);
oneOverSizeOfDifferenceToEstimatedMedian = 1 ./ sizeOfDifferenceToEstimatedMedian;
% to prevent nans
oneOverSizeOfDifferenceToEstimatedMedian(isinf(oneOverSizeOfDifferenceToEstimatedMedian)) = 1e20;
geometricMedian = sum(bsxfun(@times, x , oneOverSizeOfDifferenceToEstimatedMedian)) / sum(oneOverSizeOfDifferenceToEstimatedMedian);
%maxRelativeChange = max(max(abs(lastGeometricMedian - geometricMedian)) ./ abs(geometricMedian));
maxRelativeChange = (sum((lastGeometricMedian - geometricMedian).^2) / sum(geometricMedian.^2)) .^ 0.5;
if nargout > 1
convergenceHistory(i) = maxRelativeChange;
end;
if (maxRelativeChange < inputOptions.tolerance || isnan(maxRelativeChange))
break;
end;
end;