source: distools/ksvo.m @ 89

Last change on this file since 89 was 10, checked in by bduin, 14 years ago
File size: 5.9 KB
Line 
1%KSVO Kernel Support Vector Optimizer
2%
3%   [V,J,T,REG] = KSVO(K,Y,C,R)
4%
5% INPUT
6%   K   Kernel or a square similarity matrix
7%   Y   Label list consisting of -1/+1
8%   C   Scalar for weighting the errors (optional; default: 1)
9%   R   Parameter: -1,0,1,2
10%       -1 or 'flip',   Changes the kernel by flipping negative eigenvalues to
11%          positive
12%        0 or '',       Uses the kernel as it is
13%        1 or 'reg',    Checks positive definiteness and regularizes the kernel by
14%          adding the minimal constant in the form of 10^i to the diagonal
15%        2 or 'lamreg', Checks positive definiteness and regularizes the kernel by
16%          adding the minimal constant to the diagonal (equal to the magnitude of
17%          the smallest negative eigenvalue)
18%       (optional; default: 0, do not change the kernel)
19%
20% OUTPUT
21%   V   Vector of weights for the support vectors
22%   J   Index vector pointing to the support vectors
23%   T   Transformation matrix for the test kernel; to be used in testing
24%   REG Regularization parameter added to the diagonal, if used (R=1,2); a vector
25%       of eigenvalues of K (R=-1), or -1 if not checked (R=0)
26%
27% DESCRIPTION
28% A low level routine that optimizes the set of support vectors for a two-class
29% classification problem based on the kernel or similarity matrix K. KSVO is called
30% directly from KSVC. The labels Y should indicate the two classes by +1 and -1.
31% Optimization is done by a quadratic programming. If available, the QLD function
32% is used for a positive definite kernel, otherwise an appropriate Matlab routine.
33%
34% SEE ALSO
35% KSVC, SVC, SVO
36
37% Copyright: Elzbieta Pekalska, Robert P.W. Duin, ela.pekalska@googlemail.com
38% Based on SVC.M by D.M.J. Tax, D. de Ridder and R.P.W. Duin
39% Faculty EWI, Delft University of Technology and
40% School of Computer Science, University of Manchester
41
42
43function [v,J,T,reg,err] = ksvo(K,y,C,r)
44prtrace(mfilename);
45
46if (nargin < 4),
47  r = 0;      % Default: the kernel is used as provided
48end
49if (nargin < 3)
50  prwarning(3,'Third parameter not specified, assuming 1.');
51  C = 1;
52end
53
54if all(r ~= [-1,0,1,2]),
55  error('Wrong parameter R.');
56end
57
58err  = 0;
59v    = [];     % Weights of the SVM
60J    = [];     % Index of support vectors
61reg = -1;      % Regularization on the diagonal or a list of eigenvalues, if used; -1, if not checked
62vmin = 1e-9;   % Accuracy to determine when an object becomes the support object
63iacc = -14;    % Accuracy of 10^i to determine whether the kernel is pd or not
64T    = [];     % Matrix to transform the test kernel if r = -1
65
66% Set up variables for the optimization.
67n  = size(K,1);
68Ky = (y*y').*K;
69f  = -ones(1,n);
70A  = y';
71b  = 0;
72lb = zeros(n,1);
73ub = repmat(C,n,1);
74p  = rand(n,1);
75
76
77if r ~= 0,
78  % Find whether the kernel is positive definite.
79  i = -20;
80  while (pd_check (Ky + (10.0^i) * eye(n)) == 0)
81    i = i + 1;
82  end
83
84  if r == 1,
85    if i > iacc,  % if i is smaller, then the regularization is within numerical accuracy
86      prwarning(1,'K is not positive definite. The diagonal is regularized by 10.0^(%d)',i);
87    end
88
89    % Make the kernel positive definite by adding a constant to the diagonal.
90    reg = 10.0^i;
91    Ky  = Ky + (10.0^(i)) * eye(n);
92
93  elseif r == 2,
94    L = preig(Ky);
95    L = diag(real(L));
96    I = find(L < 0);
97    if ~isempty(I),
98      % Make the kernel positive definite by adding a constant to the diagonal.
99      reg = -1.001*min(L(I));
100      Ky  = Ky + reg * eye(n);
101      pow = round(log10(reg));
102      if pow >= 0
103        prwarning(1,['K is not positive definite. The diagonal is regularized by %' num2str(pow) '.2f'],reg);
104      elseif pow > iacc,
105        prwarning(1,['K is not positive definite. The diagonal is regularized by %0.3g'], reg);
106      else
107        ;
108      end
109    else
110      reg = 0;
111    end
112
113  else   % r = -1,
114    % reverse the negative eigenvalues of the kernel K
115    if i >= iacc,
116      [Q,L] = preig(K);
117      Q     = real(Q);
118      L     = diag(real(L));
119      reg   = L;
120      if all(L >= 0),
121        T = [];
122      else
123        K   = Q*diag(abs(L))*Q';
124        Ky  = (y*y').*K;
125        T   = Q* diag(sign(L)) *Q';   % transformation matrix for the test kernel
126      end
127    else
128      % if i < iacc, then the regularization is within numerical accuracy, so apply it
129      Ky    = Ky + (10.0^(i)) * eye(n);
130    end
131  end
132end
133
134
135% Minimization procedure
136% QP  minimizes:   0.5 x'*Ky*x + f'x
137% subject to:      Ax <= b
138%
139
140done = 0;
141if r ~= 0 & (exist('qld') == 3)
142  prwarning(5,'QLD routine is used.')
143  v = qld (Ky, f, -A, b, lb, ub, p, 2);
144  done = 1;
145end
146
147if r == 0 | ~done,
148  if (exist('quadprog') == 2)
149    prwarning(5,'Matlab QUADPROG is used.')
150    opt = optimset;
151    opt.Diagnostics = 'off';
152    opt.LargeScale  = 'off';
153    opt.Display     = 'off';
154    opt.MaxIter     = 500;
155    v = quadprog(Ky, f, [], [], A, b, lb, ub,[],opt);
156  else
157    error(5,'KSVC requires Matlab 6.x')
158  end
159end
160
161
162
163% Compute the square pseudo-norm of the weights in the corresponding
164% Hilbert/Krein space. If it is negative (which may happen for a highly
165% indefinite kernel), then the SVM is not proper.
166
167vnorm = v'*Ky*v;
168if vnorm < 0 | abs(vnorm) < 10^iacc,
169  prwarning(1,'SVM: ||w||^2_PE < 0. The SVM is not properly defined. Pseudo-Fisher is computed instead.');
170  err = 1;
171  v   = prpinv([K ones(n,1)])*y;
172  J   = [1:n]';
173  return;
174end
175
176
177% Find all support vectors SVs.
178J = find(v > vmin);
179
180% First find the SVs on the boundary
181I  = find((v > vmin) & (v < C-vmin));
182Ip = find(y(I) ==  1);
183Im = find(y(I) == -1);
184
185if (isempty(v) | isempty(Ip) | isempty(Im))
186  prwarning(1,'Quadratic Optimization failed. Pseudo-Fisher is computed instead.');
187  err = 1;
188  v   = prpinv([K ones(n,1)])*y;
189  J   = [1:n]';
190  return;
191end
192
193
194v = y.*v;
195
196% Find the output for the SVs:
197out = y(I)-(K(I,J)*v(J));
198b   = mean(out);
199v   = [v(J); b];
200return;
Note: See TracBrowser for help on using the repository browser.