Daniel@0: function sM = som_supervised(sData,varargin) Daniel@0: Daniel@0: %SOM_SUPERVISED SOM training which utilizes class information. Daniel@0: % Daniel@0: % sM = som_supervised(sData, [ArgID, value,...])) Daniel@0: % Daniel@0: % Input and output arguments ([]'s are optional) Daniel@0: % sData (struct) data struct, the class information is Daniel@0: % taken from the first column of .labels field Daniel@0: % [argID, (string) See below. These are given as Daniel@0: % value] (varies) 'argID', value -pairs. Daniel@0: % Daniel@0: % sMap (struct) map struct Daniel@0: % Daniel@0: % Here are the argument IDs and corresponding values: Daniel@0: % 'munits' (scalar) the preferred number of map units Daniel@0: % 'msize' (vector) map grid size Daniel@0: % 'mask' (vector) BMU search mask, size dim x 1 Daniel@0: % 'name' (string) map name Daniel@0: % 'comp_names' (string array / cellstr) component names, size dim x 1 Daniel@0: % 'tracking' (scalar) how much to report, default = 1 Daniel@0: % The following values are unambiguous and can therefore Daniel@0: % be given without the preceeding argument ID: Daniel@0: % 'algorithm' (string) training algorithm: 'seq' or 'batch' Daniel@0: % 'mapsize' (string) do you want a 'small', 'normal' or 'big' map Daniel@0: % Any explicit settings of munits or msize override this. Daniel@0: % 'topol' (struct) topology struct Daniel@0: % 'som_topol','sTopol' = 'topol' Daniel@0: % 'lattice' (string) map lattice, 'hexa' or 'rect' Daniel@0: % 'shape' (string) map shape, 'sheet', 'cyl' or 'toroid' Daniel@0: % 'neigh' (string) neighborhood function, 'gaussian', 'cutgauss', Daniel@0: % 'ep' or 'bubble' Daniel@0: % Daniel@0: % For more help, try 'type som_supervised', or check out online documentation. Daniel@0: % See also SOM_MAKE, SOM_AUTOLABEL. Daniel@0: Daniel@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: % Daniel@0: % som_supervised Daniel@0: % Daniel@0: % PURPOSE Daniel@0: % Daniel@0: % Creates, initializes and trains a supervised SOM by taking the Daniel@0: % class-identity into account. Daniel@0: % Daniel@0: % SYNTAX Daniel@0: % Daniel@0: % sMap = som_supervised(sData); Daniel@0: % sMap = som_supervised(...,'argID',value,...) Daniel@0: % sMap = som_make(...,value,...); Daniel@0: % Daniel@0: % DESCRIPTION Daniel@0: % Daniel@0: % Creates, initializes and trains a supervised SOM. It constructs the Daniel@0: % training data by adding 1-of-N -coded matrix to the original data Daniel@0: % based on the class information in the .labels field. The dimension Daniel@0: % of vectors after the process is (the old dimension + number of Daniel@0: % different classes). In each vector, one of the new components has Daniel@0: % value '1' (this depends on the class of the vector), and others '0'. Daniel@0: % Calls SOM_MAKE to construct the map. Then the class of each map unit Daniel@0: % is determined by taking maximum over these added components, and a Daniel@0: % label is give accordingly. Finally, the extra components (the Daniel@0: % 1-of-N -coded ones) are removed. Daniel@0: % Daniel@0: % REFERENCES Daniel@0: % Daniel@0: % Kohonen, T., "Self-Organizing Map", 2nd ed., Springer-Verlag, Daniel@0: % Berlin, 1995, pp. 160-161. Daniel@0: % Kohonen, T., Mäkivasara, K., Saramäki, T., "Phonetic Maps - Daniel@0: % Insightful Representation of Phonological Features For Daniel@0: % Speech Recognition", In proceedings of International Daniel@0: % Conference on Pattern Recognition (ICPR), Montreal, Canada, Daniel@0: % 1984, pp. 182-185. Daniel@0: % Daniel@0: % REQUIRED INPUT ARGUMENTS Daniel@0: % Daniel@0: % sData The data to use in the training. Daniel@0: % (struct) A data struct. '.comp_names' as well as '.name' Daniel@0: % is copied to the map. The class information is Daniel@0: % taken from the first column of '.labels' field. Daniel@0: % Daniel@0: % OPTIONAL INPUT ARGUMENTS Daniel@0: % Daniel@0: % argID (string) Argument identifier string (see below). Daniel@0: % value (varies) Value for the argument (see below). Daniel@0: % Daniel@0: % The optional arguments can be given as 'argID',value -pairs. If an Daniel@0: % argument is given value multiple times, the last one is used. Daniel@0: % Here are the argument IDs and corresponding values: Daniel@0: % 'munits' (scalar) the preferred number of map units - this may Daniel@0: % change a bit, depending on the properties of the data Daniel@0: % 'msize' (vector) map grid size Daniel@0: % 'mask' (vector) BMU search mask, size dim x 1 Daniel@0: % 'name' (string) map name Daniel@0: % 'comp_names' (string array / cellstr) component names, size dim x 1 Daniel@0: % 'tracking' (scalar) how much to report, default = 1. This parameter Daniel@0: % is also passed to the training functions. Daniel@0: % The following values are unambiguous and can therefore Daniel@0: % be given without the preceeding argument ID: Daniel@0: % 'algorithm' (string) training algorithm: 'seq' or 'batch' (default) Daniel@0: % 'mapsize' (string) do you want a 'small', 'normal' or 'big' map Daniel@0: % Any explicit settings of munits or msize (or topol) Daniel@0: % override this. Daniel@0: % 'topol' (struct) topology struct Daniel@0: % 'som_topol','sTopol' = 'topol' Daniel@0: % 'lattice' (string) map lattice, 'hexa' or 'rect' Daniel@0: % 'shape' (string) map shape, 'sheet', 'cyl' or 'toroid' Daniel@0: % 'neigh' (string) neighborhood function, 'gaussian', 'cutgauss', Daniel@0: % 'ep' or 'bubble' Daniel@0: % Daniel@0: % OUTPUT ARGUMENTS Daniel@0: % Daniel@0: % sMap (struct) SOM -map struct Daniel@0: % Daniel@0: % EXAMPLES Daniel@0: % Daniel@0: % To simply train a map with default parameters: Daniel@0: % Daniel@0: % sMap = som_supervised(sData); Daniel@0: % Daniel@0: % With the optional arguments, the initialization and training can be Daniel@0: % influenced. To change map size, use 'msize', 'munits' or 'mapsize' Daniel@0: % arguments: Daniel@0: % Daniel@0: % sMap = som_supervised(D,'mapsize','big'); or Daniel@0: % sMap = som_supervised(D,'big'); Daniel@0: % sMap = som_supervised(D,'munits', 100); Daniel@0: % sMap = som_supervised(D,'msize', [20 10]); Daniel@0: % Daniel@0: % Argument 'algorithm' can be used to switch between 'seq' and 'batch' Daniel@0: % algorithms. 'batch' is the default, so to use 'seq' algorithm: Daniel@0: % Daniel@0: % sMap = som_supervised(D,'algorithm','seq'); or Daniel@0: % sMap = som_supervised(D,'seq'); Daniel@0: % Daniel@0: % The 'tracking' argument can be used to control the amout of reporting Daniel@0: % during training. The argument is used in this function, and it is Daniel@0: % passed to the training functions. To make the function work silently Daniel@0: % set it to 0. Daniel@0: % Daniel@0: % sMap = som_supervised(D,'tracking',0); Daniel@0: % Daniel@0: % SEE ALSO Daniel@0: % Daniel@0: % som_make Create, initialize and train Self-Organizing map. Daniel@0: % som_autolabel Label SOM/data set based on another SOM/data set. Daniel@0: Daniel@0: % Contributed to SOM Toolbox vs2, Feb 2nd, 2000 by Juha Parhankangas Daniel@0: % Copyright (c) by Juha Parhankangas Daniel@0: % http://www.cis.hut.fi/projects/somtoolbox/ Daniel@0: Daniel@0: % Juha Parhankangas 050100 Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: D0 = sData.data; Daniel@0: [c,n,classlabels] = class2num(sData.labels(:,1)); Daniel@0: Daniel@0: %%%%%%%% Checking arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: if ~isstruct(sData) Daniel@0: error('Argument ''sData'' must be a ''som_data'' -struct.'); Daniel@0: else Daniel@0: data_name = sData.name; Daniel@0: comp_names = sData.comp_names; Daniel@0: comp_norm = sData.comp_norm; Daniel@0: end Daniel@0: Daniel@0: [dlen,dim] = size(sData.data); Daniel@0: Daniel@0: % defaults Daniel@0: Daniel@0: mapsize = ''; Daniel@0: sM = som_map_struct(dim+n); Daniel@0: sTopol = sM.topol; Daniel@0: munits = prod(sTopol.msize); % should be zero Daniel@0: mask = sM.mask; Daniel@0: name = sM.name; Daniel@0: neigh = sM.neigh; Daniel@0: tracking = 1; Daniel@0: algorithm = 'batch'; Daniel@0: Daniel@0: %%%% changes to defaults (checking varargin) %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: i=1; Daniel@0: while i <= length(varargin) Daniel@0: argok = 1; Daniel@0: if ischar(varargin{i}) Daniel@0: switch varargin{i}, Daniel@0: % argument IDs Daniel@0: case 'mask', Daniel@0: i=i+1; Daniel@0: mask = varargin{i}; Daniel@0: case 'munits', Daniel@0: i=i+1; Daniel@0: munits = varargin{i}; Daniel@0: case 'msize', Daniel@0: i=i+1; Daniel@0: sTopol.msize = varargin{i}; Daniel@0: munits = prod(sTopol.msize); Daniel@0: case 'mapsize', Daniel@0: i=i+1; Daniel@0: mapsize = varargin{i}; Daniel@0: case 'name', Daniel@0: i=i+1; Daniel@0: name = varargin{i}; Daniel@0: case 'comp_names', Daniel@0: i=i+1; Daniel@0: comp_names = varargin{i}; Daniel@0: case 'lattice', Daniel@0: i=i+1; Daniel@0: sTopol.lattice = varargin{i}; Daniel@0: case 'shape', Daniel@0: i=i+1; Daniel@0: sTopol.shape = varargin{i}; Daniel@0: case {'topol','som_topol','sTopol'}, Daniel@0: i=i+1; Daniel@0: sTopol = varargin{i}; Daniel@0: munits = prod(sTopol.msize); Daniel@0: case 'neigh', Daniel@0: i=i+1; Daniel@0: neigh = varargin{i}; Daniel@0: case 'tracking', Daniel@0: i=i+1; Daniel@0: tracking = varargin{i}; Daniel@0: case 'algorithm', Daniel@0: i=i+1; Daniel@0: algorithm = varargin{i}; Daniel@0: % unambiguous values Daniel@0: case {'hexa','rect'}, Daniel@0: sTopol.lattice = varargin{i}; Daniel@0: case {'sheet','cyl','toroid'}, Daniel@0: sTopol.shape = varargin{i}; Daniel@0: case {'gaussian','cutgauss','ep','bubble'}, Daniel@0: neigh = varargin{i}; Daniel@0: case {'seq','batch'}, Daniel@0: algorithm = varargin{i}; Daniel@0: case {'small','normal','big'}, Daniel@0: mapsize = varargin{i}; Daniel@0: otherwise argok=0; Daniel@0: end Daniel@0: elseif isstruct(varargin{i}) & isfield(varargin{i},'type'), Daniel@0: switch varargin{i}(1).type, Daniel@0: case 'som_topol', Daniel@0: sTopol = varargin{i}; Daniel@0: otherwise argok=0; Daniel@0: end Daniel@0: else Daniel@0: argok = 0; Daniel@0: end Daniel@0: if ~argok, Daniel@0: disp(['(som_supervised) Ignoring invalid argument #' num2str(i+1)]); Daniel@0: end Daniel@0: i = i+1; Daniel@0: end Daniel@0: Daniel@0: %%%%%%%% Action %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: Daniel@0: Daniel@0: % constructing the training data by adding 1-of-N -coded matrix to the Daniel@0: % original data. Daniel@0: Daniel@0: [dlen,dim] = size(D0); Daniel@0: Daniel@0: Dc = zeros(dlen,n); Daniel@0: Daniel@0: for i=1:dlen Daniel@0: if c(i) Daniel@0: Dc(i,c(i)) = 1; Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: D = [D0, Dc]; Daniel@0: Daniel@0: % initialization and training Daniel@0: Daniel@0: sD = som_data_struct(D,... Daniel@0: 'name',data_name); Daniel@0: Daniel@0: sM = som_make(sD,... Daniel@0: 'mask',mask,... Daniel@0: 'munits',munits,... Daniel@0: 'name',data_name,... Daniel@0: 'tracking',tracking,... Daniel@0: 'algorithm',algorithm,... Daniel@0: 'mapsize',mapsize,... Daniel@0: 'topol',sTopol,... Daniel@0: 'neigh',neigh); Daniel@0: Daniel@0: % add labels Daniel@0: Daniel@0: for i=1:prod(sM.topol.msize), Daniel@0: [dummy,class] = max(sM.codebook(i,dim+[1:n])); Daniel@0: sM.labels{i} = classlabels{class}; Daniel@0: end Daniel@0: Daniel@0: %sD.labels = sData.labels; Daniel@0: %sM = som_autolabel(sM,sD,'vote'); Daniel@0: Daniel@0: % remove extra components and modify map -struct Daniel@0: Daniel@0: sM.codebook = sM.codebook(:,1:dim); Daniel@0: sM.mask = sM.mask(1:dim); Daniel@0: sM.comp_names = sData.comp_names; Daniel@0: sM.comp_norm = sData.comp_norm; Daniel@0: Daniel@0: % remove extras from sM.trainhist Daniel@0: Daniel@0: for i=1:length(sM.trainhist) Daniel@0: if sM.trainhist(i).mask Daniel@0: sM.trainhist(i).mask = sM.trainhist(i).mask(1:dim); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: function [numbers, n, names] = class2num(class) Daniel@0: Daniel@0: names = {}; Daniel@0: numbers = zeros(length(class),1); Daniel@0: Daniel@0: for i=1:length(class) Daniel@0: if ~isempty(class{i}) & ~any(strcmp(class{i},names)) Daniel@0: names=cat(1,names,class(i)); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: n=length(names); Daniel@0: Daniel@0: tmp_numbers = (1:n)'; Daniel@0: Daniel@0: for i=1:length(class) Daniel@0: if ~isempty(class{i}) Daniel@0: numbers(i,1) = find(strcmp(class{i},names)); Daniel@0: end Daniel@0: end