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 MTTMixedFeatureStober11GenrePCA < MTTAudioFeature & handle
|
wolffd@0
|
6
|
wolffd@0
|
7 properties(Constant = true)
|
wolffd@0
|
8
|
wolffd@0
|
9 my_revision = str2double(substr('$Rev: 457 $', 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 = 'MTTMixedFeatureStober11Genre';
|
wolffd@0
|
18
|
wolffd@0
|
19 my_params = MTTAudioFeature.inherited_params(...
|
wolffd@0
|
20 'MTTMixedFeatureStober11Genre', ...
|
wolffd@0
|
21 'min_pca_var', 0, ... % [0-1], def. 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, ...
|
wolffd@0
|
24 'norm_post_pca', 1 ...% normalise pca coefficients after transformation
|
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 = MTTMixedFeatureStober11GenrePCA(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 = class(feature);
|
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 X = basef.vector();
|
wolffd@0
|
93
|
wolffd@0
|
94 % check dataset dimension
|
wolffd@0
|
95 if numel(features) < basef.dim;
|
wolffd@0
|
96
|
wolffd@0
|
97 error ('Not enough feature vectors for PCA calculation. need %d samples', ...
|
wolffd@0
|
98 basef.dim);
|
wolffd@0
|
99 end
|
wolffd@0
|
100
|
wolffd@0
|
101 % ---
|
wolffd@0
|
102 % NOTE: should the data be normalised and scaled to -1:1
|
wolffd@0
|
103 % instead of being in a range of 0-1 AND max-min = 1
|
wolffd@0
|
104 % ---
|
wolffd@0
|
105 if features(1).my_params.norm_pre_pca == 1
|
wolffd@0
|
106
|
wolffd@0
|
107 [X, pstd] = mapminmax(X,-1,1);
|
wolffd@0
|
108 common.pca.pre_norm = pstd;
|
wolffd@0
|
109 elseif features(1).my_params.norm_pre_pca == 2
|
wolffd@0
|
110
|
wolffd@0
|
111 [X, pstd] = mapstd(X,0,1);
|
wolffd@0
|
112 common.pca.pre_norm = pstd;
|
wolffd@0
|
113 end
|
wolffd@0
|
114
|
wolffd@0
|
115
|
wolffd@0
|
116 % ---
|
wolffd@0
|
117 % get and apply the principal component analysis
|
wolffd@0
|
118 % NOTE: the variance percentile is applied here, too.
|
wolffd@0
|
119 % ---
|
wolffd@0
|
120
|
wolffd@0
|
121 [Y, ps] = processpca(X, 0);
|
wolffd@0
|
122 common.pca.transform = ps;
|
wolffd@0
|
123
|
wolffd@0
|
124 % ---
|
wolffd@0
|
125 % get cumulative sum of variance, and decide on cutoff
|
wolffd@0
|
126 % point
|
wolffd@0
|
127 % ---
|
wolffd@0
|
128 v = cumsum(var(Y'));
|
wolffd@0
|
129 v = v / max(v);
|
wolffd@0
|
130 common.pca.transform.varpart = v;
|
wolffd@0
|
131
|
wolffd@0
|
132 if features(1).my_params.min_pca_var > 0
|
wolffd@0
|
133
|
wolffd@0
|
134 min_pca_idx = find(v >= features(1).my_params.min_pca_var,1, 'first');
|
wolffd@0
|
135
|
wolffd@0
|
136 % save into pca structure
|
wolffd@0
|
137 common.pca.transform.yrows = min_pca_idx;
|
wolffd@0
|
138
|
wolffd@0
|
139 end
|
wolffd@0
|
140
|
wolffd@0
|
141 % normalise pca values after processing
|
wolffd@0
|
142 if features(1).my_params.norm_post_pca
|
wolffd@0
|
143
|
wolffd@0
|
144 [Y,pmm] = mapminmax(Y,0,1);
|
wolffd@0
|
145 common.pca.post_norm = pmm;
|
wolffd@0
|
146
|
wolffd@0
|
147 end
|
wolffd@0
|
148
|
wolffd@0
|
149 % ---
|
wolffd@0
|
150 % set common feature values for mixed features
|
wolffd@0
|
151 % ---
|
wolffd@0
|
152 features(1).my_db.set_common(common);
|
wolffd@0
|
153
|
wolffd@0
|
154 % save the transformed features straight away!
|
wolffd@0
|
155 features.finalise(Y);
|
wolffd@0
|
156 end
|
wolffd@0
|
157
|
wolffd@0
|
158 function finalise(feature, final)
|
wolffd@0
|
159 % applies a final transformation and
|
wolffd@0
|
160 % collects the information of this feature within a single vector
|
wolffd@0
|
161 % see info for types in specific dimensions
|
wolffd@0
|
162
|
wolffd@0
|
163 % determine size
|
wolffd@0
|
164 if feature(1).my_params.max_pca_coeffs > 0
|
wolffd@0
|
165
|
wolffd@0
|
166 max_size = min(feature(1).common.pca.transform.yrows, ...
|
wolffd@0
|
167 feature(1).my_params.max_pca_coeffs);
|
wolffd@0
|
168 else
|
wolffd@0
|
169
|
wolffd@0
|
170 max_size = feature(1).common.pca.transform.yrows;
|
wolffd@0
|
171 end
|
wolffd@0
|
172
|
wolffd@0
|
173
|
wolffd@0
|
174 % prepare information
|
wolffd@0
|
175 info = {'PCA'};
|
wolffd@0
|
176 if isfield(feature(1).common.pca.transform, 'varpart')
|
wolffd@0
|
177 info(2:max_size) = num2cell(feature(1).common.pca.transform.varpart(2:max_size));
|
wolffd@0
|
178 else
|
wolffd@0
|
179 info(2:max_size) = num2cell(2:max_size);
|
wolffd@0
|
180 end
|
wolffd@0
|
181
|
wolffd@0
|
182
|
wolffd@0
|
183 % check if features have been finalised already
|
wolffd@0
|
184 if nargin == 2 && isempty(final)
|
wolffd@0
|
185
|
wolffd@0
|
186 % the final vector etc already are set to zero;
|
wolffd@0
|
187 return;
|
wolffd@0
|
188
|
wolffd@0
|
189 elseif nargin == 2 && (numel(feature) == size(final, 2))
|
wolffd@0
|
190
|
wolffd@0
|
191 for i = 1:numel(feature)
|
wolffd@0
|
192
|
wolffd@0
|
193 % save final vector and description
|
wolffd@0
|
194 feature(i).data.final.vector = final(1:max_size,i);
|
wolffd@0
|
195 feature(i).data.final.dim = max_size;
|
wolffd@0
|
196 feature(i).data.final.vector_info.labels = info;
|
wolffd@0
|
197 end
|
wolffd@0
|
198
|
wolffd@0
|
199 else
|
wolffd@0
|
200 % features have to be transformed first
|
wolffd@0
|
201 % ---
|
wolffd@0
|
202 % TODO: this code remains untested
|
wolffd@0
|
203 % ---
|
wolffd@0
|
204
|
wolffd@0
|
205 % check for neccesary parameters
|
wolffd@0
|
206 if isempty(feature(1).my_db.commondb)
|
wolffd@0
|
207
|
wolffd@0
|
208 error('Define the global transformation first')
|
wolffd@0
|
209 return;
|
wolffd@0
|
210 end
|
wolffd@0
|
211
|
wolffd@0
|
212
|
wolffd@0
|
213 for i = 1:numel(feature)
|
wolffd@0
|
214
|
wolffd@0
|
215 % check for neccesary parameters
|
wolffd@0
|
216 if isempty(feature(i).my_db.commondb)
|
wolffd@0
|
217
|
wolffd@0
|
218 error('Define the global transformation first')
|
wolffd@0
|
219 end
|
wolffd@0
|
220
|
wolffd@0
|
221 % ---
|
wolffd@0
|
222 % get feature vector and apply transformation
|
wolffd@0
|
223 % ---
|
wolffd@0
|
224 X = feature(i).data.basefeat.vector();
|
wolffd@0
|
225
|
wolffd@0
|
226 % ---
|
wolffd@0
|
227 % apply normalisation used for removing mean
|
wolffd@0
|
228 % in training data
|
wolffd@0
|
229 % ---
|
wolffd@0
|
230 if feature(1).my_params.norm_pre_pca == 1
|
wolffd@0
|
231
|
wolffd@0
|
232 X = mapminmax('apply', X, feature(1).common.pca.pre_norm);
|
wolffd@0
|
233 elseif feature(1).my_params.norm_pre_pca == 2
|
wolffd@0
|
234
|
wolffd@0
|
235 X = mapstd('apply', X, feature(1).common.pca.pre_norm);
|
wolffd@0
|
236 end
|
wolffd@0
|
237
|
wolffd@0
|
238 % apply PCA transform
|
wolffd@0
|
239 vec = processpca('apply', X, feature(1).common.pca.transform);
|
wolffd@0
|
240
|
wolffd@0
|
241 % normalise pca values after transformation
|
wolffd@0
|
242 if feature(1).my_params.norm_post_pca
|
wolffd@0
|
243
|
wolffd@0
|
244 vec = mapminmax('apply', vec,...
|
wolffd@0
|
245 feature(1).common.pca.post_norm);
|
wolffd@0
|
246 end
|
wolffd@0
|
247
|
wolffd@0
|
248 % ---
|
wolffd@0
|
249 % cut vector to final size.
|
wolffd@0
|
250 % NOTE: this should be done before
|
wolffd@0
|
251 % transformation to reduce computation time
|
wolffd@0
|
252 % ---
|
wolffd@0
|
253 vec = vec(1:max_size);
|
wolffd@0
|
254
|
wolffd@0
|
255 % save final vector and description
|
wolffd@0
|
256 feature(i).data.final.vector = vec;
|
wolffd@0
|
257 feature(i).data.final.dim = numel(vec);
|
wolffd@0
|
258 feature(i).data.final.vector_info.labels = info;
|
wolffd@0
|
259 end
|
wolffd@0
|
260 end
|
wolffd@0
|
261 end
|
wolffd@0
|
262
|
wolffd@0
|
263 end
|
wolffd@0
|
264 end |