0001 function S = slpca(X, 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 if ndims(X) ~= 2
0054 error('sltoolbox:invaliddims', 'X should be a 2D sample matrix');
0055 end
0056 [d, n] = size(X);
0057
0058
0059 opts.method = 'auto';
0060 opts.preserve = {'rank'};
0061 opts.weights = [];
0062 opts = slparseprops(opts, varargin{:});
0063
0064
0065
0066 switch opts.method
0067 case 'auto'
0068 fh_learnpca = @pca_auto;
0069 case 'std'
0070 fh_learnpca = @pca_std;
0071 case 'svd'
0072 fh_learnpca = @pca_svd;
0073 case 'trans'
0074 fh_learnpca = @pca_trans;
0075 otherwise
0076 error('sltoolbox:invalidarg', ...
0077 'Invalid PCA learning method %s', opts.method);
0078 end
0079
0080
0081 if ~isempty(opts.weights)
0082 if ~isequal(size(opts.weights), [1, n])
0083 error('sltoolbox:sizmismatch', ...
0084 'The sample weights should be a 1 x n row vector');
0085 end
0086 end
0087
0088
0089
0090
0091
0092 vmean = slmean(X, opts.weights);
0093 X = sladdvec(X, -vmean, 1);
0094
0095
0096
0097 if isempty(opts.weights)
0098 X = sqrt(1 / n) * X;
0099 else
0100 w = max(opts.weights, 0);
0101 tw = sum(w);
0102 sf = sqrt(w / tw);
0103 X = slmulvec(X, sf, 2);
0104 clear sf;
0105 end
0106
0107
0108
0109 [P, evals] = fh_learnpca(X);
0110
0111
0112
0113
0114 evals = max(evals, 0);
0115 kmax = min([size(P, 2), d, n-1]);
0116 if kmax < size(P, 2)
0117 P = P(:, 1:kmax);
0118 evals = evals(1:kmax);
0119 end
0120 k = sldim_by_eigval(evals, opts.preserve{:});
0121
0122
0123
0124
0125 S.sampledim = d;
0126 S.feadim = k;
0127
0128 if isempty(opts.weights)
0129 S.support = n;
0130 else
0131 S.support = tw;
0132 end
0133
0134 S.vmean = vmean;
0135 if k < kmax
0136 S.P = P(:, 1:k);
0137 S.eigvals = evals(1:k);
0138 S.residue = sum(evals(k+1:kmax));
0139 else
0140 S.P = P;
0141 S.eigvals = evals;
0142 S.residue = 0;
0143 end
0144
0145 prinenergy = sum(S.eigvals);
0146 S.energyratio = prinenergy / (prinenergy + S.residue);
0147
0148
0149
0150
0151 function [P, evals] = pca_auto(X)
0152
0153 [d, n] = size(X);
0154 if d <= n
0155 [P, evals] = pca_std(X);
0156 else
0157 [P, evals] = pca_trans(X);
0158 end
0159
0160
0161 function [P, evals] = pca_std(X)
0162
0163 C = X * X';
0164 [evals, P] = slsymeig(C);
0165
0166
0167 function [P, evals] = pca_svd(X)
0168
0169 [P, D, V] = svd(X, 0);
0170 clear V;
0171 evals = diag(D) .^ 2;
0172
0173 slignorevars(V);
0174
0175 function [P, evals] = pca_trans(X)
0176
0177 Ct = X' * X;
0178 [evals, P] = slsymeig(Ct);
0179 P = slnormalize(X * P);
0180
0181
0182
0183