1 | %Auxiliary script for incsvc. |
---|
2 | %I especially did not make it a function to avoid a ton of arguments to |
---|
3 | %pass. Maybe it gives a small speedup... |
---|
4 | |
---|
5 | %fprintf('Add object number %d\n',c); |
---|
6 | % currently seen objects plus new object |
---|
7 | newsetD = (1:c)'; |
---|
8 | |
---|
9 | % compute the kernel matrix entry for the new object: |
---|
10 | % (let us assume this is a row vector) |
---|
11 | K = feval(kernel,kpar,c,newsetD); |
---|
12 | Kc = (y(c)*y(newsetD)').*K; |
---|
13 | |
---|
14 | % % first see if the object is accepted or not |
---|
15 | % % (note that I could also have looked at the gradient, but then I |
---|
16 | % % don't have a very honest 'distance to the boundary') |
---|
17 | % this_label = K(c) - b; |
---|
18 | % if ~isempty(setS) |
---|
19 | % this_label = this_label - K(setS)*(y(setS).*alf(setS)); |
---|
20 | % end |
---|
21 | % if ~isempty(setE) |
---|
22 | % this_label = this_label - K(setE)*(y(setE).*alf(setE)); |
---|
23 | % end |
---|
24 | |
---|
25 | % Compute the gradient for the new object: |
---|
26 | grad(c,1) = y(c)*b - 1; %DXD here is a change for SVC |
---|
27 | if ~isempty(setS) |
---|
28 | grad(c,1) = grad(c,1) + Kc(setS)*alf(setS); |
---|
29 | end |
---|
30 | if ~isempty(setE) |
---|
31 | grad(c,1) = grad(c,1) + Kc(setE)*alf(setE); |
---|
32 | end |
---|
33 | |
---|
34 | % Right, here we go, can be add object c?: |
---|
35 | if grad(c)>0 % it is already classified ok, |
---|
36 | if length(setR)>0 |
---|
37 | setR = [setR;c]; % put in the 'rest' set |
---|
38 | Kr = [Kr; Kc(setS)]; % update Kr |
---|
39 | else |
---|
40 | setR = c; |
---|
41 | Kr = Kc(setS); |
---|
42 | end |
---|
43 | |
---|
44 | else % we have to work |
---|
45 | |
---|
46 | done = 0; % to check if we are done |
---|
47 | nrloops=0; |
---|
48 | while ~done |
---|
49 | |
---|
50 | % compute beta, not for the new object: |
---|
51 | beta = zeros(length(setS)+1,1); |
---|
52 | beta = -R*[y(c); Kc(setS)']; |
---|
53 | |
---|
54 | if any(beta>1e100) & ~isempty(setS) |
---|
55 | disp('Beta is too large: do you have identical objects with different labels??'); keyboard; |
---|
56 | end |
---|
57 | |
---|
58 | % compute gamma, also for the new object: |
---|
59 | if isempty(setS) |
---|
60 | % here something fishy is going on, when there is just a single |
---|
61 | % object added. Then we cannot freely move alf, and we can only |
---|
62 | % move b. In this case, b is moved until alf(c) enters setS |
---|
63 | % (that means, the gradient becomes 0). |
---|
64 | gamma = y(c)*y(newsetD); |
---|
65 | duptonow = y(c)*b; |
---|
66 | else |
---|
67 | gamma = Kc'; |
---|
68 | if ~isempty(setE) |
---|
69 | gamma(setE) = gamma(setE) + [y(setE) Ke]*beta; |
---|
70 | end |
---|
71 | if ~isempty(setR) |
---|
72 | gamma(setR) = gamma(setR) + [y(setR) Kr]*beta; |
---|
73 | end |
---|
74 | gamma(c) = gamma(c) + [y(c) Kc(setS)]*beta; |
---|
75 | gamma(setS) = 0; |
---|
76 | duptonow = alf(c); |
---|
77 | end |
---|
78 | |
---|
79 | % now we have to see how large deltaAc can become... |
---|
80 | % (1) check the own upper bound: |
---|
81 | if isempty(setS) |
---|
82 | deltaAcisC = inf; %because we're moving b, and not alf! |
---|
83 | else |
---|
84 | deltaAcisC = C; |
---|
85 | end |
---|
86 | % (2) check if own gradient becomes zero: |
---|
87 | warning off; |
---|
88 | deltaGcis0 = duptonow-grad(c)./gamma(c); |
---|
89 | warning on; |
---|
90 | % object moves the wrong way: |
---|
91 | deltaGcis0(deltaGcis0<duptonow) = inf; |
---|
92 | % (3) check upper bounds of the SVs: |
---|
93 | deltaupperC = inf; |
---|
94 | if ~isempty(setS) |
---|
95 | warning off; |
---|
96 | deltaupperC = duptonow + (C-alf(setS))./beta(2:end); |
---|
97 | warning on; |
---|
98 | % negative changes do not count: |
---|
99 | deltaupperC(deltaupperC<duptonow) = inf; |
---|
100 | % object moves the wrong way (or not at all): |
---|
101 | deltaupperC(beta(2:end)<=0) = inf; |
---|
102 | [deltaupperC,nrS_up] = min(deltaupperC); |
---|
103 | end |
---|
104 | % (4) check lower bounds of the SVs: |
---|
105 | deltalowerC = inf; |
---|
106 | if ~isempty(setS) |
---|
107 | warning off; |
---|
108 | deltalowerC = duptonow + -alf(setS)./beta(2:end); |
---|
109 | warning on; |
---|
110 | % negative changes do not count: |
---|
111 | deltalowerC(deltalowerC<=duptonow) = inf; |
---|
112 | % object moves the wrong way (or not at all) |
---|
113 | deltalowerC(beta(2:end)>=0) = inf; |
---|
114 | [deltalowerC,nrS_low] = min(deltalowerC); |
---|
115 | end |
---|
116 | % (5) check E gradients to become 0: |
---|
117 | deltaGeis0 = inf; |
---|
118 | if ~isempty(setE) |
---|
119 | warning off; % divide by 0 is taken care of later... |
---|
120 | deltaGeis0 = duptonow -grad(setE)./gamma(setE); |
---|
121 | warning on; |
---|
122 | deltaGeis0(deltaGeis0<duptonow) = inf; |
---|
123 | deltaGeis0(gamma(setE)<=0) = inf; |
---|
124 | [deltaGeis0,nrE_0] = min(deltaGeis0); |
---|
125 | end |
---|
126 | % (6) check R gradients to become 0: |
---|
127 | deltaGris0 = inf; |
---|
128 | if ~isempty(setR) |
---|
129 | warning off; % divide by 0 is taken care of later... |
---|
130 | deltaGris0 = duptonow -grad(setR)./gamma(setR); |
---|
131 | warning on; |
---|
132 | %deltaGris0(deltaGris0<duptonow) = inf; |
---|
133 | deltaGris0(deltaGris0<=duptonow) = inf; |
---|
134 | deltaGris0(gamma(setR)>=0) = inf; |
---|
135 | [deltaGris0,nrG_0] = min(deltaGris0); |
---|
136 | end |
---|
137 | |
---|
138 | % which one is the most urgent one? |
---|
139 | deltas = [deltaAcisC; deltaGcis0; deltaupperC; deltalowerC;... |
---|
140 | deltaGeis0; deltaGris0]; |
---|
141 | [maxdelta,situation] = min(deltas); |
---|
142 | % fprintf('Situation %d (max_delta=%f)\n',situation,maxdelta); |
---|
143 | % |
---|
144 | % update the parameters |
---|
145 | if isempty(setS) % then we only change b: |
---|
146 | %disp('setS is empty!'); |
---|
147 | b = y(c)*maxdelta; |
---|
148 | else |
---|
149 | alf(c) = maxdelta; |
---|
150 | alf(setS) = alf(setS) + (maxdelta-duptonow)*beta(2:end); |
---|
151 | b = b + (maxdelta-duptonow)*beta(1); |
---|
152 | %fprintf(' b: %f -> %f\n',bold,b); |
---|
153 | %alf' |
---|
154 | %fprintf('after: sum alf = %f\n',sum(alf)); |
---|
155 | end |
---|
156 | grad = grad + (maxdelta-duptonow)*gamma; |
---|
157 | |
---|
158 | % do consistency check: |
---|
159 | I = find(alf<tol); |
---|
160 | if ~isempty(I) |
---|
161 | J = find(alf(I)<-tol); |
---|
162 | % if ~isempty(J) |
---|
163 | % disp('One of the alpha''s became < 0!'); |
---|
164 | % alf(I(J)) |
---|
165 | % keyboard; |
---|
166 | % end |
---|
167 | alf(I) = 0; |
---|
168 | end |
---|
169 | |
---|
170 | % update the sets: |
---|
171 | %fprintf('%d: situation %d \n',c,situation); |
---|
172 | switch situation |
---|
173 | case 1 % object c goes to setE |
---|
174 | alf(c) = C; % just to be sure... |
---|
175 | if size(Ke,1)==0, Ke = []; end % make it really empty |
---|
176 | Ke = [Ke; Kc(setS)]; |
---|
177 | setE = [setE; c]; |
---|
178 | done = 1; |
---|
179 | case 2 % object c goes to setS |
---|
180 | Ks = [Ks [y(c); Kc(setS)']; y(c) Kc([setS; c])]; |
---|
181 | Ke = [Ke Kc(setE)']; |
---|
182 | Kr = [Kr Kc(setR)']; |
---|
183 | % update R |
---|
184 | if isempty(setS) % compute it directly (to avoid the inf's)... |
---|
185 | R = [-Kc(c) y(c); y(c) 0]; |
---|
186 | else |
---|
187 | R = change_R(R,+c,beta,gamma(c)); |
---|
188 | end |
---|
189 | setS = [setS;c]; |
---|
190 | done = 1; |
---|
191 | case 3 % a support object hits upper bound |
---|
192 | j = setS(nrS_up); % number of the object |
---|
193 | alf(j) = C; % just to be sure |
---|
194 | if size(Ke,1)==0, Ke=[]; end % make it really really empty |
---|
195 | Ke = [Ke; Ks(nrS_up+1,2:end)]; % update Ke |
---|
196 | setE = [setE;j]; % add to setE |
---|
197 | Ks(nrS_up+1,:) = []; % update all K's |
---|
198 | Ks(:,nrS_up+1) = []; |
---|
199 | Ke(:,nrS_up) = []; |
---|
200 | if ~isempty(Kr), Kr(:,nrS_up) = []; end |
---|
201 | setS(nrS_up) = []; % remove from setS |
---|
202 | R = change_R(R,-nrS_up,beta,gamma(j)); |
---|
203 | case 4 % a support object hits lower bound |
---|
204 | j = setS(nrS_low); % number of the object |
---|
205 | alf(j) = 0; % just to be sure |
---|
206 | if size(Kr,1)==0, Kr = []; end % make really empty |
---|
207 | Kr = [Kr; Ks(nrS_low+1,2:end)]; % update Kr |
---|
208 | setR = [setR;j]; % add to setE |
---|
209 | Ks(nrS_low+1,:) = []; % update all K's |
---|
210 | Ks(:,nrS_low+1) = []; |
---|
211 | if ~isempty(Ke), Ke(:,nrS_low) = []; end; |
---|
212 | if ~isempty(Kr), Kr(:,nrS_low) = []; end; |
---|
213 | setS(nrS_low) = []; % remove from setS |
---|
214 | R = change_R(R,-nrS_low,beta,gamma(j)); |
---|
215 | case 5 % an error becomes a support object |
---|
216 | j = setE(nrE_0); % number of the object |
---|
217 | % adding to setS, means that all kernels have to be computed: |
---|
218 | K = feval(kernel,kpar,j,newsetD); |
---|
219 | Kj = (y(j)*y(newsetD)').*K; |
---|
220 | % to update R, we have to have the beta of object j: |
---|
221 | betaj = zeros(length(setS)+1,1); |
---|
222 | betaj = -R*[y(j); Kj(setS)']; |
---|
223 | Ks = [Ks; y(j) Kj(setS)]; % add row to Ks |
---|
224 | Kr = [Kr Kj(setR)']; % update Kr |
---|
225 | Ke = [Ke Kj(setE)']; % update Ke |
---|
226 | Ke(nrE_0,:) = []; |
---|
227 | setE(nrE_0) = []; % update setE |
---|
228 | setS = [setS;j]; % add to setS |
---|
229 | Ks = [Ks [y(j); Kj(setS)']]; % and the extra column for Ks |
---|
230 | if length(betaj)==1 % compute it directly (to avoid the inf's)... |
---|
231 | R = [-Kj(j) y(j); y(j) 0]; |
---|
232 | else |
---|
233 | % to update R, we also have to have the gamma of object j: |
---|
234 | gammaj = Ks(end,:)*[betaj;1] ; |
---|
235 | R = change_R(R,+j,betaj,gammaj); |
---|
236 | end |
---|
237 | case 6 % an other object becomes a support object |
---|
238 | j = setR(nrG_0); % number of the object |
---|
239 | % adding to setS, means that all kernels have to be computed: |
---|
240 | K = feval(kernel,kpar,j,newsetD); |
---|
241 | Kj = (y(j)*y(newsetD)').*K; |
---|
242 | % to update R, we have to have the beta of object j: |
---|
243 | betaj = zeros(length(setS)+1,1); |
---|
244 | betaj = -R*[y(j); Kj(setS)']; |
---|
245 | Ks = [Ks; y(j) Kj(setS)]; % add row to Ks |
---|
246 | Ks = [Ks [y(j); Kj([setS;j])']]; % and the extra column for Ks |
---|
247 | Ke = [Ke Kj(setE)']; % update Ke |
---|
248 | Kr = [Kr Kj(setR)']; % update Kr |
---|
249 | Kr(nrG_0,:) = []; |
---|
250 | setS = [setS;j]; % add to setS |
---|
251 | setR(nrG_0) = []; % update setR |
---|
252 | if length(betaj)==1 % compute it directly (to avoid the inf's)... |
---|
253 | R = [-Kj(j) y(j); y(j) 0]; |
---|
254 | else |
---|
255 | % to update R, we also have to have the gamma of object j: |
---|
256 | gammaj = Ks(end,:)*[betaj;1] ; |
---|
257 | R = change_R(R,+j,betaj,gammaj); |
---|
258 | end |
---|
259 | end |
---|
260 | %fprintf('end situation\n'); |
---|
261 | %alf,b |
---|
262 | nrloops = nrloops+1; |
---|
263 | %fprintf('nrloops = %d\n',nrloops); |
---|
264 | if nrloops>50, done=1; end |
---|
265 | %keyboard |
---|
266 | end % changing alfa's till stable solution is found |
---|
267 | end % check for gradient<=0 |
---|
268 | |
---|
269 | |
---|
270 | % now we can also compute the R, compute the output for the x(setS): |
---|
271 | % But fortunately, this value is |
---|
272 | % R^2 = offset + b; |
---|
273 | % If we ignore the offset, we just have to use b! |
---|
274 | |
---|
275 | |
---|