Mercurial > hg > camir-aes2014
diff core/magnatagatune/MTTMixedFeatureGenreBasicSmPCA.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/magnatagatune/MTTMixedFeatureGenreBasicSmPCA.m Tue Feb 10 15:05:51 2015 +0000 @@ -0,0 +1,265 @@ +% -- +% This class loads and hanles the aufdio features included with the MTT +% Library +% --- +classdef MTTMixedFeatureGenreBasicSmPCA < MTTAudioFeature & handle + + properties(Constant = true) + + my_revision = str2double(substr('$Rev$', 5, -1)); + end + + properties + + % --- + % Set default parameters + % --- + my_basetype = 'MTTMixedFeatureGenreBasicSm'; + + my_params = MTTAudioFeature.inherited_params(... + 'MTTMixedFeatureGenreBasicSm', ... + 'min_pca_var', 0, ... % % fraction of variance to keep + 'max_pca_coeffs', 0, ...% max. number of final coefficients + 'norm_pre_pca', 1, ...% normalise pca coefficients after transformation + 'norm_post_pca', 1 ... + ); + end + % --- + % member functions + % --- + methods + + % --- + % constructor: pointer to feature in database + % --- + function feature = MTTMixedFeatureGenreBasicSmPCA(varargin) + + feature = feature@MTTAudioFeature(varargin{:}); + end + + % --- + % load feature data from xml file + % --- + function data = extract(feature, clip) + % load feature data by parsing xml + + global globalvars; + + % --- + % we extract the base features, and save + % the pointers to these. + % the main work is then done in the define_global_transf + % and finalise functions. + % --- + data.basefeat = clip.features(feature.my_basetype,... + feature.my_params); + + % save info data + data.info.type = 'MTTMixedFeatureGenreBasicSmPCA'; + data.info.owner_id = clip.id; + data.info.creatorrev = feature.my_revision; + + % save param data + data.info.params = feature.my_params; + + % prepare field for final features + data.final.vector = []; + data.final.dim = 0; + data.final.vector_info.labels = {}; + end + + function define_global_transform(features) + + if numel(features) == 1 + error ('Insert feature array for this method'); + end + + % --- + % We collect all the relevant genretag + % features and get the transform on this basis. + % --- + for i = 1:numel(features) + basef(i) = features(i).data.basefeat; + end + + % call the features own transsform function + basef.define_global_transform(); + + % --- + % finalise the basic features, and + % get the feature vectors; + % --- + basef.finalise(); + X = basef.vector(); + + % check dataset dimension + if numel(features) < basef.dim; + + error ('Not enough feature vectors for PCA calculation. need %d samples', ... + basef.dim); + end + + % --- + % NOTE: should the data be normalised and scaled to -1:1 + % instead of being in a range of 0-1 AND max-min = 1 + % --- + if features(1).my_params.norm_pre_pca == 1 + + [X, pstd] = mapminmax(X,-1,1); + common.pca.pre_norm = pstd; + elseif features(1).my_params.norm_pre_pca == 2 + + [X, pstd] = mapstd(X,0,1); + common.pca.pre_norm = pstd; + end + + + % --- + % get and apply the principal component analysis + % NOTE: the variance percentile is applied here, too. + % --- + + [Y, ps] = processpca(X, 0); + common.pca.transform = ps; + + % --- + % get cumulative sum of variance, and decide on cutoff + % point + % --- + v = cumsum(var(Y')); + v = v / max(v); + common.pca.transform.varpart = v; + + if features(1).my_params.min_pca_var > 0 + + min_pca_idx = find(v >= features(1).my_params.min_pca_var,1, 'first'); + + % save into pca structure + common.pca.transform.yrows = min_pca_idx; + + end + + % normalise pca values after processing + if features(1).my_params.norm_post_pca + + [Y,pmm] = mapminmax(Y,0,1); + common.pca.post_norm = pmm; + + end + + % --- + % set common feature values for mixed features + % --- + features(1).my_db.set_common(common); + + % save the transformed features straight away! + features.finalise(Y); + end + + function finalise(feature, final) + % applies a final transformation and + % collects the information of this feature within a single vector + % see info for types in specific dimensions + + % determine size + if feature(1).my_params.max_pca_coeffs > 0 + + max_size = min(feature(1).common.pca.transform.yrows, ... + feature(1).my_params.max_pca_coeffs); + else + + max_size = feature(1).common.pca.transform.yrows; + end + + + % prepare information + info = {'PCA'}; + if isfield(feature(1).common.pca.transform, 'varpart') + info(2:max_size) = num2cell(feature(1).common.pca.transform.varpart(2:max_size)); + else + info(2:max_size) = num2cell(2:max_size); + end + + + % check if features have been finalised already + if nargin == 2 && isempty(final) + + % the final vector etc already are set to zero; + return; + + elseif nargin == 2 && (numel(feature) == size(final, 2)) + + for i = 1:numel(feature) + + % save final vector and description + feature(i).data.final.vector = final(1:max_size,i); + feature(i).data.final.dim = max_size; + feature(i).data.final.vector_info.labels = info; + end + + else + % features have to be transformed first + % --- + % TODO: this code remains untested + % --- + + % check for neccesary parameters + if isempty(feature(1).my_db.commondb) + + error('Define the global transformation first') + return; + end + + + for i = 1:numel(feature) + + % check for neccesary parameters + if isempty(feature(i).my_db.commondb) + + error('Define the global transformation first') + end + + % --- + % get feature vector and apply transformation + % --- + X = feature(i).data.basefeat.vector(); + + % --- + % apply normalisation used for removing mean + % in training data + % --- + if feature(1).my_params.norm_pre_pca == 1 + + X = mapminmax('apply', X, feature(1).common.pca.pre_norm); + elseif feature(1).my_params.norm_pre_pca == 2 + + X = mapstd('apply', X, feature(1).common.pca.pre_norm); + end + + % apply PCA transform + vec = processpca('apply', X, feature(1).common.pca.transform); + + % normalise pca values after transformation + if feature(1).my_params.norm_post_pca + + vec = mapminmax('apply', vec,... + feature(1).common.pca.post_norm); + end + + % --- + % cut vector to final size. + % NOTE: this should be done before + % transformation to reduce computation time + % --- + vec = vec(1:max_size); + + % save final vector and description + feature(i).data.final.vector = vec; + feature(i).data.final.dim = numel(vec); + feature(i).data.final.vector_info.labels = info; + end + end + end + + end +end \ No newline at end of file