%STACKED Combining classifiers in the same feature space % % WC = STACKED(W1,W2,W3, ....) or WC = [W1,W2,W3, ...] % WC = STACKED({W1,W2,W3, ...}) or WC = [{W1,W2,W3, ...}] % WC = STACKED(WC,W1,W2, ....) or WC = [WC,W2,W3, ...] % % INPUT % W1,W2,W3 Set of classifiers % % OUTPUT % WC Combined classifier % % DESCRIPTION % The base classifiers (or mappings) W1, W2, W3, ... defined in the same % feature space are combined in WC. This is a classifier defined for the % same number of features as each of the base classifiers and with the % combined set of outputs. So, for three two class classifiers defined for % the classes 'c1' and 'c2', a dataset A is mapped by D = A*WC on the outputs % 'c1','c2','c1','c2','c1','c2', which are the feature labels of D. Note that % classification by LABELD(D) finds for each vector in D the feature label % of the column with the maximum value. This is equivalent to using the % maximum combiner MAXC, % % Other fixed combining rules like PRODC, MEANC, and VOTEC can be applied by % D = A*WC*PRODC. A trained combiner like FISHERC has to be supplied with % the appropriate training set by AC = A*WC; VC = AC*FISHERC. So the % expression VC = A*WC*FISHERC yields a classifier, not a dataset as with % fixed combining rules. This classifier operates in the intermediate % feature space, the output space of the set of base classifiers. A new % dataset B has to be mapped to this intermediate space first by BC = B*WC % before it can be classified by D = BC*VC. As this is equivalent to D = % B*WC*VC, the total trained combiner is WTC = WC*VC = WC*A*WC*FISHERC. To % simplify this procedure PRTools executes the training of a combined % classifier by WTC = A*(WC*FISHERC) as WTC = WC*A*WC*FISHERC. % % It is also possible to combine a set of untrained classifiers, e.g. WC = % [LDC NMC KNNC([],1)]*CLASSC, in which CLASSC takes care that all outputs % will be transformed to appropriate posterior probabilities. Training of % all base classifiers is done by WC = A*WC. Again, this may be combined % with training of a combiner by WTC = A*(WC*FISHERC). % % EXAMPLES % PREX_COMBINING % SEE ALSO (PRTools Guide) % MAPPINGS, DATASETS, MAXC, MINC, MEANC, % MEDIANC, PRODC, FISHERC, PARALLEL % Copyright: R.P.W. Duin, r.p.w.duin@37steps.com function w = stacked(varargin) % No arguments given: just return map information. if (nargin == 0) w = prmapping(mfilename,'combiner'); return end % Single argument: should be a mapping or cell array of mappings. if (nargin == 1) v = varargin{1}; % If V is a single mapping, process it directly. if (~iscell(v)) if (~isa(v,'prmapping')) error('Mapping expected.') end w = prmapping('stacked',getmapping_type(v),{v},getlabels(v)); w = set(w,'size',getsize(v)); else % If V is a cell array of mappings, call this function recursively. if (size(v,1) ~= 1) error('Row of cells containing mappings expected') end w = feval(mfilename,v{:}); end return end % Multiple arguments, all of which are mappings: combine them. if (~(isa(varargin{1},'prdataset') | (isa(varargin{1},'double') & ~isempty(varargin{1})))) % Get the first mapping. v1 = varargin{1}; if (isempty(v1)) start = 3; v1 = varargin{2}; else start = 2; end ismapping(v1); % Assert V1 is a mapping. k = prod(getsize_in(v1)); labels = getlabels(v1); type = getmapping_type(v1); % If V1 is already a stacked mapping without output conversion, % unpack it to re-stack. if (~strcmp(getmapping_file(v1),mfilename)) | getout_conv(v1) > 1 v = {v1}; else v = getdata(v1); end % Now stack the second to the last mapping onto the first. for j = start:nargin v2 = varargin{j}; if (~strcmp(type,getmapping_type(v2))) error('All mappings should be of the same type.') end if (getsize(v2,1) ~= k) error('Mappings should have equal numbers of inputs.') end v = [v {v2}]; if ischar(labels) labels = char(labels,getlabels(v2)); elseif iscell(labels) labels = {labels{:} getlabels(v2)}; else labels = [labels;getlabels(v2)]; end end w = prmapping('stacked',type,v,labels,k); elseif isdatafile(varargin{1}) % datafile * stacked mapping: store it as postprocessing w = addpostproc(varargin{1},stacked(varargin{2:end})); else % The first argument is a dataset: apply the stacked mapping. a = varargin{1}; v = varargin{2}; if (~isa(v,'prmapping')) error('Mapping expected as second argument.') end if nargin==2 & isstacked(v) n = length(v.data); else v = varargin(2:end); n = nargin-1; end % Calculate W, the output of the stacked mapping on A. w = []; if n > 2 s = sprintf('Concatenating %i mappings: ',n); prwaitbar(n,s); end for j = 1:n if n > 2, prwaitbar(n,j,[s int2str(j)]); end b = a*v{j}; % If, for a mapping to 1D (e.g. a 2-class discriminant) % more than 1 output is returned, truncate. if (size(v{j},2) == 1) b = b(:,1); end w = [w b]; % Concatenate the outputs. end if n > 2 prwaitbar(0); end end return