-
Notifications
You must be signed in to change notification settings - Fork 3
/
Featurevector.m
105 lines (104 loc) · 4.41 KB
/
Featurevector.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
classdef Featurevector < matlab.mixin.CustomDisplay
% Featurevector A vector of features represented numerically, extracted from
% a signal segment.
properties(SetAccess=private)
Vector % Struct mapping a feature (e.g. "Mean") to a numerical value (e.g. -0.0222)
end
methods
function self = Featurevector(featureStruct)
self.Vector = featureStruct;
end
function fs = features(self)
% List of features
fs = fieldnames([self.Vector]);
end
function count = dimension(self)
% The number of features
count = numel(self.features);
end
function featurevectors = select(self,varargin)
% Reduce the dimension, selecting only the most relevant features
filteredfields = varargin;
if length(filteredfields) == 0
filteredfields = fieldnames(self.Vector);
end
vectors = [self.Vector]';
for f = setdiff(fieldnames([self.Vector]),filteredfields)
vectors = rmfield(vectors,f);
end
featurevectors = arrayfun(@(v){Featurevector(v)},vectors);
featurevectors = [featurevectors{:}]';
end
function featurevectors = extend(self,field,values)
featurevectors = self;
for i = 1:size(self,1)
featurevectors(i).Vector.(field) = values(i);
end
end
function components = pca(self, numberofcomponents)
m = self.matrix();
normalized = (m-repmat(min(m),size(m,1),1))./repmat(max(m)-min(m),size(m,1),1);
[coeff score latent] = princomp(normalized);
components = num2cell(score(:,1:numberofcomponents),2);
if numberofcomponents == 2
components = arrayfun(@(v){Featurevector(struct('PC1',v{1}(1),'PC2',v{1}(2)))},components);
elseif numberofcomponents == 3
components = arrayfun(@(v){Featurevector(struct('PC1',v{1}(1),'PC2',v{1}(2),'PC3',v{1}(3)))},components);
end
components = [components{:}]';
end
function matrix = matrix(self)
% The set of features in the form of a NxM matrix, where N is the number of vectors and M
% is the number of features
matrix = cell2mat(struct2cell([self.Vector]')');
end
function featurevectors = kmeans(self,k)
m = self.matrix();
[idx,C] = kmeans(m,k,'Distance','cityblock','Replicates',5);
featurevectors = self.extend('Cluster',idx);
end
function newfeaturevectors = change(self,replacement)
% Replaces this feature vector with new feature vectors specified by the argument
newfeaturevectors = self;
vectortemplate = struct();
for i = 1:size(replacement,2)
featurename = ['F',num2str(i)];
vectortemplate.(featurename) = 0;
end
featurenames = fieldnames(vectortemplate);
if isnumeric(replacement) && size(replacement,1) == numel(self)
for i = 1:numel(self)
newvector = vectortemplate;
for j = 1:size(replacement,2)
newvector.(featurenames{j}) = replacement(i,j);
end
newfeaturevectors(i).Vector = newvector;
end
else
error('Unexpected input.')
end
end
end
methods(Access=protected)
function displayScalarObject(self)
% Cosmetic
className = matlab.mixin.CustomDisplay.getClassNameForHeader(self);
scalarHeader = [className,' with properties:'];
header = sprintf('%s\n',scalarHeader);
disp(header)
propgroup = getPropertyGroups(self);
matlab.mixin.CustomDisplay.displayPropertyGroups(self,propgroup);
end
function pg = getPropertyGroups(self)
% Cosmetic
if ~isscalar(self)
pg = getPropertyGroups@matlab.mixin.CustomDisplay(self);
else
pg(1) = matlab.mixin.util.PropertyGroup(self.Vector,'Vector');
end
% TODO Array of vectors of the same type should have format:
% 1x2 Featurevector array with properties:
% Vector(Mean,Variance,Skewness)
end
end
end