function red_model = rsrbf(model,options)
% RSRBF Redused Set Method for RBF kernel expansion.
%
% Synopsis:
% red_model = rsrbf(model)
% red_model = rsrbf(model,options)
%
% Description:
% red_model = rsrbf(model) searchs for a kernel expansion
% with nsv vectors which best approximates the input
% expansion given in model [Schol98a]. The Radial Basis
% kernel (RBF) is assumed (see 'help kernel').
%
% red_model = rsrbf(model,options) allows to specify the
% control paramaters.
%
% Input:
% model [struct] Kernel expansion:
% .Alpha [nsv x 1] Weight vector.
% .sv.X [dim x nsv] Vectors defining the expansion.
% .options.ker [string] Must be equal to 'rbf'.
% .options.arg [1x1] Kernel argument (see 'help kernel').
%
% options [struct] Control parameters:
% .nsv [1x1] Desired number of vectors in the reduced
% expansion (default round(length(model.Alpha)/2)).
% .eps [1x1] Desier limit on the norm of difference between
% the original normal vector and the reduced the normal
% vector in the feature space. The algorithm is stopped
% when a lower difference is achived (default 1e-6).
% .preimage [string] Function called to solve the RBF pre-image
% problem (default 'rbfpreimg');
% .verb [1x1] If 1 then progress info is display (default 0).
%
% Output:
% red_model [struct] Reduced kernel expansion.
%
% Example:
% trn = load('riply_trn');
% model = smo(trn,struct('ker','rbf','arg',1,'C',10));
% red_model = rsrbf(model,struct('nsv',10));
% figure; ppatterns(trn);
% h1 = pboundary(model,struct('line_style','r'));
% h2 = pboundary(red_model,struct('line_style','b'));
% legend([h1(1) h2(1)],'Original SVM','Reduced SVM');
%
% See also
% RBFPREIMG.
%
% About: Statistical Pattern Recognition Toolbox
% (C) 1999-2003, Written by Vojtech Franc and Vaclav Hlavac
% <a href="http://www.cvut.cz">Czech Technical University Prague</a>
% <a href="http://www.feld.cvut.cz">Faculty of Electrical Engineering</a>
% <a href="http://cmp.felk.cvut.cz">Center for Machine Perception</a>
% Modifications:
% 11-oct-2004, VF, knorm.m used
% 21-sep-2004, VF
% 10-jun-2004, VF
% 02-dec-2003, VF
if nargin < 2, options=[]; else options = c2s(options); end
if ~isfield(options,'nsv'), options.nsv = round(length(model.Alpha)/2); end
if ~isfield(options,'eps'), options.eps = 1e-6; end
if ~isfield(options,'preimage'), options.preimage = 'rbfpreimg2'; end
if ~isfield(options,'verb'), options.verb = 0; end
Z=[];
Beta = [];
Alpha = model.Alpha(:);
X = model.sv.X;
Const = knorm(X,Alpha,model.options.ker,model.options.arg)^2;
error = inf;
iter = 0;
while error > options.eps & iter < options.nsv,
iter = iter + 1;
if options.verb,
fprintf('Iteration %d: ', iter);
end
tmp_model.Alpha = Alpha;
tmp_model.sv.X = X;
tmp_model.options = model.options;
if options.verb,
fprintf('computing preimage, ');
end
Z = [Z, feval( options.preimage,tmp_model)];
Kz = kernel( Z, model.options.ker, model.options.arg );
Kzs = kernel( Z, model.sv.X, model.options.ker, model.options.arg );
Beta = inv( Kz ) * Kzs * model.Alpha(:);
error = Const + Beta'*Kz*Beta - 2*Beta'*Kzs*model.Alpha(:);
if options.verb,
fprintf('||w-w_red||^2 = %f\n', error);
end
Alpha = [model.Alpha(:); -Beta(:)]';
X = [model.sv.X, Z];
end
red_model = model;
red_model.Alpha = Beta;
red_model.sv.X = Z;
red_model.nsv = size(Z,2);
return;