wolffd@0
|
1 % --
|
wolffd@0
|
2 % This class loads and hanles the aufdio features included with the MTT
|
wolffd@0
|
3 % Library
|
wolffd@0
|
4 % ---
|
wolffd@0
|
5 classdef MTTMixedFeatureGenreBasicSmPCA < MTTAudioFeature & handle
|
wolffd@0
|
6
|
wolffd@0
|
7 properties(Constant = true)
|
wolffd@0
|
8
|
wolffd@0
|
9 my_revision = str2double(substr('$Rev$', 5, -1));
|
wolffd@0
|
10 end
|
wolffd@0
|
11
|
wolffd@0
|
12 properties
|
wolffd@0
|
13
|
wolffd@0
|
14 % ---
|
wolffd@0
|
15 % Set default parameters
|
wolffd@0
|
16 % ---
|
wolffd@0
|
17 my_basetype = 'MTTMixedFeatureGenreBasicSm';
|
wolffd@0
|
18
|
wolffd@0
|
19 my_params = MTTAudioFeature.inherited_params(...
|
wolffd@0
|
20 'MTTMixedFeatureGenreBasicSm', ...
|
wolffd@0
|
21 'min_pca_var', 0, ... % % fraction of variance to keep
|
wolffd@0
|
22 'max_pca_coeffs', 0, ...% max. number of final coefficients
|
wolffd@0
|
23 'norm_pre_pca', 1, ...% normalise pca coefficients after transformation
|
wolffd@0
|
24 'norm_post_pca', 1 ...
|
wolffd@0
|
25 );
|
wolffd@0
|
26 end
|
wolffd@0
|
27 % ---
|
wolffd@0
|
28 % member functions
|
wolffd@0
|
29 % ---
|
wolffd@0
|
30 methods
|
wolffd@0
|
31
|
wolffd@0
|
32 % ---
|
wolffd@0
|
33 % constructor: pointer to feature in database
|
wolffd@0
|
34 % ---
|
wolffd@0
|
35 function feature = MTTMixedFeatureGenreBasicSmPCA(varargin)
|
wolffd@0
|
36
|
wolffd@0
|
37 feature = feature@MTTAudioFeature(varargin{:});
|
wolffd@0
|
38 end
|
wolffd@0
|
39
|
wolffd@0
|
40 % ---
|
wolffd@0
|
41 % load feature data from xml file
|
wolffd@0
|
42 % ---
|
wolffd@0
|
43 function data = extract(feature, clip)
|
wolffd@0
|
44 % load feature data by parsing xml
|
wolffd@0
|
45
|
wolffd@0
|
46 global globalvars;
|
wolffd@0
|
47
|
wolffd@0
|
48 % ---
|
wolffd@0
|
49 % we extract the base features, and save
|
wolffd@0
|
50 % the pointers to these.
|
wolffd@0
|
51 % the main work is then done in the define_global_transf
|
wolffd@0
|
52 % and finalise functions.
|
wolffd@0
|
53 % ---
|
wolffd@0
|
54 data.basefeat = clip.features(feature.my_basetype,...
|
wolffd@0
|
55 feature.my_params);
|
wolffd@0
|
56
|
wolffd@0
|
57 % save info data
|
wolffd@0
|
58 data.info.type = 'MTTMixedFeatureGenreBasicSmPCA';
|
wolffd@0
|
59 data.info.owner_id = clip.id;
|
wolffd@0
|
60 data.info.creatorrev = feature.my_revision;
|
wolffd@0
|
61
|
wolffd@0
|
62 % save param data
|
wolffd@0
|
63 data.info.params = feature.my_params;
|
wolffd@0
|
64
|
wolffd@0
|
65 % prepare field for final features
|
wolffd@0
|
66 data.final.vector = [];
|
wolffd@0
|
67 data.final.dim = 0;
|
wolffd@0
|
68 data.final.vector_info.labels = {};
|
wolffd@0
|
69 end
|
wolffd@0
|
70
|
wolffd@0
|
71 function define_global_transform(features)
|
wolffd@0
|
72
|
wolffd@0
|
73 if numel(features) == 1
|
wolffd@0
|
74 error ('Insert feature array for this method');
|
wolffd@0
|
75 end
|
wolffd@0
|
76
|
wolffd@0
|
77 % ---
|
wolffd@0
|
78 % We collect all the relevant genretag
|
wolffd@0
|
79 % features and get the transform on this basis.
|
wolffd@0
|
80 % ---
|
wolffd@0
|
81 for i = 1:numel(features)
|
wolffd@0
|
82 basef(i) = features(i).data.basefeat;
|
wolffd@0
|
83 end
|
wolffd@0
|
84
|
wolffd@0
|
85 % call the features own transsform function
|
wolffd@0
|
86 basef.define_global_transform();
|
wolffd@0
|
87
|
wolffd@0
|
88 % ---
|
wolffd@0
|
89 % finalise the basic features, and
|
wolffd@0
|
90 % get the feature vectors;
|
wolffd@0
|
91 % ---
|
wolffd@0
|
92 basef.finalise();
|
wolffd@0
|
93 X = basef.vector();
|
wolffd@0
|
94
|
wolffd@0
|
95 % check dataset dimension
|
wolffd@0
|
96 if numel(features) < basef.dim;
|
wolffd@0
|
97
|
wolffd@0
|
98 error ('Not enough feature vectors for PCA calculation. need %d samples', ...
|
wolffd@0
|
99 basef.dim);
|
wolffd@0
|
100 end
|
wolffd@0
|
101
|
wolffd@0
|
102 % ---
|
wolffd@0
|
103 % NOTE: should the data be normalised and scaled to -1:1
|
wolffd@0
|
104 % instead of being in a range of 0-1 AND max-min = 1
|
wolffd@0
|
105 % ---
|
wolffd@0
|
106 if features(1).my_params.norm_pre_pca == 1
|
wolffd@0
|
107
|
wolffd@0
|
108 [X, pstd] = mapminmax(X,-1,1);
|
wolffd@0
|
109 common.pca.pre_norm = pstd;
|
wolffd@0
|
110 elseif features(1).my_params.norm_pre_pca == 2
|
wolffd@0
|
111
|
wolffd@0
|
112 [X, pstd] = mapstd(X,0,1);
|
wolffd@0
|
113 common.pca.pre_norm = pstd;
|
wolffd@0
|
114 end
|
wolffd@0
|
115
|
wolffd@0
|
116
|
wolffd@0
|
117 % ---
|
wolffd@0
|
118 % get and apply the principal component analysis
|
wolffd@0
|
119 % NOTE: the variance percentile is applied here, too.
|
wolffd@0
|
120 % ---
|
wolffd@0
|
121
|
wolffd@0
|
122 [Y, ps] = processpca(X, 0);
|
wolffd@0
|
123 common.pca.transform = ps;
|
wolffd@0
|
124
|
wolffd@0
|
125 % ---
|
wolffd@0
|
126 % get cumulative sum of variance, and decide on cutoff
|
wolffd@0
|
127 % point
|
wolffd@0
|
128 % ---
|
wolffd@0
|
129 v = cumsum(var(Y'));
|
wolffd@0
|
130 v = v / max(v);
|
wolffd@0
|
131 common.pca.transform.varpart = v;
|
wolffd@0
|
132
|
wolffd@0
|
133 if features(1).my_params.min_pca_var > 0
|
wolffd@0
|
134
|
wolffd@0
|
135 min_pca_idx = find(v >= features(1).my_params.min_pca_var,1, 'first');
|
wolffd@0
|
136
|
wolffd@0
|
137 % save into pca structure
|
wolffd@0
|
138 common.pca.transform.yrows = min_pca_idx;
|
wolffd@0
|
139
|
wolffd@0
|
140 end
|
wolffd@0
|
141
|
wolffd@0
|
142 % normalise pca values after processing
|
wolffd@0
|
143 if features(1).my_params.norm_post_pca
|
wolffd@0
|
144
|
wolffd@0
|
145 [Y,pmm] = mapminmax(Y,0,1);
|
wolffd@0
|
146 common.pca.post_norm = pmm;
|
wolffd@0
|
147
|
wolffd@0
|
148 end
|
wolffd@0
|
149
|
wolffd@0
|
150 % ---
|
wolffd@0
|
151 % set common feature values for mixed features
|
wolffd@0
|
152 % ---
|
wolffd@0
|
153 features(1).my_db.set_common(common);
|
wolffd@0
|
154
|
wolffd@0
|
155 % save the transformed features straight away!
|
wolffd@0
|
156 features.finalise(Y);
|
wolffd@0
|
157 end
|
wolffd@0
|
158
|
wolffd@0
|
159 function finalise(feature, final)
|
wolffd@0
|
160 % applies a final transformation and
|
wolffd@0
|
161 % collects the information of this feature within a single vector
|
wolffd@0
|
162 % see info for types in specific dimensions
|
wolffd@0
|
163
|
wolffd@0
|
164 % determine size
|
wolffd@0
|
165 if feature(1).my_params.max_pca_coeffs > 0
|
wolffd@0
|
166
|
wolffd@0
|
167 max_size = min(feature(1).common.pca.transform.yrows, ...
|
wolffd@0
|
168 feature(1).my_params.max_pca_coeffs);
|
wolffd@0
|
169 else
|
wolffd@0
|
170
|
wolffd@0
|
171 max_size = feature(1).common.pca.transform.yrows;
|
wolffd@0
|
172 end
|
wolffd@0
|
173
|
wolffd@0
|
174
|
wolffd@0
|
175 % prepare information
|
wolffd@0
|
176 info = {'PCA'};
|
wolffd@0
|
177 if isfield(feature(1).common.pca.transform, 'varpart')
|
wolffd@0
|
178 info(2:max_size) = num2cell(feature(1).common.pca.transform.varpart(2:max_size));
|
wolffd@0
|
179 else
|
wolffd@0
|
180 info(2:max_size) = num2cell(2:max_size);
|
wolffd@0
|
181 end
|
wolffd@0
|
182
|
wolffd@0
|
183
|
wolffd@0
|
184 % check if features have been finalised already
|
wolffd@0
|
185 if nargin == 2 && isempty(final)
|
wolffd@0
|
186
|
wolffd@0
|
187 % the final vector etc already are set to zero;
|
wolffd@0
|
188 return;
|
wolffd@0
|
189
|
wolffd@0
|
190 elseif nargin == 2 && (numel(feature) == size(final, 2))
|
wolffd@0
|
191
|
wolffd@0
|
192 for i = 1:numel(feature)
|
wolffd@0
|
193
|
wolffd@0
|
194 % save final vector and description
|
wolffd@0
|
195 feature(i).data.final.vector = final(1:max_size,i);
|
wolffd@0
|
196 feature(i).data.final.dim = max_size;
|
wolffd@0
|
197 feature(i).data.final.vector_info.labels = info;
|
wolffd@0
|
198 end
|
wolffd@0
|
199
|
wolffd@0
|
200 else
|
wolffd@0
|
201 % features have to be transformed first
|
wolffd@0
|
202 % ---
|
wolffd@0
|
203 % TODO: this code remains untested
|
wolffd@0
|
204 % ---
|
wolffd@0
|
205
|
wolffd@0
|
206 % check for neccesary parameters
|
wolffd@0
|
207 if isempty(feature(1).my_db.commondb)
|
wolffd@0
|
208
|
wolffd@0
|
209 error('Define the global transformation first')
|
wolffd@0
|
210 return;
|
wolffd@0
|
211 end
|
wolffd@0
|
212
|
wolffd@0
|
213
|
wolffd@0
|
214 for i = 1:numel(feature)
|
wolffd@0
|
215
|
wolffd@0
|
216 % check for neccesary parameters
|
wolffd@0
|
217 if isempty(feature(i).my_db.commondb)
|
wolffd@0
|
218
|
wolffd@0
|
219 error('Define the global transformation first')
|
wolffd@0
|
220 end
|
wolffd@0
|
221
|
wolffd@0
|
222 % ---
|
wolffd@0
|
223 % get feature vector and apply transformation
|
wolffd@0
|
224 % ---
|
wolffd@0
|
225 X = feature(i).data.basefeat.vector();
|
wolffd@0
|
226
|
wolffd@0
|
227 % ---
|
wolffd@0
|
228 % apply normalisation used for removing mean
|
wolffd@0
|
229 % in training data
|
wolffd@0
|
230 % ---
|
wolffd@0
|
231 if feature(1).my_params.norm_pre_pca == 1
|
wolffd@0
|
232
|
wolffd@0
|
233 X = mapminmax('apply', X, feature(1).common.pca.pre_norm);
|
wolffd@0
|
234 elseif feature(1).my_params.norm_pre_pca == 2
|
wolffd@0
|
235
|
wolffd@0
|
236 X = mapstd('apply', X, feature(1).common.pca.pre_norm);
|
wolffd@0
|
237 end
|
wolffd@0
|
238
|
wolffd@0
|
239 % apply PCA transform
|
wolffd@0
|
240 vec = processpca('apply', X, feature(1).common.pca.transform);
|
wolffd@0
|
241
|
wolffd@0
|
242 % normalise pca values after transformation
|
wolffd@0
|
243 if feature(1).my_params.norm_post_pca
|
wolffd@0
|
244
|
wolffd@0
|
245 vec = mapminmax('apply', vec,...
|
wolffd@0
|
246 feature(1).common.pca.post_norm);
|
wolffd@0
|
247 end
|
wolffd@0
|
248
|
wolffd@0
|
249 % ---
|
wolffd@0
|
250 % cut vector to final size.
|
wolffd@0
|
251 % NOTE: this should be done before
|
wolffd@0
|
252 % transformation to reduce computation time
|
wolffd@0
|
253 % ---
|
wolffd@0
|
254 vec = vec(1:max_size);
|
wolffd@0
|
255
|
wolffd@0
|
256 % save final vector and description
|
wolffd@0
|
257 feature(i).data.final.vector = vec;
|
wolffd@0
|
258 feature(i).data.final.dim = numel(vec);
|
wolffd@0
|
259 feature(i).data.final.vector_info.labels = info;
|
wolffd@0
|
260 end
|
wolffd@0
|
261 end
|
wolffd@0
|
262 end
|
wolffd@0
|
263
|
wolffd@0
|
264 end
|
wolffd@0
|
265 end |