1 %> @brief Least-squares classifier
7 %> =1. Whether or not to use priors. If set, will calculate the prior
class-conditional probabilities based on the amount of
8 %> training data
for each class.
10 %> Whether to weight the observations (
for unbalanced classes)
12 %> []. Number of features. If specified, will find a threshold to trim the coefficients
14 % nregions_select = [];
17 properties(SetAccess=
protected)
18 %>
"Intercepts" (account
for features whose mean is not zero
20 %>
"Loadings matrix" [nf]x[nc]
22 %> Recording of each stage of the feature reduction
30 o.classtitle = 'Least-Squares';
35 % %> If title is not empty, will not mess with description too much
36 % function s = get_description(o)
37 % if ~isempty(o.title)
38 % s = get_description@
clssr(o);
40 % s = [get_description@
clssr(o), ' type = ', o.type];
47 % %> Thresholds L_ to have maximum nf non-zero coefficients
48 % function [L_, threshs] = nfthreshold(L_, maxnf)
49 % [ro, co] = size(L_);
52 % %> nf maximum is less restrictive than number of existing features
53 % threshs = zeros(1, co);
66 % me = round(mean([ma, mi]));
68 % num = numel(find(y_ <= thresh));
71 % elseif num < ro-maxnf
82 % L_(y_ <= thresh, i) = 0;
83 % threshs(i) = thresh;
87 %> Returns weights that are inversely propoertional to the number of observations in each class
89 %> Weights are
scaled so that sum(w_c*N_c) = N,
91 %> where w_c is the weight for class c, N_c is the number of observations in class c, and N is the total number of observations.
92 function w = get_weights(data)
93 ww = arrayfun(@(i) (sqrt(sum(data.classes == i))), 0:data.nc-1);
94 % ww = arrayfun(@(i) (sum(data.classes == i)), 0:data.nc-1);
95 w = (1./ww)*(data.no/sum(ww));
99 methods(Access=protected)
101 function o = do_train(o, data)
102 o.classlabels = data.classlabels;
106 X = [ones(data.no, 1), data.X];
109 w = data.get_weights(1); % Calculates weights
for the classes
112 X(data.classes == i-1, :) = X(data.classes == i-1, :)*w(i);
118 L0 = (X
'*X)\(X'*Y); % Least-squares formula
121 % Separates the intercept and loadings;
this is
for interpretability, wouldn
't be needed otherwise
123 o.intercepts = L0(1, :);
125 if ~isempty(o.nf_select) && o.nf_select > 0
126 [o.L, o.thresholds] = o.nfthreshold(o.L, o.nf_select);
130 o.time_train = toc(t);
138 pars.x_range = [1, 6];
139 pars.y_range = [3, 8];
140 % % % function o = do_train(o, data)
141 % % % o.classlabels = data.classlabels;
145 % % % X = [ones(data.no, 1), data.X];
147 % % % if o.flag_weighted
148 % % % w = data.get_weights(1); % Calculates weighblock_mold.block_mold.ts for the classes
150 % % % for i = 1:data.nc
151 % % % X(data.classes == i-1, :) pars.x_range = [1, 6];
152 pars.y_range = [3, 8];= X(data.clasblock_mold.ses == i-1, :)*w(i);
156 % % % Y = classes2boolean(data.classes);
158 % % % L0 = (X'*X)\(X
'*Y); % Least-squares formula
161 % % % % Separates the intercept and loadings; this is for interpretability, wouldn't be needed otherwise
162 % % % o.L = L0(2:end, :);
163 % % % o.intercepts = L0(1, :);
165 % % %
if ~isempty(o.nf_select) && o.nf_select > 0
166 % % % [o.L, o.thresholds] = o.nfthreshold(o.L, o.nf_select);
168 % % % o.v = o.L > 0; % This is 2-
class but just for a while...
173 % % % X = [ones(data.no, 1), data.X(:, o.v(:, 1))];
175 % % %
if o.flag_weighted
176 % % % w = data.get_weights(1); % Calculates weights
for the classes
178 % % %
for i = 1:data.nc
179 % % % X(data.classes == i-1, :) = X(data.classes == i-1, :)*w(i);
185 % % % L0 = (X
'*X)\(X'*Y); % Least-squares formula
188 % % % % Separates the intercept and loadings;
this is
for interpretability, wouldn
't be needed otherwise
189 % % % o.L = L0(2:end, :);
190 % % % o.intercepts = L0(1, :);
207 % % % o.time_train = toc(t);
213 function o = do_train(o, data)
214 o.classlabels = data.classlabels;
218 X0 = [ones(data.no, 1), data.X];
220 w = o.get_weights(data); % Calculates weights for the classes
222 % w = w*data.nc*100; %/min(w);
226 X0(data.classes == i-1, :) = X0(data.classes == i-1, :)*w(i);
230 Y = classes2boolean(data.classes);
233 flag_reduce = ~isempty(o.nf_select);
237 L0 = (X0'*X0)\(X0
'*Y); % Least-squares formula
241 % nc = iif(data.nc == 2, 1, data.nc);
244 L0 = zeros(data.nf+1, data.nc);
248 vin = 1:data.nf; % Features selected
250 Sc = zeros(data.nf-o.nf_select, data.nf);
254 for i = data.nf:-1:o.nf_select
255 X = X0(:, [1, vin+1]);
262 L1 = (X'*X)\(X
'*Yc); % Least-squares formula
263 % fprintf('%d features took %.5f seconds\n
', size(X, 2), toc(tt));
267 fprintf('%d fea, toc toc %.6f\n
', i, tt);
268 o.time_train = o.time_train+tt;
271 temp = zeros(1, data.nf);
272 temp(vin) = abs(L1(2:end));
273 Sc(i-o.nf_select+1, :) = temp;
280 [va, in] = min(abs(L1(2:end, 1)));
285 L0([1, vin+1], ic) = L1;
288 fprintf('---Time train was %.6f seconds\n
', o.time_train());
292 o.intercepts = L0(1, :);
299 %> With bits from MATLAB classify()
300 function est = do_use(o, data)
302 est.classlabels = o.classlabels;
303 est = est.copy_from_data(data);
307 X = data.X(:, o.v); % Temporary
310 X = [ones(data.no, 1), X];
311 posteriors = X*[o.intercepts; o.L];
312 posteriors = normalize_rows(posteriors);
320 function est = do_use(o, data)
322 est.classlabels = o.classlabels;
323 est = est.copy_from_data(data);
327 X = [ones(data.no, 1), data.X];
328 posteriors = X*[o.intercepts; o.L];
329 % posteriors = normalize_rows(posteriors);
330 % posteriors = irsoftmax(posteriors);
331 % posteriors = exp(exp(exp(exp(posteriors))));
332 posteriors = normalize_rows(exp(posteriors).^2);
333 % posteriors = normalize_rows(posteriors);
334 % posteriors = round(posteriors);
337 % est.X = round(est.X);
function classes2boolean(in classes, in no_different)
Least-squares classifier.