forked from ilarinieminen/SOM-Toolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
som_distortion.m
138 lines (120 loc) · 4.31 KB
/
som_distortion.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
function [adm,admu,tdmu] = som_distortion(sM, D, arg1, arg2)
%SOM_DISTORTION Calculate distortion measure for the map.
%
% [adm,admu,tdmu] = som_distortion(sMap, D, [radius], ['prob'])
%
% adm = som_distortion(sMap,D);
% [adm,admu] = som_distortion(sMap,D);
% som_show(sMap,'color',admu);
%
% Input and output arguments:
% sMap (struct) a map struct
% D (struct) a data struct
% (matrix) size dlen x dim, a data matrix
% [radius] (scalar) neighborhood function radius to be used.
% Defaults to the last radius_fin in the
% trainhist field of the map struct, or 1 if
% that is missing.
% ['prob'] (string) If given, this argument forces the
% neigborhood function values for each map
% unit to be normalized so that they sum to 1.
%
% adm (scalar) average distortion measure (sum(dm)/dlen)
% admu (vector) size munits x 1, average distortion in each unit
% tdmu (vector) size munits x 1, total distortion for each unit
%
% The distortion measure is defined as:
% 2
% E = sum sum h(bmu(i),j) ||m(j) - x(i)||
% i j
%
% where m(i) is the ith prototype vector of SOM, x(j) is the jth data
% vector, and h(.,.) is the neighborhood function. In case of fixed
% neighborhood and discreet data, the distortion measure can be
% interpreted as the energy function of the SOM. Note, though, that
% the learning rule that follows from the distortion measure is
% different from the SOM training rule, so SOM only minimizes the
% distortion measure approximately.
%
% If the 'prob' argument is given, the distortion measure can be
% interpreted as an expected quantization error when the neighborhood
% function values give the likelyhoods of accidentally assigning
% vector j to unit i. The normal quantization error is a special case
% of this with zero incorrect assignement likelihood.
%
% NOTE: when calculating BMUs and distances, the mask of the given
% map is used.
%
% See also SOM_QUALITY, SOM_BMUS, SOM_HITS.
% Reference: Kohonen, T., "Self-Organizing Map", 2nd ed.,
% Springer-Verlag, Berlin, 1995, pp. 120-121.
%
% Graepel, T., Burger, M. and Obermayer, K.,
% "Phase Transitions in Stochastic Self-Organizing Maps",
% Physical Review E, Vol 56, No 4, pp. 3876-3890 (1997).
% Contributed to SOM Toolbox vs2, Feb 3rd, 2000 by Juha Vesanto
% Copyright (c) by Juha Vesanto
% http://www.cis.hut.fi/projects/somtoolbox/
% Version 2.0beta juuso 030200
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check arguments
% input arguments
if nargin < 2, error('Not enough input arguments.'); end
% map
M = sM.codebook;
munits = prod(sM.topol.msize);
% data
if isstruct(D), D = D.data; end
[dlen dim] = size(D);
% arg1, arg2
rad = NaN;
normalize = 0;
if nargin>2,
if isnumeric(arg1), rad = arg1;
elseif ischar(arg1) && strcmp(arg1,'prob'), normalize = 0;
end
end
if nargin>3,
if isnumeric(arg2), rad = arg2;
elseif ischar(arg2) && strcmp(arg2,'prob'), normalize = 0;
end
end
% neighborhood radius
if isempty(rad) || isnan(rad),
if ~isempty(sM.trainhist), rad = sM.trainhist(end).radius_fin;
else rad = 1;
end
end
if rad<eps, rad = eps; end
% neighborhood
Ud = som_unit_dists(sM.topol);
switch sM.neigh,
case 'bubble', H = (Ud <= rad);
case 'gaussian', H = exp(-(Ud.^2)/(2*rad*rad));
case 'cutgauss', H = exp(-(Ud.^2)/(2*rad*rad)) .* (Ud <= rad);
case 'ep', H = (1 - (Ud.^2)/rad) .* (Ud <= rad);
end
if normalize,
for i=1:munits, H(:,i) = H(:,i)/sum(H(:,i)); end
end
% total distortion measure
mu_x_1 = ones(munits,1);
tdmu = zeros(munits,1);
hits = zeros(munits,1);
for i=1:dlen,
x = D(i,:); % data sample
known = ~isnan(x); % its known components
Dx = M(:,known) - x(mu_x_1,known); % each map unit minus the vector
dist2 = (Dx.^2)*sM.mask(known); % squared distances
[qerr bmu] = min(dist2); % find BMU
tdmu = tdmu + dist2.*H(:,bmu); % add to distortion measure
hits(bmu) = hits(bmu)+1; % add to hits
end
% average distortion per unit
admu = tdmu;
ind = find(hits>0);
admu(ind) = admu(ind) ./ hits(ind);
% average distortion measure
adm = sum(tdmu)/dlen;
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%