wolffd@0
|
1 function base = som_clspread(sM,base,cldist,Ne,verbosity)
|
wolffd@0
|
2
|
wolffd@0
|
3 % SOM_CLSPREAD Partition the given data by flooding.
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % part = som_clspread(sM,part,cldist,[Ne],[verbos])
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % Input and output arguments ([]'s are optional):
|
wolffd@0
|
8 % sM (struct) map or data struct
|
wolffd@0
|
9 % (matrix) size dlen x dim, the data set
|
wolffd@0
|
10 % base (vector) initial partition, where if base(i) is
|
wolffd@0
|
11 % 0 i should be assigned to some cluster
|
wolffd@0
|
12 % NaN i should not be assigned to any cluster
|
wolffd@0
|
13 % otherwise i belongs to cluster base(i)
|
wolffd@0
|
14 % cldist (string) cluster distance measure: 'single', 'average',
|
wolffd@0
|
15 % 'complete', 'neighf', 'ward', 'centroid', 'BMU'
|
wolffd@0
|
16 % [Ne] (scalar) 0 = not constrined to neighborhood
|
wolffd@0
|
17 % 1 = constrained
|
wolffd@0
|
18 % (matrix) size dlen x dlen, indicating possible connections
|
wolffd@0
|
19 % [verbos] (scalar) 1 (default) = show status bar
|
wolffd@0
|
20 % 0 = don't
|
wolffd@0
|
21 %
|
wolffd@0
|
22 % See also SOM_CLDIST.
|
wolffd@0
|
23
|
wolffd@0
|
24 % Copyright (c) 2000 by Juha Vesanto
|
wolffd@0
|
25 % Contributed to SOM Toolbox on XXX by Juha Vesanto
|
wolffd@0
|
26 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
27
|
wolffd@0
|
28 % Version 2.0beta juuso 220800
|
wolffd@0
|
29
|
wolffd@0
|
30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
31 %% input arguments
|
wolffd@0
|
32
|
wolffd@0
|
33 q = 2;
|
wolffd@0
|
34
|
wolffd@0
|
35 % map/data
|
wolffd@0
|
36 if isstruct(sM),
|
wolffd@0
|
37 switch sM.type,
|
wolffd@0
|
38 case 'som_map', M = sM.codebook; mask = sM.mask; sT = sM.topol;
|
wolffd@0
|
39 case 'som_data', M = sM.data; mask = []; sT = [];
|
wolffd@0
|
40 end
|
wolffd@0
|
41 else M = sM; mask = []; sT = [];
|
wolffd@0
|
42 end
|
wolffd@0
|
43 [dlen dim] = size(M);
|
wolffd@0
|
44 if isempty(mask), mask = ones(dim,1); end
|
wolffd@0
|
45
|
wolffd@0
|
46 % simple option
|
wolffd@0
|
47 if any(strcmp(cldist,{'closest','BMU'})),
|
wolffd@0
|
48 i0 = find(base==0);
|
wolffd@0
|
49 i1 = find(base>0);
|
wolffd@0
|
50 bmus = som_bmus(M(i1,:),M(i0,:));
|
wolffd@0
|
51 base(i0) = base(i1(bmus));
|
wolffd@0
|
52 return;
|
wolffd@0
|
53 end
|
wolffd@0
|
54
|
wolffd@0
|
55 % constrained clustering
|
wolffd@0
|
56 if nargin<4, Ne = []; end
|
wolffd@0
|
57 if prod(size(Ne))==1,
|
wolffd@0
|
58 if Ne & isempty(sT),
|
wolffd@0
|
59 warning('Cannot use constrained clustering.'); Ne = 0;
|
wolffd@0
|
60 end
|
wolffd@0
|
61 if Ne, Ne = som_unit_neighs(sT); else Ne = []; end
|
wolffd@0
|
62 end
|
wolffd@0
|
63 if ~isempty(Ne),
|
wolffd@0
|
64 Ne([0:dlen-1]*dlen+[1:dlen]) = 1; % set diagonal elements = 1
|
wolffd@0
|
65 if all(Ne(:)>0), Ne = []; end
|
wolffd@0
|
66 end
|
wolffd@0
|
67
|
wolffd@0
|
68 if nargin<5, verbosity = 1; end
|
wolffd@0
|
69
|
wolffd@0
|
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
71 %% initialize
|
wolffd@0
|
72
|
wolffd@0
|
73 if size(base,1)==1, base = base'; end
|
wolffd@0
|
74
|
wolffd@0
|
75 cid = unique(base(isfinite(base) & base~=0)); % cluster IDs
|
wolffd@0
|
76 nc = length(cid);
|
wolffd@0
|
77 uind = find(base==0); % unclustered points
|
wolffd@0
|
78 nu = length(uind);
|
wolffd@0
|
79 if nu==0, return; end
|
wolffd@0
|
80
|
wolffd@0
|
81 % initial clusters
|
wolffd@0
|
82 clinds = cell(nc,1); for i=1:nc, clinds{i} = find(base==i); end
|
wolffd@0
|
83 clinds2 = cell(nu,1); for i=1:nu, clinds2{i} = uind(i); end
|
wolffd@0
|
84
|
wolffd@0
|
85 % neighborhood function values
|
wolffd@0
|
86 if strcmp(cldist,'neighf')
|
wolffd@0
|
87 if isempty(sT), error('Cannot use neighf linkage.'); end
|
wolffd@0
|
88 q = som_unit_dists(sT).^2;
|
wolffd@0
|
89 r = sM.trainhist(end).radius_fin^2;
|
wolffd@0
|
90 if isnan(r) | isempty(r), r = 1; end
|
wolffd@0
|
91 switch sM.neigh,
|
wolffd@0
|
92 case 'bubble', q = (q <= r);
|
wolffd@0
|
93 case 'gaussian', q = exp(-q/(2*r));
|
wolffd@0
|
94 case 'cutgauss', q = exp(-q/(2*r)) .* (q <= r);
|
wolffd@0
|
95 case 'ep', q = (1-q/r) .* (q <= r);
|
wolffd@0
|
96 end
|
wolffd@0
|
97 end
|
wolffd@0
|
98
|
wolffd@0
|
99 % distance of each cluster to the unclustered points
|
wolffd@0
|
100 if any(strcmp(cldist,{'single','average','complete','neighf'})),
|
wolffd@0
|
101 M = som_mdist(M,2,mask,Ne);
|
wolffd@0
|
102 end
|
wolffd@0
|
103 Cd = som_cldist(M,clinds,clinds2,cldist,q,mask);
|
wolffd@0
|
104
|
wolffd@0
|
105 % check out from Ne which of the clusters are not connected
|
wolffd@0
|
106 if ~isempty(Ne) & any(strcmp(cldist,{'centroid','ward'})),
|
wolffd@0
|
107 Clconn = sparse(nc,nu);
|
wolffd@0
|
108 for i=1:nc, for j=1:nu, Clconn(i,j) = any(any(Ne(clinds{i},uind(j)))); end, end
|
wolffd@0
|
109 Cd(Clconn==0) = Inf;
|
wolffd@0
|
110 else
|
wolffd@0
|
111 Clconn = [];
|
wolffd@0
|
112 end
|
wolffd@0
|
113
|
wolffd@0
|
114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
115 %% action
|
wolffd@0
|
116
|
wolffd@0
|
117 if verbosity,
|
wolffd@0
|
118 nu0 = nu;
|
wolffd@0
|
119 h = waitbar(1-nu/nu0,'Assigning unclustered points'); % tracking
|
wolffd@0
|
120 end
|
wolffd@0
|
121
|
wolffd@0
|
122 while 1,
|
wolffd@0
|
123
|
wolffd@0
|
124 % find closest unclustered point
|
wolffd@0
|
125 [dk,k] = min(Cd,[],2); % min distance from each unclustered point
|
wolffd@0
|
126 [d,c] = min(dk); % cluster to which it is assigned
|
wolffd@0
|
127 k = k(c);
|
wolffd@0
|
128
|
wolffd@0
|
129 if ~isfinite(d),
|
wolffd@0
|
130 break;
|
wolffd@0
|
131 end
|
wolffd@0
|
132
|
wolffd@0
|
133 % add k to cluster c
|
wolffd@0
|
134 base(uind(k)) = cid(c);
|
wolffd@0
|
135 clinds{c} = [clinds{c}; uind(k)];
|
wolffd@0
|
136
|
wolffd@0
|
137 % remove point k
|
wolffd@0
|
138 notk = [1:k-1,k+1:nu];
|
wolffd@0
|
139 nu = nu-1; if nu<=0, break; end
|
wolffd@0
|
140 Cd = Cd(:,notk);
|
wolffd@0
|
141 uind = uind(notk);
|
wolffd@0
|
142 clinds2 = clinds2(notk);
|
wolffd@0
|
143 if ~isempty(Clconn), Clconn = Clconn(:,notk); end
|
wolffd@0
|
144
|
wolffd@0
|
145 % update cluster distances to c
|
wolffd@0
|
146 Cd(c,:) = som_cldist(M,clinds(c),clinds2,cldist,q,mask);
|
wolffd@0
|
147 if ~isempty(Clconn),
|
wolffd@0
|
148 for j=1:nu, Clconn(c,j) = any(any(Ne(clinds{c},uind(j)))); end
|
wolffd@0
|
149 Cd(c,find(Clconn(c,:)==0)) = Inf;
|
wolffd@0
|
150 end
|
wolffd@0
|
151
|
wolffd@0
|
152 if verbosity, waitbar(1-nu/nu0,h); end % tracking
|
wolffd@0
|
153
|
wolffd@0
|
154 end
|
wolffd@0
|
155 if verbosity, close(h); end
|
wolffd@0
|
156
|
wolffd@0
|
157 return;
|
wolffd@0
|
158
|
wolffd@0
|
159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
160
|
wolffd@0
|
161
|