Mercurial > hg > camir-aes2014
comparison toolboxes/MIRtoolbox1.3.2/somtoolbox/sammon.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 function P = sammon(D, P, varargin) | |
2 | |
3 %SAMMON Computes Sammon's mapping of a data set. | |
4 % | |
5 % P = sammon(D, P, [value], [mode], [alpha], [Mdist]) | |
6 % | |
7 % P = sammon(D,2); % projection to 2-dim space | |
8 % P = sammon(sMap,3); % projects the codebook vectors | |
9 % P = sammon(sMap,3,[],[],[],Md) % uses distance matrix Md | |
10 % som_grid(sMap,'Coord',P) % visualization of map projection | |
11 % | |
12 % Input and output arguments ([]'s are optional): | |
13 % D (matrix) size dlen x dim, data to be projected | |
14 % (struct) data or map struct | |
15 % P (scalar) output dimension | |
16 % (matrix) size dlen x odim, initial projection matrix | |
17 % [value] (scalar) all different modes (the next argument) require | |
18 % a value, default = 100 | |
19 % [mode] (string) 'steps' or 'errlimit' or 'errchange' or 'seconds', | |
20 % see below, default is 'steps' | |
21 % [alpha] (scalar) iteration step size, default = 0.2 | |
22 % [Dist] (matrix) pairwise distance matrix, size dlen x dlen. | |
23 % If the distances in the input space should | |
24 % be calculated otherwise than as euclidian | |
25 % distances, the distance from each vector | |
26 % to each other vector can be given here, | |
27 % size dlen x dlen. For example PDIST | |
28 % function can be used to calculate the | |
29 % distances: Dist = squareform(pdist(D,'mahal')); | |
30 % | |
31 % P (matrix) size dlen x odim, the projections | |
32 % | |
33 % The output dimension must be 2 or higher but (naturally) lower | |
34 % than data set dimension. | |
35 % | |
36 % The mode argument determines the end condition for iteration. If | |
37 % the mode argument is used, also the value argument has to be | |
38 % specified. Different mode possibilities are: | |
39 % 'steps' the iteration is terminated when it is run <value> | |
40 % 'errlimit' steps, the iteration is terminated when projection error | |
41 % is lower than <value>, | |
42 % 'errchange' the iteration is terminated when change between | |
43 % projection error on two successive iteration rounds | |
44 % is less than <value> percent of total error, and | |
45 % 'seconds' the iteration is terminated after <value> seconds | |
46 % of iteration. | |
47 % | |
48 % See also CCA, PCAPROJ, SOM_GRID. | |
49 | |
50 % Reference: Sammon, J.W. Jr., "A nonlinear mapping for data | |
51 % structure analysis", IEEE Transactions on Computers, vol. C-18, | |
52 % no. 5, 1969, pp. 401-409. | |
53 | |
54 % Contributed to SOM Toolbox vs2, February 2nd, 2000 by Juha Vesanto | |
55 % Copyright (c) by Juha Vesanto | |
56 % http://www.cis.hut.fi/projects/somtoolbox/ | |
57 | |
58 % juuso 040100 | |
59 | |
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
61 %% check arguments | |
62 | |
63 error(nargchk(2, 6, nargin)); % check no. of input arguments is correct | |
64 | |
65 % input data | |
66 if isstruct(D), | |
67 if isfield(D, 'data'), D = D.data; % data struct | |
68 elseif isfield(D, 'codebook'), D = D.codebook; % map struct | |
69 else error('Invalid structure'); | |
70 end | |
71 end | |
72 if any(isnan(D(:))), | |
73 error('Cannot make Sammon''s projection for data with unknown components') | |
74 end | |
75 | |
76 % compute data dimensions | |
77 orig_si = size(D); | |
78 dim = orig_si(end); | |
79 noc = prod(orig_si)/dim; | |
80 if length(orig_si)>2, D = reshape(D,[noc dim]); end | |
81 | |
82 % output dimension / initial projection matrix | |
83 if prod(size(P))==1, | |
84 odim = P; | |
85 P = rand(noc,odim)-0.5; | |
86 else | |
87 si = size(P); | |
88 odim = si(end); | |
89 if prod(si) ~= noc*odim, | |
90 error('Initial projection matrix size does not match data size'); | |
91 end | |
92 if length(si)>2, P = reshape(P,[noc odim]); end | |
93 inds = find(isnan(P)); | |
94 if length(inds), P(inds) = rand(size(inds)); end | |
95 end | |
96 if odim > dim | odim < 2, | |
97 error('Output dimension must be within [2, dimension of data]'); | |
98 end | |
99 | |
100 % determine operating mode | |
101 if nargin < 3 | isempty(varargin{1}) | isnan(varargin{1}), value=100; | |
102 else value = varargin{1}; | |
103 end | |
104 | |
105 if nargin < 4 | isempty(varargin{2}) | isnan(varargin{2}), mode='steps'; | |
106 else mode = varargin{2}; | |
107 end | |
108 switch mode, | |
109 case 'steps', runlen = value; | |
110 case 'errlimit', errlimit = value; | |
111 case 'errchange', errchange = value; e_prev = 0; | |
112 case 'seconds', endtime = value; | |
113 otherwise, error(['Illegal mode: ' mode]); | |
114 end | |
115 | |
116 % iteration step size | |
117 if nargin > 4, alpha = varargin{3}; else alpha = NaN; end | |
118 if isempty(alpha) | isnan(alpha), alpha = 0.2; end | |
119 | |
120 % mutual distances | |
121 if nargin > 5, Mdist = varargin{4}; else Mdist = []; end | |
122 | |
123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
124 %% initialization | |
125 | |
126 % these are used quite frequently | |
127 noc_x_1 = ones(noc, 1); | |
128 odim_x_1 = ones(odim,1); | |
129 | |
130 % compute mutual distances between vectors | |
131 if isempty(Mdist) | all(isnan(Mdist(:))), | |
132 fprintf(2, 'computing mutual distances\r'); | |
133 dim_x_1 = ones(dim,1); | |
134 for i = 1:noc, | |
135 x = D(i,:); | |
136 Diff = D - x(noc_x_1,:); | |
137 N = isnan(Diff); | |
138 Diff(find(N)) = 0; | |
139 Mdist(:,i) = sqrt((Diff.^2)*dim_x_1); | |
140 N = find(sum(N')==dim); %mutual distance unknown | |
141 if ~isempty(N), Mdist(N,i) = NaN; end | |
142 end | |
143 else | |
144 % if the distance matrix is output from PDIST function | |
145 if size(Mdist,1)==1, Mdist = squareform(Mdist); end | |
146 if size(Mdist,1)~=noc, | |
147 error('Mutual distance matrix size and data set size do not match'); | |
148 end | |
149 end | |
150 | |
151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
152 %% action | |
153 | |
154 if strcmp(mode, 'seconds'), tic; end; | |
155 fprintf(2, 'iterating \r'); | |
156 | |
157 % sammon iteration | |
158 | |
159 x = P ; | |
160 xu = zeros(noc, odim); | |
161 xd = zeros(noc, odim); | |
162 dq = zeros(noc, 1); | |
163 dr = zeros(noc, 1); | |
164 | |
165 i = 0; | |
166 ready = 0; | |
167 while ~ready | |
168 for j = 1:noc, | |
169 xd = -x + x(j*noc_x_1,:); | |
170 xd2 = xd.^2; | |
171 dpj = sqrt(sum(xd2'))'; | |
172 dq = Mdist(:,j) - dpj; | |
173 dr = Mdist(:,j) .* dpj; | |
174 ind = find(dr ~= 0); | |
175 term = dq(ind) ./ dr(ind); | |
176 e1 = sum(xd(ind,:) .* term(:,odim_x_1)); | |
177 term2 = ((1.0 + dq(ind) ./ dpj(ind)) ./ dpj(ind)) ./ dr(ind); | |
178 e2 = sum(term) - sum(xd2(ind,:) .* term2(:,odim_x_1)); | |
179 xu(j,:) = x(j,:) + alpha * e1 ./ abs(e2); | |
180 end | |
181 | |
182 % move the center of mass to the center | |
183 | |
184 c = sum(xu) / noc; | |
185 x = xu - c(noc_x_1, :); | |
186 | |
187 i = i + 1; | |
188 | |
189 % compute mapping error | |
190 % doing this adds about 25% to computing time | |
191 if 0, | |
192 e = 0; tot = 0; | |
193 for j = 2:noc, | |
194 d = Mdist(1:(j - 1), j); | |
195 tot = tot + sum(d); | |
196 ind = find(d ~= 0); | |
197 xd = -x(1:(j - 1), :) + x(j * ones(j - 1, 1), :); | |
198 ee = d - sqrt(sum(xd'.^2))'; | |
199 e = e + sum(ee(ind).^2 ./ d(ind)); | |
200 end | |
201 e = e/tot; | |
202 fprintf(2, '\r%d iterations, error %f', i, e); | |
203 else | |
204 fprintf(2, '\r%d iterations', i); | |
205 end | |
206 | |
207 % determine is the iteration ready | |
208 | |
209 switch mode | |
210 case 'steps', | |
211 if i == runlen, ready = 1; end; | |
212 case 'errlimit', | |
213 if e < errlimit, ready = 1; end; | |
214 case 'errchange', | |
215 if i > 1 | |
216 change = 100 * abs(e - e_prev) / e_prev; | |
217 if change < errchange, ready = 1; end; | |
218 fprintf(2, ', change of error %f %% ', change); | |
219 end | |
220 e_prev = e; | |
221 case 'seconds' | |
222 if toc > endtime, ready = 1; end; | |
223 fprintf(2, ', elapsed time %f seconds ', toc); | |
224 end | |
225 fprintf(2, ' '); | |
226 | |
227 % If you want to see the Sammon's projection plotted (in 2-D and 3-D case), | |
228 % execute the code below; it is not in use by default to speed up | |
229 % computation. | |
230 if 0, | |
231 clf | |
232 if odim == 1, plot(x(:,1), noc_x_1, 'o'); | |
233 elseif odim == 2, plot(x(:,1), x(:,2), 'o'); | |
234 else plot3(x(:,1), x(:,2), x(:,3), 'o') | |
235 end | |
236 drawnow | |
237 end | |
238 end | |
239 | |
240 fprintf(2, '\n'); | |
241 | |
242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
243 %% clean up | |
244 | |
245 % reshape | |
246 orig_si(end) = odim; | |
247 P = reshape(x, orig_si); | |
248 | |
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |