[5] | 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 | |
---|