forked from ilarinieminen/SOM-Toolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsom_neighf.m
117 lines (98 loc) · 3.44 KB
/
som_neighf.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
function H = som_neighf(sMap,radius,neigh,ntype)
%SOM_NEIGHF Return neighborhood function values.
%
% H = som_neighf(sMap,[radius],[neigh],[ntype]);
%
% Input and output arguments ([]'s are optional):
% sMap (struct) map or topology struct
% [radius] (scalar) neighborhood radius (by default, the last used value
% in sMap.trainhist is used, or 1 if that is unavailable)
% [neigh] (string) neighborhood function type (by default, ..., or
% 'gaussian' if that is unavailable)
% [ntype] (string) 'normal' (default), 'probability' or 'mirror'
%
% H (matrix) [munits x munits] neighborhood function values from
% each map unit to each other map unit
%
% For more help, try 'type som_batchtrain' or check out online documentation.
% See also SOM_MAKE, SOM_SEQTRAIN, SOM_TRAIN_STRUCT.
% Copyright (c) 1997-2000 by the SOM toolbox programming team.
% http://www.cis.hut.fi/projects/somtoolbox/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Check arguments
% defaults
rdefault = 1;
ndefault = 'gaussian';
tdefault = 'normal';
% map
switch sMap.type,
case 'som_map',
sTopol = sMap.topol;
sTrain = sMap.trainhist(end);
if isempty(sTrain.radius_fin) || isnan(sTrain.radius_fin),
rdefault = 1;
else
rdefault = sTrain.radius_fin;
end
if ~isempty(sTrain.neigh) && ~isnan(sTrain.neigh),
ndefault = sTrain.neigh;
end
case 'som_topol', sTopol = sMap;
end
munits = prod(sTopol.msize);
% other parameters
if nargin<2 || isempty(radius), radius = rdefault; end
if nargin<3 || isempty(neigh), neigh = ndefault; end
if nargin<4 || isempty(ntype), ntype = tdefault; end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% initialize
% basic neighborhood
Ud = som_unit_dists(sTopol);
Ud = Ud.^2;
radius = radius.^2;
if radius==0, radius = eps; end % zero neighborhood radius may cause div-by-zero error
switch ntype,
case 'normal',
H = neighf(neigh,Ud,radius);
case 'probability',
H = neighf(neigh,Ud,radius);
for i=1:munits, H(i,:) = H(i,:)/sum(H(i,:)); end
case 'mirror', % only works for 2-dim grid!!!
H = zeros(munits,munits);
Co = som_unit_coords(sTopol);
for i=-1:1,
for j=-1:1,
Ud = gridmirrordist(Co,i,j);
H = H + neighf(neigh,Ud,radius);
end
end
end
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% subfunctions
function H = neighf(neigh,Ud,radius)
switch neigh,
case 'bubble', H = (Ud<=radius);
case 'gaussian', H = exp(-Ud/(2*radius));
case 'cutgauss', H = exp(-Ud/(2*radius)) .* (Ud<=radius);
case 'ep', H = (1-Ud/radius) .* (Ud<=radius);
end
return;
function Ud = gridmirrordist(Co,mirrorx,mirrory)
[munits,mdim] = size(Co);
if mdim>2, error('Mirrored neighborhood only works for 2-dim map grids.'); end
% width and height of the grid
dx = max(Co(:,1))-min(Co(:,1));
dy = max(Co(:,2))-min(Co(:,2));
% calculate distance from each location to each other location
Ud = zeros(munits,munits);
for i=1:munits,
inds = [i:munits];
coi = Co(i,:); % take hexagonal shift into account
coi(1) = coi(1)*(1-2*(mirrorx~=0)) + 2*dx*(mirrorx==1); % +mirrorx * step
coi(2) = coi(2)*(1-2*(mirrory~=0)) + 2*dy*(mirrory==1); % +mirrory * step
Dco = (Co(inds,:) - coi(ones(munits-i+1,1),:))';
Ud(i,inds) = sqrt(sum(Dco.^2));
Ud(inds,i) = Ud(i,inds)';
end
return;