0001 function T = slnlda(X, nums, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 if nargin < 2
0070 raise_lackinput('slfld', 2);
0071 end
0072
0073
0074
0075 if ~isempty(X)
0076 if ndims(X) ~= 2
0077 error('sltoolbox:invaliddims', ...
0078 'The sample matrix X should be a 2D matrix');
0079 end
0080 [d, n] = size(X);
0081
0082 k = length(nums);
0083 if ~isequal(size(nums), [1, k]);
0084 error('sltoolbox:invaliddims', ...
0085 'The nums vector should be a row vector');
0086 end
0087 if sum(nums) ~= n
0088 error('sltoolbox:sizmismatch', ...
0089 'The total number in nums is not consistent with that in X');
0090 end
0091 end
0092
0093
0094
0095 opts.prepca = false;
0096 opts.pdimset = {};
0097 opts.dimset = {};
0098 opts.Sb = {'Sb'};
0099 opts.Sw = {'Sw'};
0100 opts.weights = [];
0101 opts = slparseprops(opts, varargin{:});
0102
0103 has_Sb = ~isempty(opts.Sb) && isnumeric(opts.Sb);
0104 has_Sw = ~isempty(opts.Sw) && isnumeric(opts.Sw);
0105 if has_Sb && has_Sw
0106 use_samples = false;
0107 d = size(opts.Sw, 1);
0108
0109 if ~isequal(size(opts.Sb), [d, d]) || ~isequal(size(opts.Sw), [d, d])
0110 error('sltoolbox:sizmismatch', ...
0111 'Size consistency in Sb and Sw');
0112 end
0113
0114 else
0115 if isempty(X)
0116 error('sltoolbox:invalidargs', ...
0117 'The samples cannot be empty when Sb or Sw is not pre-computed');
0118 end
0119 use_samples = true;
0120 if (has_Sb && ~isequal(size(opts.Sb), [d, d])) || (has_Sw && ~isequal(size(opts.Sw), [d, d]))
0121 error('sltoolbox:sizmismatch', ...
0122 'Size consistency in Sb and Sw');
0123 end
0124
0125 end
0126 w = opts.weights;
0127
0128
0129
0130
0131
0132 pca_computed = false;
0133 if use_samples && opts.prepca
0134 SPCA = slpca(X, 'weights', w);
0135 X = SPCA.P' * sladdvec(X, -SPCA.vmean, 1);
0136 pca_computed = true;
0137 end
0138
0139
0140
0141 if has_Sw
0142 PN = slnullspace({'cov', opts.Sw}, opts.pdimset{:});
0143 elseif ~isempty(opts.Sw) && ~isequal(opts.Sw, {'Sw'})
0144 Sw = slscatter(X, opts.Sw{:}, 'sweights', w, 'nums', nums);
0145 PN = slnullspace({'cov', Sw}, opts.pdimset{:});
0146 clear Sw;
0147 else
0148 PN = slnullspace(make_weighted_withinclass_diffvecs(X, w, nums), ...
0149 opts.pdimset{:});
0150 end
0151
0152 if pca_computed
0153 T1 = SPCA.P * PN;
0154 clear SPCA PN;
0155 else
0156 T1 = PN;
0157 clear PN;
0158 end
0159
0160
0161
0162
0163 if has_Sb
0164 WSb = T1' * opts.Sb * T1;
0165 else
0166 X = T1' * X;
0167 WSb = slscatter(X, opts.Sb{:}, 'sweights', w, 'nums', nums);
0168 end
0169 [evs, T2] = slsymeig(WSb);
0170 rk2 = sldim_by_eigval(evs, opts.dimset{:});
0171 T2 = T2(:, 1:rk2);
0172
0173
0174
0175 T = T1 * T2;
0176
0177
0178
0179 function Y = make_weighted_withinclass_diffvecs(X, w, nums)
0180
0181 mvs = slmeans(X, w, nums);
0182 Y = X;
0183 [sp, ep] = slnums2bounds(nums);
0184 k = length(nums);
0185 for i = 1 : k
0186 Y(:, sp(i):ep(i)) = sladdvec(X(:, sp(i):ep(i)), -mvs(:,i), 1);
0187 end
0188
0189 if ~isempty(w)
0190 Y = slmulvec(Y, sqrt(max(w, 0)), 2);
0191 end
0192