forked from ilarinieminen/SOM-Toolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
som_kmeanscolor2.m
189 lines (164 loc) · 5.7 KB
/
som_kmeanscolor2.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
function [color,centroids]=som_kmeanscolor2(mode,sM,C,initRGB,contrast,R)
% SOM_KMEANSCOLOR2 Color codes a SOM according to averaged or best K-means clustering
%
% color = som_kmeanscolor2('average',sM, C, [initRGB], [contrast],[R])
%
% color=som_kmeanscolor2('average',sM,[2 4 8 16],som_colorcode(sM,'rgb1'),'enhanced');
% [color,centroid]=som_kmeanscolor2('best',sM,15,[],'flat',R);
%
% Input and output arguments ([]'s are optional):
%
% mode (string) 'average' or 'best', defalut: 'average'
% sM (struct) a map struct
% C (vector) number of clusters
% [initRGB] (string, matrix) a color code string accepted by SOM_COLORCODE
% or an Mx3 matrix of RGB triples, where M is the number
% of map units. Default: SOM_COLORCODEs default
% [contrast] (string) 'flat', 'enhanced' color contrast mode, default:
% 'enhanced'.
% [R] (scalar) number of K-means trials, default: 30.
% color (matrix) Mx3xC of RGB triples
% centroid (array of matrices) centroid{i} includes codebook for the best
% k-means for C(i) clusters, i.e. the cluster centroids corresponding to
% the color code color(:,:,i).
%
% The function gives a set of color codes for the SOM according to K-means
% clustering. It has two operation modes:
%
% 'average': The idea of coloring is that the color of the units belonging to the same
% cluster is the mean of the original RGB values (see SOM_COLORCODE) of the map units
% belonging to the cluster (see SOM_CLUSTERCOLOR). The K-means clustering is made,
% by default, 30 times and the resulting color codes are averaged for
% each specified number of clusters C(i), i=1,...,k. In a way, the resulting averaged color
% codes reflect the stability of the K-means clustering made on the map units.
%
% 'best': runs the k-means R times for C(i), i=1,...,n clusters as in previous mode,
% but instead of averaging all the R color codes, it picks the one that corresponds to the
% best k-means clustering for each C(i). The 'best' is the one with the lowest
% quantization error. The result may differ from run to run.
%
% EXAMPLE
%
% load iris; % or any other map struct sM
% color=som_kmeanscolor2('average',sM,[2:6]);
% som_show(sM,'umat','all','color',color);
%
% See also SOM_KMEANS, SOM_SHOW, SOM_COLORCODE, SOM_CLUSTERCOLOR, SOM_KMEANSCOLOR
% Contributed to SOM Toolbox 2.0, 2001 February by Johan Himberg
% Copyright (c) by Johan Himberg
% http://www.cis.hut.fi/projects/somtoolbox/
%%% Check number of inputs
error(nargchk(3, 6, nargin)); % check no. of input args
%%% Check input args & set defaults
if ~vis_valuetype(mode,{'string'}),
error('Mode must be a string.');
end
switch lower(mode),
case{'average','best'}
otherwise
error('Mode must be string ''average'' or ''best''.');
end
if isstruct(sM) && isfield(sM,'type') && strcmp(sM.type,'som_map'),
[tmp,lattice,msize]=vis_planeGetArgs(sM);
munits=prod(msize);
if length(msize)>2
error('Does not work with 3D maps.')
end
else
error('Map struct required for the second input argument!');
end
if ~vis_valuetype(C,{'1xn','nx1'}),
error('Vector value expected for cluster number.');
end
% Round C and check
C=round(C(:)');
if any(C<2),
error('Cluster number must be 2 or more.');
end
% check initial color coding
if nargin<4 || isempty(initRGB)
initRGB=som_colorcode(sM);
end
% check contrast checking
if nargin<5 || isempty(contrast),
contrast='enhanced';
end
if ~ischar(contrast),
error('String input expected for input arg. ''contrast''.');
else
switch lower(contrast)
case {'flat','enhanced'}
otherwise
error(['''flat'' or ''enhanced'' expected for '...
'input argument ''contrast''.']);
end
end
if ischar(initRGB),
try
initRGB=som_colorcode(sM,initRGB);
catch
error(['Color code ' initRGB ...
'was not recognized by SOM_COLORCODE.']);
end
elseif vis_valuetype(initRGB,{'nx3rgb',[munits 3]},'all'),
else
error(['The initial color code must be a string '...
'or an Mx3 matrix of RGB triples.']);
end
if nargin<6||isempty(R),
R=30;
end
if ~vis_valuetype(R,{'1x1'}),
error('''R'' must be scalar.');
end
%%% Action %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
disp('Wait...');
index=0; hit_=zeros(munits,munits);
switch mode,
%% Averaged k-means coloring
case 'average'
for k=C,
disp(['Running K-means for ' num2str(k) ' clusters...']);
color_=zeros(munits,3);
colord_=color_;
% Average R k-means colorings for C clusters
for j=1:R,
[dummy,c]=som_kmeans('batch',sM,k,100,0); % max 100 iterations, verbose off
color_=color_+som_clustercolor(sM,c,initRGB);
end
index=index+1;
color(:,:,index)=color_./R;
end
%% coloring for 'best' k-means coloring
case 'best'
for k=C,
disp(['Running K-means for ' num2str(k) ' clusters...']);
c=[];err=Inf; div=[];
%% look for the best k-means among R trials
for i=1:R,
[c_,div_,err_(i)]=som_kmeans('batch',sM,k,100,0); % max 100 iterations, verbose off
if err_(i)<err,
err=err_(i); c=c_; div=div_;
end
end
% record the 'best' k-means for C clusters
index=index+1;
color(:,:,index)=som_clustercolor(sM,div,initRGB);
centroid{index}=c;
end
end
%%% Build output
switch contrast
case 'flat'
case 'enhanced'
warning off;
ncolor=maxnorm(color);
ncolor(~isfinite(ncolor))=color(~isfinite(ncolor));
color=ncolor;
warning on;
end
%%% Subfunctions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function X=maxnorm(x)
% normalize columns of x between [0,1]
x=x-repmat(min(x),[size(x,1) 1 1]);
X=x./repmat(max(x),[size(x,1) 1 1]);