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