1 | %GLDBM_TD GLDB using top-down criterion (Fisher separability) |
---|
2 | % |
---|
3 | % W = GLDBM_TD(A) |
---|
4 | % |
---|
5 | % INPUT |
---|
6 | % A Training dataset |
---|
7 | % |
---|
8 | % OUTPUT |
---|
9 | % W best bases mapping |
---|
10 | % |
---|
11 | % DESCRIPTION |
---|
12 | % Generalised Best Bases mapping is a feature extraction technique for |
---|
13 | % spectral datasets with two classes. This function implements the |
---|
14 | % top-down approach starting from a single group with all the wavelengths, |
---|
15 | % recursively identifying the best possible split points. Groups of |
---|
16 | % adjacent features (wavelengths) are identified in the input dataset such |
---|
17 | % that Fisher criterion is maximized in each group. Output dataset is |
---|
18 | % created by projecting wavelengths in each group to the 1D Fisher |
---|
19 | % subspace. The procedure is defined for two class problems, if a |
---|
20 | % multi-class dataset is supplied, a cell array of mappings will be |
---|
21 | % computed. Multi-class classifier, based on this routine, is implemented |
---|
22 | % as PREXP algorithm ALG_GLDBM |
---|
23 | % |
---|
24 | % REFERENCE |
---|
25 | % Kumar,Ghosh,Crawford: Classification of Hyperspectral Data using |
---|
26 | % Best-bases Feature Extraction Algorithm |
---|
27 | % |
---|
28 | % SEE ALSO |
---|
29 | % DATASETS, MAPPINGS, GLDBM |
---|
30 | |
---|
31 | % Copyright: P. Paclik, pavel@ph.tn.tudelft.nl |
---|
32 | % Faculty of Applied Physics, Delft University of Technology |
---|
33 | % P.O. Box 5046, 2600 GA Delft, The Netherlands |
---|
34 | |
---|
35 | % $Id: gldbm_td.m,v 1.5 2005/02/10 15:24:07 pavel Exp $ |
---|
36 | |
---|
37 | function [w,crit] = gldbm_td(a,arg2) |
---|
38 | |
---|
39 | % No arguments given: return untrained mapping. |
---|
40 | |
---|
41 | if (nargin < 1) | (isempty(a)) |
---|
42 | w = mapping(mfilename); |
---|
43 | w = setname(w,'Best Bases mapping (top-down)'); |
---|
44 | return |
---|
45 | end |
---|
46 | |
---|
47 | if (~exist('arg2','var')) % Second argument is not a mapping: training. |
---|
48 | |
---|
49 | isdataset(a); % Assert that A is a dataset. |
---|
50 | |
---|
51 | [m,k,c] = getsize(a); M = classsizes(a); |
---|
52 | |
---|
53 | if c>2 |
---|
54 | % for multi-class problem, create all pair-wise extractors |
---|
55 | w={}; |
---|
56 | iter=[]; |
---|
57 | for i=1:c-1 |
---|
58 | for j=i+1:c |
---|
59 | fprintf(1,'(%d-%d',i,j); |
---|
60 | t=seldat(a,[i j]); |
---|
61 | eval(['w{i,j}=' mfilename '(t);']); |
---|
62 | fprintf(1,') '); |
---|
63 | end |
---|
64 | end |
---|
65 | return |
---|
66 | end |
---|
67 | |
---|
68 | % counter with ten steps |
---|
69 | t=floor(k/10); % usually, only 80% bands is processed |
---|
70 | counts=t*ones(1,10); |
---|
71 | counts(1:mod(m,10))=counts(1:mod(m,10))+1; |
---|
72 | counts=cumsum(counts); |
---|
73 | |
---|
74 | Q=corrcoef(+a); |
---|
75 | [U,G]=meancov(a); |
---|
76 | |
---|
77 | m=0; % level |
---|
78 | Nm=size(a,2); |
---|
79 | |
---|
80 | % in top-down approach, each group of bands is defined by its limits (l,u), |
---|
81 | % flag saying if it should be processed further and a criterion value: |
---|
82 | |
---|
83 | l=1; % lower bounds of group-bands |
---|
84 | u=Nm; % upper bounds of group-bands |
---|
85 | process=1; % should the group be processed? |
---|
86 | I=0; % criterion values for each group |
---|
87 | |
---|
88 | % compute crit for each single band group: |
---|
89 | % I=crit_eval(l,u,Q,+U(1,:),+U(2,:),G(:,:,1),G(:,:,2)); |
---|
90 | |
---|
91 | while 1 |
---|
92 | |
---|
93 | % we'll go over all the groups and process the processable ones: |
---|
94 | temp=find(process==1); |
---|
95 | gid=temp(1); % the 1st group in queue to be processed |
---|
96 | % fprintf(1,' l=%d,u=%d ',l(gid),u(gid)); |
---|
97 | |
---|
98 | % make possible merges: |
---|
99 | % pl and pu refer to the possible left subgroup! |
---|
100 | gc=u(gid)-l(gid)+1; % number of possible left subgroups |
---|
101 | pl=repmat( l(gid), 1, gc-1 ); % possible beginnings of the left new subgroup |
---|
102 | pu=pl(1):u(gid)-1; |
---|
103 | |
---|
104 | % eval criterium for left subgroups: |
---|
105 | crit1=crit_eval(pl,pu,Q,+U(1,:),+U(2,:),G(:,:,1),G(:,:,2)); |
---|
106 | |
---|
107 | % eval criterion for right subgroups: |
---|
108 | crit2=crit_eval(pu+1,repmat(u(gid),1,gc-1),Q,+U(1,:),+U(2,:),G(:,:,1),G(:,:,2)); |
---|
109 | |
---|
110 | maxval=max([crit1; crit2]); |
---|
111 | [maxval,ind]=max(maxval); |
---|
112 | |
---|
113 | newcrit=[crit1(ind) crit2(ind)]; |
---|
114 | |
---|
115 | % pu(ind) is the best possible splitting index |
---|
116 | |
---|
117 | % decide which of the two new subgroups should be processed further |
---|
118 | newprocess=[0 0]; % by default: don't process |
---|
119 | if crit1(ind)>I(gid) & ind>1 |
---|
120 | % decompose the left subgroup |
---|
121 | newprocess(1)=1; |
---|
122 | end |
---|
123 | if crit2(ind)>I(gid) & gc-ind>1 |
---|
124 | % decompose the left subgroup |
---|
125 | newprocess(2)=1; |
---|
126 | end |
---|
127 | |
---|
128 | % update high-level group definition: |
---|
129 | if gid==1 |
---|
130 | % we're splitting the firrst group |
---|
131 | l=[ 1 pu(ind)+1 l(2:end)]; |
---|
132 | u=[ pu(ind) u(1) u(2:end)]; |
---|
133 | process=[newprocess process(2:end)]; |
---|
134 | I=[newcrit I(2:end)]; |
---|
135 | elseif gid==Nm |
---|
136 | % we're splitting the last group |
---|
137 | l=[ l(1:end-1) l(gid) pu(ind)+1]; |
---|
138 | u=[ u(1:end-1) pu(ind) Nm]; |
---|
139 | process=[process(1:end-1) newprocess]; |
---|
140 | I=[I(1:end-1) newcrit]; |
---|
141 | else |
---|
142 | % we're in the middle |
---|
143 | l=[ l(1:gid-1) l(gid) pu(ind)+1 l(gid+1:end)]; |
---|
144 | u=[ u(1:gid-1) pu(ind) u(gid) u(gid+1:end)]; |
---|
145 | process=[process(1:gid-1) newprocess process(gid+1:end)]; |
---|
146 | I=[I(1:gid-1) newcrit I(gid+1:end)]; |
---|
147 | end |
---|
148 | fprintf(1,'(%d) ', sum(process)); |
---|
149 | |
---|
150 | if isempty(find(process==1)) |
---|
151 | % no candidates for progress left, return what |
---|
152 | % we have at the moment. |
---|
153 | [crit,clf]=crit_eval(l,u,Q,+U(1,:),+U(2,:),G(:,:,1),G(:,:,2)); |
---|
154 | |
---|
155 | % parameters |
---|
156 | pars.clf=clf; pars.l=l; pars.u=u; pars.info_iter=m; |
---|
157 | w = mapping(mfilename,'trained',pars,(1:length(l))',k,length(pars.l)); |
---|
158 | w = setname(w,'Best Bases mapping (top-down)'); |
---|
159 | |
---|
160 | return |
---|
161 | end |
---|
162 | end % while |
---|
163 | else % Second argument is a a mapping: testing. |
---|
164 | |
---|
165 | w = arg2; |
---|
166 | pars = getdata(w); % Unpack the mapping. |
---|
167 | [m,k] = getsize(a); |
---|
168 | |
---|
169 | % create an output dataset |
---|
170 | out=[]; |
---|
171 | for i=1:length(pars.clf) |
---|
172 | % get the subset of bands... |
---|
173 | t=+a(:,pars.l(i):pars.u(i)); |
---|
174 | % ... and project it to 1D Fisher subspace |
---|
175 | out=[out t*pars.clf(i).w]; |
---|
176 | end |
---|
177 | |
---|
178 | w = setdat(a,out); |
---|
179 | w=setfeatlab(w,(1:size(w,2))'); |
---|
180 | end |
---|
181 | |
---|
182 | return |
---|
183 | |
---|
184 | |
---|
185 | |
---|
186 | function [I,clf]=crit_eval(l,u,Q,mua,mub,sigmaa,sigmab) |
---|
187 | |
---|
188 | I=zeros(1,length(l)); |
---|
189 | |
---|
190 | clf=[]; |
---|
191 | for i=1:length(l) |
---|
192 | |
---|
193 | C=min(min( Q( l(i):u(i), l(i):u(i) ) )); |
---|
194 | |
---|
195 | W=0.5*( sigmaa( l(i):u(i), l(i):u(i) )+sigmab( l(i):u(i), l(i):u(i) ) ); |
---|
196 | t=( mua( l(i):u(i) ) - mub( l(i):u(i) ) )'; |
---|
197 | B=t*t'; |
---|
198 | |
---|
199 | w=pinv(W)*t; |
---|
200 | D=(w'*B*w)/(w'*W*w); |
---|
201 | |
---|
202 | I(i)=C*D; |
---|
203 | |
---|
204 | clf(i).w=w; |
---|
205 | end |
---|
206 | |
---|
207 | |
---|