diff --git a/bob/pad/face/__init__.py b/bob/pad/face/__init__.py index d1ea6f773ccf84016bab2d4c0fa3db360fea8602..0c4f8c74db6c9de41137b8b7467260ee17206d8d 100644 --- a/bob/pad/face/__init__.py +++ b/bob/pad/face/__init__.py @@ -1,4 +1,4 @@ -from . import algorithm, extractor, preprocessor, database, test +from . import extractor, preprocessor, database, test def get_config(): diff --git a/bob/pad/face/algorithm/VideoCascadeSvmPadAlgorithm.py b/bob/pad/face/algorithm/VideoCascadeSvmPadAlgorithm.py deleted file mode 100644 index 5da451bce6cb78b220f8fb58a9b1287fd89e106b..0000000000000000000000000000000000000000 --- a/bob/pad/face/algorithm/VideoCascadeSvmPadAlgorithm.py +++ /dev/null @@ -1,1088 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- -""" -Created on Wed May 17 09:43:09 2017 - -@author: Olegs Nikisins -""" - -#============================================================================== -# Import what is needed here: - -from bob.pad.base.algorithm import Algorithm - -import numpy as np - -import bob.learn.libsvm - -import bob.learn.linear - -import bob.io.base - -import os - -import fnmatch - -from bob.bio.video.utils import FrameContainer - -#============================================================================== -# Main body : - - -class VideoCascadeSvmPadAlgorithm(Algorithm): - """ - This class is designed to train the **cascede** of SVMs given Frame Containers - with features of real and attack classes. The procedure is the following: - - 1. First, the input data is mean-std normalized. - - 2. Second, the PCA is trained on normalized input features. Only the - features of the **real** class are used in PCA training, both - for one-class and two-class SVMs. - - 3. The features are next projected given trained PCA machine. - - 4. Prior to SVM training the features are again mean-std normalized. - - 5. Next SVM machine is trained for each N projected features. First, preojected - features corresponding to highest eigenvalues are selected. N is usually small - N = (2, 3). So, if N = 2, the first SVM is trained for projected features 1 and 2, - second SVM is trained for projected features 3 and 4, and so on. - - 6. These SVMs then form a cascade of classifiers. The input feature vector is then - projected using PCA machine and passed through all classifiers in the cascade. - The decision is then made by majority voting. - - Both one-class SVM and two-class SVM cascades can be trained. - In this implementation the grid search of SVM parameters is not supported. - - **Parameters:** - - ``machine_type`` : :py:class:`str` - A type of the SVM machine. Please check ``bob.learn.libsvm`` for - more details. Default: 'C_SVC'. - - ``kernel_type`` : :py:class:`str` - A type of kerenel for the SVM machine. Please check ``bob.learn.libsvm`` - for more details. Default: 'RBF'. - - ``svm_kwargs`` : :py:class:`dict` - Dictionary containing the hyper-parameters of the SVM. - Default: {'cost': 1, 'gamma': 0}. - - ``N`` : :py:class:`int` - The number of features to be used for training a single SVM machine - in the cascade. Default: 2. - - ``pos_scores_slope`` : :py:class:`float` - The positive scores returned by SVM cascade will be multiplied by this - constant prior to majority voting. Default: 0.01 . - - ``frame_level_scores_flag`` : :py:class:`bool` - Return scores for each frame individually if True. Otherwise, return a - single score per video. Default: False. - """ - - def __init__(self, - machine_type='C_SVC', - kernel_type='RBF', - svm_kwargs={'cost': 1, - 'gamma': 0}, - N=2, - pos_scores_slope=0.01, - frame_level_scores_flag=False): - - Algorithm.__init__( - self, - machine_type=machine_type, - kernel_type=kernel_type, - svm_kwargs=svm_kwargs, - N=N, - pos_scores_slope=pos_scores_slope, - frame_level_scores_flag=frame_level_scores_flag, - performs_projection=True, - requires_projector_training=True) - - self.machine_type = machine_type - self.kernel_type = kernel_type - self.svm_kwargs = svm_kwargs - self.N = N - self.pos_scores_slope = pos_scores_slope - self.frame_level_scores_flag = frame_level_scores_flag - - self.pca_projector_file_name = "pca_projector" # pca machine will be saved to .hdf5 file with this name - self.svm_projector_file_name = "svm_projector" # svm machines will be saved to .hdf5 files with this name augumented by machine number - - self.pca_machine = None - self.svm_machines = None - - #========================================================================== - def convert_frame_cont_to_array(self, frame_container): - """ - This function converts a single Frame Container into an array of features. - The rows are samples, the columns are features. - - **Parameters:** - - ``frame_container`` : object - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames. - The rows are samples, the columns are features. - """ - - feature_vectors = [] - - frame_dictionary = {} - - for frame in frame_container: - - frame_dictionary[frame[0]] = frame[1] - - for idx, _ in enumerate(frame_container): - - # Frames are stored in a mixed order, therefore we get them using incrementing frame index: - feature_vectors.append(frame_dictionary[str(idx)]) - - features_array = np.vstack(feature_vectors) - - return features_array - - #========================================================================== - def convert_list_of_frame_cont_to_array(self, frame_containers): - """ - This function converts a list of Frame containers into an array of features. - Features from different frame containers (individuals) are concatenated into the - same list. This list is then converted to an array. The rows are samples, - the columns are features. - - **Parameters:** - - ``frame_containers`` : [FrameContainer] - A list of Frame Containers, , see ``bob.bio.video.utils.FrameContainer``. - Each frame Container contains feature vectors for the particular individual/person. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames of all individuals. - """ - - feature_vectors = [] - - for frame_container in frame_containers: - - video_features_array = self.convert_frame_cont_to_array( - frame_container) - - feature_vectors.append(video_features_array) - - features_array = np.vstack(feature_vectors) - - return features_array - - #========================================================================== - def comp_prediction_precision(self, machine, real, attack): - """ - This function computes the precision of the predictions as a ratio - of correctly classified samples to the total number of samples. - - **Parameters:** - - ``machine`` : object - A pre-trained SVM machine. - - ``real`` : 2D :py:class:`numpy.ndarray` - Array of features representing the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Array of features representing the attack class. - - **Returns:** - - ``precision`` : :py:class:`float` - The precision of the predictions. - """ - - labels_real = machine.predict_class(real) - - labels_attack = machine.predict_class(attack) - - samples_num = len(labels_real) + len(labels_attack) - - precision = (np.sum(labels_real == 1) + np.sum(labels_attack == -1) - ).astype(np.float) / samples_num - - return precision - - #========================================================================== - def mean_std_normalize(self, - features, - features_mean=None, - features_std=None): - """ - The features in the input 2D array are mean-std normalized. - The rows are samples, the columns are features. If ``features_mean`` - and ``features_std`` are provided, then these vectors will be used for - normalization. Otherwise, the mean and std of the features is - computed on the fly. - - **Parameters:** - - ``features`` : 2D :py:class:`numpy.ndarray` - Array of features to be normalized. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. Default: None. - - ``features_std`` : 2D :py:class:`numpy.ndarray` - Standart deviation of the features. Default: None. - - **Returns:** - - ``features_norm`` : 2D :py:class:`numpy.ndarray` - Normalized array of features. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - features = np.copy(features) - - # Compute mean and std if not given: - if features_mean is None: - - features_mean = np.mean(features, axis=0) - - features_std = np.std(features, axis=0) - - row_norm_list = [] - - for row in features: # row is a sample - - row_norm = (row - features_mean) / features_std - - row_norm_list.append(row_norm) - - features_norm = np.vstack(row_norm_list) - - return features_norm, features_mean, features_std - - #========================================================================== - def norm_train_data(self, real, attack, one_class_flag): - """ - Mean-std normalization of input data arrays. If ``one_class_flag = True`` - the ``attack`` argument can be anything, it will be skipped. - - **Parameters:** - - ``real`` : 2D :py:class:`numpy.ndarray` - Training features for the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Training features for the attack class. If ``one_class_flag = True`` - this argument can be anything, it will be skipped. - - ``one_class_flag`` : :py:class:`bool` - If ``True``, only real features will be used in the computation of - mean and std normalization vectors. Otherwise both sets are used. - - **Returns:** - - ``real_norm`` : 2D :py:class:`numpy.ndarray` - Mean-std normalized training features for the real class. - - ``attack_norm`` : 2D :py:class:`numpy.ndarray` - Mean-std normalized training features for the attack class. - Or an empty list if ``one_class_flag = True``. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - if not (one_class_flag): # two-class SVM case - - features = np.vstack([real, attack]) - features_norm, features_mean, features_std = self.mean_std_normalize( - features) - real_norm = features_norm[0:real.shape[ - 0], :] # The array is now normalized - attack_norm = features_norm[real.shape[ - 0]:, :] # The array is now normalized - - else: # one-class SVM case - - real_norm, features_mean, features_std = self.mean_std_normalize( - real) # use only real class to compute normalizers - attack_norm = [] - - -# attack_norm = self.mean_std_normalize(attack, features_mean, features_std) - - return real_norm, attack_norm, features_mean, features_std - - #========================================================================== - def train_pca(self, data): - """ - Train PCA given input array of feature vectors. The data is mean-std - normalized prior to PCA training. - - **Parameters:** - - ``data`` : 2D :py:class:`numpy.ndarray` - Array of feature vectors of the size (N_samples x N_features). - The features must be already mean-std normalized. - - **Returns:** - - ``machine`` : :py:class:`bob.learn.linear.Machine` - The PCA machine that has been trained. The mean-std normalizers are - also set in the machine. - - ``eig_vals`` : 1D :py:class:`numpy.ndarray` - The eigen-values of the PCA projection. - """ - - # 1. Normalize the training data: - data_norm, features_mean, features_std = self.mean_std_normalize(data) - - trainer = bob.learn.linear.PCATrainer() # Creates a PCA trainer - - [machine, eig_vals] = trainer.train( - data_norm) # Trains the machine with the given data - - # Set the normalizers for the PCA machine, needed to normalize the test samples. - machine.input_subtract = features_mean # subtract the mean of train data - machine.input_divide = features_std # divide by std of train data - - return machine, eig_vals - - #========================================================================== - def train_svm(self, real, attack, machine_type, kernel_type, svm_kwargs): - """ - One-class or two class-SVM is trained in this method given input features. - The value of ``attack`` argument is not important in the case of one-class SVM. - Prior to training the data is mean-std normalized. - - **Parameters:** - - ``real`` : 2D :py:class:`numpy.ndarray` - Training features for the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Training features for the attack class. If machine_type == 'ONE_CLASS' - this argument can be anything, it will be skipped. - - ``machine_type`` : :py:class:`str` - A type of the SVM machine. Please check ``bob.learn.libsvm`` for - more details. - - ``kernel_type`` : :py:class:`str` - A type of kerenel for the SVM machine. Please check ``bob.learn.libsvm`` - for more details. - - ``svm_kwargs`` : :py:class:`dict` - Dictionary containing the hyper-parameters of the SVM. - - **Returns:** - - ``machine`` : object - A trained SVM machine. The mean-std normalizers are also set in the - machine. - """ - - one_class_flag = ( - machine_type == 'ONE_CLASS') # True if one-class SVM is used - - # Mean-std normalize the data before training - real, attack, features_mean, features_std = self.norm_train_data( - real, attack, one_class_flag) - # real and attack - are now mean-std normalized - - trainer = bob.learn.libsvm.Trainer( - machine_type=machine_type, - kernel_type=kernel_type, - probability=True) - - for key in svm_kwargs.keys(): - - setattr(trainer, key, - svm_kwargs[key]) # set the hyper-parameters of the SVM - - if not (one_class_flag): # two-class SVM case - - data = [real, attack] # data for final training - - else: # one-class SVM case - - data = [real] # only real class used for training - - machine = trainer.train(data) # train the machine - - # add the normalizers to the trained SVM machine - machine.input_subtract = features_mean # subtract the mean of train data - machine.input_divide = features_std # divide by std of train data - - return machine - - #========================================================================== - def get_data_start_end_idx(self, data, N): - """ - Get indexes to select the subsets of data related to the cascades. - First (n_machines - 1) SVMs will be trained using N features. - Last SVM will be trained using remaining features, which is less or - equal to N. - - **Parameters:** - - ``data`` : 2D :py:class:`numpy.ndarray` - Data array containing the training features. The dimensionality is - (N_samples x N_features). - - ``N`` : :py:class:`int` - Number of features per single SVM. - - **Returns:** - - ``idx_start`` : [int] - Starting indexes for data subsets. - - ``idx_end`` : [int] - End indexes for data subsets. - - ``n_machines`` : :py:class:`int` - Number of SVMs to be trained. - """ - - n_features = data.shape[1] - - n_machines = np.int(n_features / N) - - if (n_features - - n_machines * N) > 1: # if more than one feature remains - - machines_num = range(0, n_machines, 1) - - idx_start = [item * N for item in machines_num] - - idx_end = [(item + 1) * N for item in machines_num] - - idx_start.append(n_machines * N) - - idx_end.append(n_features) - - n_machines = n_machines + 1 - - else: - - machines_num = range(0, n_machines, 1) - - idx_start = [item * N for item in machines_num] - - idx_end = [(item + 1) * N for item in machines_num] - - return idx_start, idx_end, n_machines - - #========================================================================== - def train_svm_cascade(self, real, attack, machine_type, kernel_type, - svm_kwargs, N): - """ - Train a cascade of SVMs, one SVM machine per N features. N is usually small - N = (2, 3). So, if N = 2, the first SVM is trained for features 1 and 2, - second SVM is trained for features 3 and 4, and so on. - - Both one-class and two-class SVM cascades can be trained. The value of - ``attack`` argument is not important in the case of one-class SVM. - - The data is mean-std normalized prior to SVM cascade training. - - **Parameters:** - - ``real`` : 2D :py:class:`numpy.ndarray` - Training features for the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Training features for the attack class. If machine_type == 'ONE_CLASS' - this argument can be anything, it will be skipped. - - ``machine_type`` : :py:class:`str` - A type of the SVM machine. Please check ``bob.learn.libsvm`` for - more details. - - ``kernel_type`` : :py:class:`str` - A type of kerenel for the SVM machine. Please check ``bob.learn.libsvm`` - for more details. - - ``svm_kwargs`` : :py:class:`dict` - Dictionary containing the hyper-parameters of the SVM. - - ``N`` : :py:class:`int` - The number of features to be used for training a single SVM machine - in the cascade. - - **Returns:** - - ``machines`` : :py:class:`dict` - A dictionary containing a cascade of trained SVM machines. - """ - - one_class_flag = ( - machine_type == 'ONE_CLASS') # True if one-class SVM is used - - idx_start, idx_end, n_machines = self.get_data_start_end_idx(real, N) - - machines = {} - - for machine_num in range(0, n_machines, 1): - - if not (one_class_flag): # two-class SVM - - real_subset = real[:, idx_start[machine_num]:idx_end[ - machine_num]] # both real and attack classes are used - attack_subset = attack[:, idx_start[machine_num]:idx_end[ - machine_num]] - - else: # one-class SVM case - - real_subset = real[:, idx_start[machine_num]:idx_end[ - machine_num]] # only the real class is used - attack_subset = [] - - machine = self.train_svm(real_subset, attack_subset, machine_type, - kernel_type, svm_kwargs) - - machines[str(machine_num)] = machine - - del machine - - return machines - - #========================================================================== - def train_pca_svm_cascade(self, real, attack, machine_type, kernel_type, - svm_kwargs, N): - """ - This function is designed to train the **cascede** of SVMs given - features of real and attack classes. The procedure is the following: - - 1. First, the PCA machine is trained also incorporating mean-std - feature normalization. Only the features of the **real** class are - used in PCA training, both for one-class and two-class SVMs. - - 2. The features are next projected given trained PCA machine. - - 3. Next, SVM machine is trained for each N projected features. Prior to - SVM training the features are again mean-std normalized. First, preojected - features corresponding to highest eigenvalues are selected. N is usually small - N = (2, 3). So, if N = 2, the first SVM is trained for projected features 1 and 2, - second SVM is trained for projected features 3 and 4, and so on. - - Both one-class SVM and two-class SVM cascades can be trained. - In this implementation the grid search of SVM parameters is not supported. - - **Parameters:** - - ``real`` : 2D :py:class:`numpy.ndarray` - Training features for the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Training features for the attack class. If machine_type == 'ONE_CLASS' - this argument can be anything, it will be skipped. - - ``machine_type`` : :py:class:`str` - A type of the SVM machine. Please check ``bob.learn.libsvm`` for - more details. - - ``kernel_type`` : :py:class:`str` - A type of kerenel for the SVM machine. Please check ``bob.learn.libsvm`` - for more details. - - ``svm_kwargs`` : :py:class:`dict` - Dictionary containing the hyper-parameters of the SVM. - - ``N`` : :py:class:`int` - The number of features to be used for training a single SVM machine - in the cascade. - - **Returns:** - - ``pca_machine`` : object - A trained PCA machine. - - ``svm_machines`` : :py:class:`dict` - A cascade of SVM machines. - """ - - one_class_flag = ( - machine_type == 'ONE_CLASS') # True if one-class SVM is used - - # 1. Train PCA using normalized features of the real class: - pca_machine, _ = self.train_pca( - real) # the mean-std normalizers are already set in this machine - - # 2. Project the features given PCA machine: - if not (one_class_flag): - projected_real = pca_machine( - real - ) # the normalizers are already set for the PCA machine, therefore non-normalized data is passed in - projected_attack = pca_machine( - attack - ) # the normalizers are already set for the PCA machine, therefore non-normalized data is passed in - - else: - projected_real = pca_machine( - real - ) # the normalizers are already set for the PCA machine, therefore non-normalized data is passed in - projected_attack = [] - - # 3. Train a cascade of SVM machines using **projected** data - svm_machines = self.train_svm_cascade(projected_real, projected_attack, - machine_type, kernel_type, - svm_kwargs, N) - - return pca_machine, svm_machines - - #========================================================================== - def save_machine(self, projector_file, projector_file_name, machine): - """ - Saves the machine to the hdf5 file. The name of the file is specified in - ``projector_file_name`` string. The location is specified in the - path component of the ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to save the trained projector to, as - returned by ``bob.pad.base`` framework. In this function only the path - component is used. - - ``projector_file_name`` : :py:class:`str` - The relative name of the file to save the machine to. Name without - extension. - - ``machine`` : object - The machine to be saved. - """ - - extension = ".hdf5" - - resulting_file_name = os.path.join( - os.path.split(projector_file)[0], projector_file_name + extension) - - f = bob.io.base.HDF5File(resulting_file_name, - 'w') # open hdf5 file to save to - - machine.save(f) # save the machine and normalization parameters - - del f - - #========================================================================== - def save_cascade_of_machines(self, projector_file, projector_file_name, - machines): - """ - Saves a cascade of machines to the hdf5 files. The name of the file is - specified in ``projector_file_name`` string and will be augumented with - a number of the machine. The location is specified in the path component - of the ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to save the trained projector to, as - returned by ``bob.pad.base`` framework. In this function only the path - component is used. - - ``projector_file_name`` : :py:class:`str` - The relative name of the file to save the machine to. This name will - be augumented with a number of the machine. Name without extension. - - ``machines`` : :py:class:`dict` - A cascade of machines. The key in the dictionary is the number of - the machine, value is the machine itself. - """ - - for key in machines: - - augumented_projector_file_name = projector_file_name + key - - machine = machines[key] - - self.save_machine(projector_file, augumented_projector_file_name, - machine) - - #========================================================================== - def train_projector(self, training_features, projector_file): - """ - Train PCA and cascade of SVMs for feature projection and save them - to files. The ``requires_projector_training = True`` flag must be set - to True to enable this function. - - **Parameters:** - - ``training_features`` : [[FrameContainer], [FrameContainer]] - A list containing two elements: [0] - a list of Frame Containers with - feature vectors for the real class; [1] - a list of Frame Containers with - feature vectors for the attack class. - - ``projector_file`` : :py:class:`str` - The file to save the trained projector to, as returned by the - ``bob.pad.base`` framework. In this class the names of the files to - save the projectors to are modified, see ``save_machine`` and - ``save_cascade_of_machines`` methods of this class for more details. - """ - - # training_features[0] - training features for the REAL class. - real = self.convert_list_of_frame_cont_to_array( - training_features[0]) # output is array - # training_features[1] - training features for the ATTACK class. - attack = self.convert_list_of_frame_cont_to_array( - training_features[1]) # output is array - - # Train the PCA machine and cascade of SVMs - pca_machine, svm_machines = self.train_pca_svm_cascade( - real=real, - attack=attack, - machine_type=self.machine_type, - kernel_type=self.kernel_type, - svm_kwargs=self.svm_kwargs, - N=self.N) - - # Save the PCA machine - self.save_machine(projector_file, self.pca_projector_file_name, - pca_machine) - - # Save the cascade of SVMs: - self.save_cascade_of_machines( - projector_file, self.svm_projector_file_name, svm_machines) - - #========================================================================== - def load_machine(self, projector_file, projector_file_name): - """ - Loads the machine from the hdf5 file. The name of the file is specified in - ``projector_file_name`` string. The location is specified in the - path component of the ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to load the trained projector from, as - returned by ``bob.pad.base`` framework. In this function only the path - component is used. - - ``projector_file_name`` : :py:class:`str` - The relative name of the file to load the machine from. Name without - extension. - - **Returns:** - - ``machine`` : object - A machine loaded from file. - """ - - extension = ".hdf5" - - resulting_file_name = os.path.join( - os.path.split(projector_file)[0], - projector_file_name + extension) # name of the file - - f = bob.io.base.HDF5File(resulting_file_name, - 'r') # file to read the machine from - - if "pca_" in projector_file_name: - - machine = bob.learn.linear.Machine(f) - - if "svm_" in projector_file_name: - - machine = bob.learn.libsvm.Machine(f) - - del f - - return machine - - #========================================================================== - def get_cascade_file_names(self, projector_file, projector_file_name): - """ - Get the list of file-names storing the cascade of machines. The location - of the files is specified in the path component of the ``projector_file`` - argument. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to load the trained projector from, as - returned by ``bob.pad.base`` framework. In this function only the path - component is used. - - ``projector_file_name`` : :py:class:`str` - The **common** string in the names of files storing the - cascade of pretrained machines. Name without extension. - - **Returns:** - - ``cascade_file_names`` : [str] - A list of of **relative** file-names storing the cascade of machines. - """ - - path = os.path.split(projector_file)[ - 0] # directory containing files storing the cascade of machines. - - files = [] - - for f in os.listdir(path): - - if fnmatch.fnmatch(f, projector_file_name + "*"): - - files.append(f) - - return files - - #========================================================================== - def load_cascade_of_machines(self, projector_file, projector_file_name): - """ - Loades a cascade of machines from the hdf5 files. The name of the file is - specified in ``projector_file_name`` string and will be augumented with - a number of the machine. The location is specified in the path component - of the ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to load the trained projector from, as - returned by ``bob.pad.base`` framework. In this function only the path - component is used. - - ``projector_file_name`` : :py:class:`str` - The relative name of the file to load the machine from. This name will - be augumented with a number of the machine. Name without extension. - - **Returns:** - - ``machines`` : :py:class:`dict` - A cascade of machines. The key in the dictionary is the number of - the machine, value is the machine itself. - """ - - files = self.get_cascade_file_names( - projector_file, projector_file_name) # files storing the cascade - - machines = {} - - for idx, _ in enumerate(files): - - machine = self.load_machine(projector_file, - projector_file_name + str(idx)) - - machines[str(idx)] = machine - - return machines - - #========================================================================== - def load_projector(self, projector_file): - """ - Load the pretrained PCA machine and a cascade of SVM classifiers from - files to perform feature projection. - This function sets the arguments ``self.pca_machine`` and ``self.svm_machines`` - of this class with loaded machines. - - The function must be capable of reading the data saved with the - :py:meth:`train_projector` method of this class. - - Please register `performs_projection = True` in the constructor to - enable this function. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - The file to read the projector from, as returned by the - ``bob.pad.base`` framework. In this class the names of the files to - read the projectors from are modified, see ``load_machine`` and - ``load_cascade_of_machines`` methods of this class for more details. - """ - - # Load the PCA machine - pca_machine = self.load_machine(projector_file, - self.pca_projector_file_name) - - # Load the cascade of SVMs: - svm_machines = self.load_cascade_of_machines( - projector_file, self.svm_projector_file_name) - - self.pca_machine = pca_machine - self.svm_machines = svm_machines - - #========================================================================== - def combine_scores_of_svm_cascade(self, scores_array, pos_scores_slope): - """ - First, multiply positive scores by constant ``pos_scores_slope`` in the - input 2D array. The constant is usually small, making the impact of negative - scores more significant. - Second, the a single score per sample is obtained by avaraging the - **pre-modified** scores of the cascade. - - **Parameters:** - - ``scores_array`` : 2D :py:class:`numpy.ndarray` - 2D score array of the size (N_samples x N_scores). - - ``pos_scores_slope`` : :py:class:`float` - The positive scores returned by SVM cascade will be multiplied by this - constant prior to majority voting. Default: 0.01 . - - **Returns:** - - ``scores`` : 1D :py:class:`numpy.ndarray` - Vector of scores. Scores for the real class are expected to be - higher, than the scores of the negative / attack class. - """ - - cols = [] - - for col in scores_array.T: - - idx_vec = np.where(col >= 0) - - col[idx_vec] *= pos_scores_slope # multiply positive scores by the constant - - cols.append(col) - - scores_array_modified = np.stack(cols, axis=1) - - scores = np.mean(scores_array_modified, axis=1) - - return scores - - #========================================================================== - def project(self, feature): - """ - This function computes a vector of scores for each sample in the input - array of features. The following steps are apllied: - - 1. Convert input array to numpy array if necessary. - - 2. Project features using pretrained PCA machine. - - 3. Apply the cascade of SVMs to the preojected features. - - 4. Compute a single score per sample by combining the scores produced - by the cascade of SVMs. The combination is done using - ``combine_scores_of_svm_cascade`` method of this class. - - Set ``performs_projection = True`` in the constructor to enable this function. - It is assured that the :py:meth:`load_projector` was **called before** the - ``project`` function is executed. - - **Parameters:** - - ``feature`` : FrameContainer or 2D :py:class:`numpy.ndarray` - Two types of inputs are accepted. - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - Or a 2D feature array of the size (N_samples x N_features). - - **Returns:** - - ``scores`` : 1D :py:class:`numpy.ndarray` - Vector of scores. Scores for the real class are expected to be - higher, than the scores of the negative / attack class. - """ - - # 1. Convert input array to numpy array if necessary. - if isinstance( - feature, - FrameContainer): # if FrameContainer convert to 2D numpy array - - features_array = self.convert_frame_cont_to_array(feature) - - else: - - features_array = feature - - # 2. Project features using pretrained PCA machine. - pca_projected_features = self.pca_machine(features_array) - - # 3. Apply the cascade of SVMs to the preojected features. - all_scores = [] - - idx_start, idx_end, n_machines = self.get_data_start_end_idx( - pca_projected_features, self.N) - - for machine_num in range(0, n_machines, - 1): # iterate over SVM machines - - svm_machine = self.svm_machines[str( - machine_num)] # select a machine - - # subset of PCA projected features to be passed to SVM machine - pca_projected_features_subset = pca_projected_features[:, idx_start[ - machine_num]:idx_end[machine_num]] - - # for two-class SVM select the scores corresponding to the real class only, done by [:,0]. Index [0] selects the class Index [1] selects the score.. - single_machine_scores = svm_machine.predict_class_and_scores( - pca_projected_features_subset)[1][:, 0] - - all_scores.append(single_machine_scores) - - all_scores_array = np.stack(all_scores, axis=1).astype(np.float) - - # 4. Combine the scores: - - one_class_flag = (svm_machine.machine_type == 'ONE_CLASS' - ) # True if one-class SVM is used - - if not (one_class_flag): - - scores = np.mean( - all_scores_array, axis=1) # compute mean for two-class SVM - - else: # one class SVM case - - scores = self.combine_scores_of_svm_cascade( - all_scores_array, self.pos_scores_slope) - - return scores - - #========================================================================== - def score(self, toscore): - """ - Returns a probability of a sample being a real class. - - **Parameters:** - - ``toscore`` : 1D or 2D :py:class:`numpy.ndarray` - 2D in the case of two-class SVM. - An array containing class probabilities for each frame. - First column contains probabilities for each frame being a real class. - Second column contains probabilities for each frame being an attack class. - 1D in the case of one-class SVM. - Vector with scores for each frame defining belonging to the real class. - - **Returns:** - - ``score`` : [:py:class:`float`] - If ``frame_level_scores_flag = False`` a single score is returned. - One score per video. This score is placed into a list, because - the ``score`` must be an iterable. - Score is a probability of a sample being a real class. - If ``frame_level_scores_flag = True`` a list of scores is returned. - One score per frame/sample. - """ - - if self.frame_level_scores_flag: - - score = list(toscore) - - else: - - score = [np.mean(toscore)] # compute a single score per video - - return score diff --git a/bob/pad/face/algorithm/VideoGmmPadAlgorithm.py b/bob/pad/face/algorithm/VideoGmmPadAlgorithm.py deleted file mode 100644 index a394cfc85194aecbe1dae9dda112d85911f16962..0000000000000000000000000000000000000000 --- a/bob/pad/face/algorithm/VideoGmmPadAlgorithm.py +++ /dev/null @@ -1,506 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- -""" -Created on Mon Aug 28 16:47:47 2017 - -@author: Olegs Nikisins -""" - -# ============================================================================== -# Import what is needed here: - -from bob.pad.base.algorithm import Algorithm - -from bob.bio.video.utils import FrameContainer - -import numpy as np - -import bob.io.base - -from sklearn import mixture - -# ============================================================================== -# Main body : - - -class VideoGmmPadAlgorithm(Algorithm): - """ - This class is designed to train a GMM based PAD system. The GMM is trained - using data of one class (real class) only. The procedure is the following: - - 1. First, the training data is mean-std normalized using mean and std of the - real class only. - - 2. Second, the GMM with ``n_components`` Gaussians is trained using samples - of the real class. - - 3. The input features are next classified using pre-trained GMM machine. - - **Parameters:** - - ``n_components`` : :py:class:`int` - Number of Gaussians in the GMM. Default: 1 . - - ``random_state`` : :py:class:`int` - A seed for the random number generator used in the initialization of - the GMM. Default: 7 . - - ``frame_level_scores_flag`` : :py:class:`bool` - Return scores for each frame individually if True. Otherwise, return a - single score per video. Default: False. - """ - - def __init__(self, - n_components=1, - random_state=3, - frame_level_scores_flag=False): - - Algorithm.__init__( - self, - n_components=n_components, - random_state=random_state, - frame_level_scores_flag=frame_level_scores_flag, - performs_projection=True, - requires_projector_training=True) - - self.n_components = n_components - - self.random_state = random_state - - self.frame_level_scores_flag = frame_level_scores_flag - - self.machine = None # this argument will be updated with pretrained GMM machine - - self.features_mean = None # this argument will be updated with features mean - - self.features_std = None # this argument will be updated with features std - - # names of the arguments of the pretrained GMM machine to be saved/loaded to/from HDF5 file: - self.gmm_param_keys = [ - "covariance_type", "covariances_", "lower_bound_", "means_", - "n_components", "weights_", "converged_", "precisions_", - "precisions_cholesky_" - ] - - # ========================================================================== - def convert_frame_cont_to_array(self, frame_container): - """ - This function converts a single Frame Container into an array of features. - The rows are samples, the columns are features. - - **Parameters:** - - ``frame_container`` : object - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames. - The rows are samples, the columns are features. - """ - - feature_vectors = [] - - frame_dictionary = {} - - for frame in frame_container: - frame_dictionary[frame[0]] = frame[1] - - for idx, _ in enumerate(frame_container): - # Frames are stored in a mixed order, therefore we get them using incrementing frame index: - feature_vectors.append(frame_dictionary[str(idx)]) - - features_array = np.vstack(feature_vectors) - - return features_array - - # ========================================================================== - def convert_and_prepare_features(self, features): - """ - This function converts a list or a frame container of features into a 2D array of features. - If the input is a list of frame containers, features from different frame containers (individuals) - are concatenated into the same list. This list is then converted to an array. The rows are samples, - the columns are features. - - **Parameters:** - - ``features`` : [2D :py:class:`numpy.ndarray`] or [FrameContainer] - A list or 2D feature arrays or a list of Frame Containers, see ``bob.bio.video.utils.FrameContainer``. - Each frame Container contains feature vectors for the particular individual/person. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all samples and frames. - """ - - if isinstance( - features[0], - FrameContainer): # if FrameContainer convert to 2D numpy array - return self.convert_list_of_frame_cont_to_array(features) - else: - return np.vstack(features) - - # ========================================================================== - def convert_list_of_frame_cont_to_array(self, frame_containers): - """ - This function converts a list of Frame containers into an array of features. - Features from different frame containers (individuals) are concatenated into the - same list. This list is then converted to an array. The rows are samples, - the columns are features. - - **Parameters:** - - ``frame_containers`` : [FrameContainer] - A list of Frame Containers, , see ``bob.bio.video.utils.FrameContainer``. - Each frame Container contains feature vectors for the particular individual/person. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames of all individuals. - """ - - feature_vectors = [] - - for frame_container in frame_containers: - video_features_array = self.convert_frame_cont_to_array( - frame_container) - - feature_vectors.append(video_features_array) - - features_array = np.vstack(feature_vectors) - - return features_array - - # ========================================================================== - def mean_std_normalize(self, - features, - features_mean=None, - features_std=None): - """ - The features in the input 2D array are mean-std normalized. - The rows are samples, the columns are features. If ``features_mean`` - and ``features_std`` are provided, then these vectors will be used for - normalization. Otherwise, the mean and std of the features is - computed on the fly. - - **Parameters:** - - ``features`` : 2D :py:class:`numpy.ndarray` - Array of features to be normalized. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. Default: None. - - ``features_std`` : 2D :py:class:`numpy.ndarray` - Standart deviation of the features. Default: None. - - **Returns:** - - ``features_norm`` : 2D :py:class:`numpy.ndarray` - Normalized array of features. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - features = np.copy(features) - - # Compute mean and std if not given: - if features_mean is None: - features_mean = np.mean(features, axis=0) - - features_std = np.std(features, axis=0) - - row_norm_list = [] - - for row in features: # row is a sample - - row_norm = (row - features_mean) / features_std - - row_norm_list.append(row_norm) - - features_norm = np.vstack(row_norm_list) - - return features_norm, features_mean, features_std - - # ========================================================================== - def train_gmm(self, real, n_components, random_state): - """ - Train GMM classifier given real class. Prior to the training the data is - mean-std normalized. - - **Parameters:** - - ``real`` : 2D :py:class:`numpy.ndarray` - Training features for the real class. - - ``n_components`` : :py:class:`int` - Number of Gaussians in the GMM. Default: 1 . - - ``random_state`` : :py:class:`int` - A seed for the random number generator used in the initialization of - the GMM. Default: 7 . - - **Returns:** - - ``machine`` : object - A trained GMM machine. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - features_norm, features_mean, features_std = self.mean_std_normalize( - real) - # real is now mean-std normalized - - machine = mixture.GaussianMixture( - n_components=n_components, - random_state=random_state, - covariance_type='full') - - machine.fit(features_norm) - - return machine, features_mean, features_std - - # ========================================================================== - def save_gmm_machine_and_mean_std(self, projector_file, machine, - features_mean, features_std): - """ - Saves the GMM machine, features mean and std to the hdf5 file. - The absolute name of the file is specified in ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to save the data to, as returned by - ``bob.pad.base`` framework. - - ``machine`` : object - The GMM machine to be saved. As returned by sklearn.linear_model - module. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - f = bob.io.base.HDF5File(projector_file, - 'w') # open hdf5 file to save to - - for key in self.gmm_param_keys: - data = getattr(machine, key) - - f.set(key, data) - - f.set("features_mean", features_mean) - - f.set("features_std", features_std) - - del f - - # ========================================================================== - def train_projector(self, training_features, projector_file): - """ - Train GMM for feature projection and save it to file. - The ``requires_projector_training = True`` flag must be set to True - to enable this function. - - **Parameters:** - - ``training_features`` : [[FrameContainer], [FrameContainer]] - A list containing two elements: [0] - a list of Frame Containers with - feature vectors for the real class; [1] - a list of Frame Containers with - feature vectors for the attack class. - - ``projector_file`` : :py:class:`str` - The file to save the trained projector to, as returned by the - ``bob.pad.base`` framework. - """ - - # training_features[0] - training features for the REAL class. - real = self.convert_and_prepare_features( - training_features[0]) # output is array - - # training_features[1] - training features for the ATTACK class. - # attack = self.convert_and_prepare_features(training_features[1]) # output is array - - # Train the GMM machine and get normalizers: - machine, features_mean, features_std = self.train_gmm( - real=real, - n_components=self.n_components, - random_state=self.random_state) - - # Save the GNN machine and normalizers: - self.save_gmm_machine_and_mean_std(projector_file, machine, - features_mean, features_std) - - # ========================================================================== - def load_gmm_machine_and_mean_std(self, projector_file): - """ - Loads the machine, features mean and std from the hdf5 file. - The absolute name of the file is specified in ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to load the trained projector from, as - returned by ``bob.pad.base`` framework. - - **Returns:** - - ``machine`` : object - The loaded GMM machine. As returned by sklearn.mixture module. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - f = bob.io.base.HDF5File(projector_file, - 'r') # file to read the machine from - - # initialize the machine: - machine = mixture.GaussianMixture() - - # set the params of the machine: - for key in self.gmm_param_keys: - data = f.read(key) - - setattr(machine, key, data) - - features_mean = f.read("features_mean") - - features_std = f.read("features_std") - - del f - - return machine, features_mean, features_std - - # ========================================================================== - def load_projector(self, projector_file): - """ - Loads the machine, features mean and std from the hdf5 file. - The absolute name of the file is specified in ``projector_file`` string. - - This function sets the arguments ``self.machine``, ``self.features_mean`` - and ``self.features_std`` of this class with loaded machines. - - The function must be capable of reading the data saved with the - :py:meth:`train_projector` method of this class. - - Please register `performs_projection = True` in the constructor to - enable this function. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - The file to read the projector from, as returned by the - ``bob.pad.base`` framework. In this class the names of the files to - read the projectors from are modified, see ``load_machine`` and - ``load_cascade_of_machines`` methods of this class for more details. - """ - - machine, features_mean, features_std = self.load_gmm_machine_and_mean_std( - projector_file) - - self.machine = machine - - self.features_mean = features_mean - - self.features_std = features_std - - # ========================================================================== - def project(self, feature): - """ - This function computes a vector of scores for each sample in the input - array of features. The following steps are applied: - - 1. First, the input data is mean-std normalized using mean and std of the - real class only. - - 2. The input features are next classified using pre-trained GMM machine. - - Set ``performs_projection = True`` in the constructor to enable this function. - It is assured that the :py:meth:`load_projector` was **called before** the - ``project`` function is executed. - - **Parameters:** - - ``feature`` : FrameContainer or 2D :py:class:`numpy.ndarray` - Two types of inputs are accepted. - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - Or a 2D feature array of the size (N_samples x N_features). - - **Returns:** - - ``scores`` : 1D :py:class:`numpy.ndarray` - Vector of scores. Scores for the real class are expected to be - higher, than the scores of the negative / attack class. - In this case scores are the weighted log probabilities. - """ - - # 1. Convert input array to numpy array if necessary. - if isinstance( - feature, - FrameContainer): # if FrameContainer convert to 2D numpy array - - features_array = self.convert_frame_cont_to_array(feature) - - else: - - features_array = feature - - features_array_norm, _, _ = self.mean_std_normalize( - features_array, self.features_mean, self.features_std) - - scores = self.machine.score_samples(features_array_norm) - - return scores - - # ========================================================================== - def score(self, toscore): - """ - Returns a probability of a sample being a real class. - - **Parameters:** - - ``toscore`` : 1D :py:class:`numpy.ndarray` - Vector with scores for each frame/sample defining the probability - of the frame being a sample of the real class. - - **Returns:** - - ``score`` : [:py:class:`float`] - If ``frame_level_scores_flag = False`` a single score is returned. - One score per video. This score is placed into a list, because - the ``score`` must be an iterable. - Score is a probability of a sample being a real class. - If ``frame_level_scores_flag = True`` a list of scores is returned. - One score per frame/sample. - """ - - if self.frame_level_scores_flag: - - score = list(toscore) - - else: - - score = [np.mean(toscore)] # compute a single score per video - - return score diff --git a/bob/pad/face/algorithm/VideoLRPadAlgorithm.py b/bob/pad/face/algorithm/VideoLRPadAlgorithm.py deleted file mode 100644 index 2788e80659b7c37c9818329d4f03027b2b9b5a64..0000000000000000000000000000000000000000 --- a/bob/pad/face/algorithm/VideoLRPadAlgorithm.py +++ /dev/null @@ -1,594 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- -""" -Created on Fri Aug 25 09:29:02 2017 - -@author: Olegs Nikisins -""" - -#============================================================================== -# Import what is needed here: - -from bob.pad.base.algorithm import Algorithm - -from bob.bio.video.utils import FrameContainer - -import numpy as np - -from sklearn import linear_model - -import bob.io.base - -#============================================================================== -# Main body : - - -class VideoLRPadAlgorithm(Algorithm): - """ - This class is designed to train Logistic Regression classifier given Frame Containers - with features of real and attack classes. The procedure is the following: - - 1. First, the input data is mean-std normalized using mean and std of the - real class only. - - 2. Second, the Logistic Regression classifier is trained on normalized - input features. - - 3. The input features are next classified using pre-trained LR machine. - - **Parameters:** - - ``C`` : :py:class:`float` - Inverse of regularization strength in LR classifier; must be a positive. - Like in support vector machines, smaller values specify stronger - regularization. Default: 1.0 . - - ``frame_level_scores_flag`` : :py:class:`bool` - Return scores for each frame individually if True. Otherwise, return a - single score per video. Default: ``False``. - - ``subsample_train_data_flag`` : :py:class:`bool` - Uniformly subsample the training data if ``True``. Default: ``False``. - - ``subsampling_step`` : :py:class:`int` - Training data subsampling step, only valid is - ``subsample_train_data_flag = True``. Default: 10 . - - ``subsample_videos_flag`` : :py:class:`bool` - Uniformly subsample the training videos if ``True``. Default: ``False``. - - ``video_subsampling_step`` : :py:class:`int` - Training videos subsampling step, only valid is - ``subsample_videos_flag = True``. Default: 3 . - """ - - def __init__(self, - C=1, - frame_level_scores_flag=False, - subsample_train_data_flag=False, - subsampling_step=10, - subsample_videos_flag=False, - video_subsampling_step=3): - - Algorithm.__init__( - self, - C=C, - frame_level_scores_flag=frame_level_scores_flag, - subsample_train_data_flag=subsample_train_data_flag, - subsampling_step=subsampling_step, - subsample_videos_flag=subsample_videos_flag, - video_subsampling_step=video_subsampling_step, - performs_projection=True, - requires_projector_training=True) - - self.C = C - - self.frame_level_scores_flag = frame_level_scores_flag - - self.subsample_train_data_flag = subsample_train_data_flag - - self.subsampling_step = subsampling_step - - self.subsample_videos_flag = subsample_videos_flag - - self.video_subsampling_step = video_subsampling_step - - self.lr_machine = None # this argument will be updated with pretrained LR machine - - self.features_mean = None # this argument will be updated with features mean - self.features_std = None # this argument will be updated with features std - - # names of the arguments of the pretrained LR machine to be saved/loaded to/from HDF5 file: - self.lr_param_keys = ["C", "classes_", "coef_", "intercept_"] - - #========================================================================== - def convert_frame_cont_to_array(self, frame_container): - """ - This function converts a single Frame Container into an array of features. - The rows are samples, the columns are features. - - **Parameters:** - - ``frame_container`` : object - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames. - The rows are samples, the columns are features. - """ - - feature_vectors = [] - - frame_dictionary = {} - - for frame in frame_container: - - frame_dictionary[frame[0]] = frame[1] - - for idx, _ in enumerate(frame_container): - - # Frames are stored in a mixed order, therefore we get them using incrementing frame index: - feature_vectors.append(frame_dictionary[str(idx)]) - - features_array = np.vstack(feature_vectors) - - return features_array - - #========================================================================== - def convert_list_of_frame_cont_to_array(self, frame_containers): - """ - This function converts a list of Frame containers into an array of features. - Features from different frame containers (individuals) are concatenated into the - same list. This list is then converted to an array. The rows are samples, - the columns are features. - - **Parameters:** - - ``frame_containers`` : [FrameContainer] - A list of Frame Containers, , see ``bob.bio.video.utils.FrameContainer``. - Each frame Container contains feature vectors for the particular individual/person. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames of all individuals. - """ - - feature_vectors = [] - - for frame_container in frame_containers: - - video_features_array = self.convert_frame_cont_to_array( - frame_container) - - feature_vectors.append(video_features_array) - - features_array = np.vstack(feature_vectors) - - return features_array - - #========================================================================== - def mean_std_normalize(self, - features, - features_mean=None, - features_std=None): - """ - The features in the input 2D array are mean-std normalized. - The rows are samples, the columns are features. If ``features_mean`` - and ``features_std`` are provided, then these vectors will be used for - normalization. Otherwise, the mean and std of the features is - computed on the fly. - - **Parameters:** - - ``features`` : 2D :py:class:`numpy.ndarray` - Array of features to be normalized. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. Default: None. - - ``features_std`` : 2D :py:class:`numpy.ndarray` - Standart deviation of the features. Default: None. - - **Returns:** - - ``features_norm`` : 2D :py:class:`numpy.ndarray` - Normalized array of features. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - features = np.copy(features) - - # Compute mean and std if not given: - if features_mean is None: - - features_mean = np.mean(features, axis=0) - - features_std = np.std(features, axis=0) - - row_norm_list = [] - - for row in features: # row is a sample - - row_norm = (row - features_mean) / features_std - - row_norm_list.append(row_norm) - - features_norm = np.vstack(row_norm_list) - - return features_norm, features_mean, features_std - - #========================================================================== - def norm_train_data(self, real, attack): - """ - Mean-std normalization of input data arrays. The mean and std normalizers - are computed using real class only. - - **Parameters:** - - ``real`` : 2D :py:class:`numpy.ndarray` - Training features for the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Training features for the attack class. - - **Returns:** - - ``real_norm`` : 2D :py:class:`numpy.ndarray` - Mean-std normalized training features for the real class. - - ``attack_norm`` : 2D :py:class:`numpy.ndarray` - Mean-std normalized training features for the attack class. - Or an empty list if ``one_class_flag = True``. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - real_norm, features_mean, features_std = self.mean_std_normalize(real) - - attack_norm, _, _ = self.mean_std_normalize(attack, features_mean, - features_std) - - return real_norm, attack_norm, features_mean, features_std - - #========================================================================== - def train_lr(self, real, attack, C): - """ - Train LR classifier given real and attack classes. Prior to training - the data is mean-std normalized. - - **Parameters:** - - ``real`` : 2D :py:class:`numpy.ndarray` - Training features for the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Training features for the attack class. - - ``C`` : :py:class:`float` - Inverse of regularization strength in LR classifier; must be a positive. - Like in support vector machines, smaller values specify stronger - regularization. Default: 1.0 . - - **Returns:** - - ``machine`` : object - A trained LR machine. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - real, attack, features_mean, features_std = self.norm_train_data( - real, attack) - # real and attack - are now mean-std normalized - - X = np.vstack([real, attack]) - - Y = np.hstack([np.zeros(len(real)), np.ones(len(attack))]) - - machine = linear_model.LogisticRegression(C=C) - - machine.fit(X, Y) - - return machine, features_mean, features_std - - #========================================================================== - def save_lr_machine_and_mean_std(self, projector_file, machine, - features_mean, features_std): - """ - Saves the LR machine, features mean and std to the hdf5 file. - The absolute name of the file is specified in ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to save the data to, as returned by - ``bob.pad.base`` framework. - - ``machine`` : object - The LR machine to be saved. As returned by sklearn.linear_model - module. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - f = bob.io.base.HDF5File(projector_file, - 'w') # open hdf5 file to save to - - for key in self.lr_param_keys: # ["C", "classes_", "coef_", "intercept_"] - - data = getattr(machine, key) - - f.set(key, data) - - f.set("features_mean", features_mean) - - f.set("features_std", features_std) - - del f - - #========================================================================== - def subsample_train_videos(self, training_features, step): - """ - Uniformly select subset of frmae containes from the input list - - **Parameters:** - - ``training_features`` : [FrameContainer] - A list of FrameContainers - - ``step`` : :py:class:`int` - Data selection step. - - **Returns:** - - ``training_features_subset`` : [FrameContainer] - A list with selected FrameContainers - """ - - indexes = range(0, len(training_features), step) - - training_features_subset = [training_features[x] for x in indexes] - - return training_features_subset - - #========================================================================== - def train_projector(self, training_features, projector_file): - """ - Train LR for feature projection and save them to files. - The ``requires_projector_training = True`` flag must be set to True - to enable this function. - - **Parameters:** - - ``training_features`` : [[FrameContainer], [FrameContainer]] - A list containing two elements: [0] - a list of Frame Containers with - feature vectors for the real class; [1] - a list of Frame Containers with - feature vectors for the attack class. - - ``projector_file`` : :py:class:`str` - The file to save the trained projector to, as returned by the - ``bob.pad.base`` framework. - """ - - # training_features[0] - training features for the REAL class. - # training_features[1] - training features for the ATTACK class. - - if self.subsample_videos_flag: # subsample videos of the real class - - real = self.convert_list_of_frame_cont_to_array( - self.subsample_train_videos( - training_features[0], - self.video_subsampling_step)) # output is array - - else: - - real = self.convert_list_of_frame_cont_to_array( - training_features[0]) # output is array - - if self.subsample_train_data_flag: - - real = real[range(0, len(real), self.subsampling_step), :] - - if self.subsample_videos_flag: # subsample videos of the real class - - attack = self.convert_list_of_frame_cont_to_array( - self.subsample_train_videos( - training_features[1], - self.video_subsampling_step)) # output is array - - else: - - attack = self.convert_list_of_frame_cont_to_array( - training_features[1]) # output is array - - if self.subsample_train_data_flag: - - attack = attack[range(0, len(attack), self.subsampling_step), :] - - # Train the LR machine and get normalizers: - machine, features_mean, features_std = self.train_lr( - real=real, attack=attack, C=self.C) - - # Save the LR machine and normalizers: - self.save_lr_machine_and_mean_std(projector_file, machine, - features_mean, features_std) - - #========================================================================== - def load_lr_machine_and_mean_std(self, projector_file): - """ - Loads the machine, features mean and std from the hdf5 file. - The absolute name of the file is specified in ``projector_file`` string. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - Absolute name of the file to load the trained projector from, as - returned by ``bob.pad.base`` framework. - - **Returns:** - - ``machine`` : object - The loaded LR machine. As returned by sklearn.linear_model module. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 1D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - f = bob.io.base.HDF5File(projector_file, - 'r') # file to read the machine from - - # initialize the machine: - machine = linear_model.LogisticRegression() - - # set the params of the machine: - for key in self.lr_param_keys: # ["C", "classes_", "coef_", "intercept_"] - - data = f.read(key) - - setattr(machine, key, data) - - features_mean = f.read("features_mean") - - features_std = f.read("features_std") - - del f - - return machine, features_mean, features_std - - #========================================================================== - def load_projector(self, projector_file): - """ - Loads the machine, features mean and std from the hdf5 file. - The absolute name of the file is specified in ``projector_file`` string. - - This function sets the arguments ``self.lr_machine``, ``self.features_mean`` - and ``self.features_std`` of this class with loaded machines. - - The function must be capable of reading the data saved with the - :py:meth:`train_projector` method of this class. - - Please register `performs_projection = True` in the constructor to - enable this function. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - The file to read the projector from, as returned by the - ``bob.pad.base`` framework. In this class the names of the files to - read the projectors from are modified, see ``load_machine`` and - ``load_cascade_of_machines`` methods of this class for more details. - """ - - lr_machine, features_mean, features_std = self.load_lr_machine_and_mean_std( - projector_file) - - self.lr_machine = lr_machine - - self.features_mean = features_mean - - self.features_std = features_std - - #========================================================================== - def project(self, feature): - """ - This function computes a vector of scores for each sample in the input - array of features. The following steps are apllied: - - 1. First, the input data is mean-std normalized using mean and std of the - real class only. - - 2. The input features are next classified using pre-trained LR machine. - - Set ``performs_projection = True`` in the constructor to enable this function. - It is assured that the :py:meth:`load_projector` was **called before** the - ``project`` function is executed. - - **Parameters:** - - ``feature`` : FrameContainer or 2D :py:class:`numpy.ndarray` - Two types of inputs are accepted. - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - Or a 2D feature array of the size (N_samples x N_features). - - **Returns:** - - ``scores`` : 1D :py:class:`numpy.ndarray` - Vector of scores. Scores for the real class are expected to be - higher, than the scores of the negative / attack class. - In this case scores are probabilities. - """ - - # 1. Convert input array to numpy array if necessary. - if isinstance( - feature, - FrameContainer): # if FrameContainer convert to 2D numpy array - - features_array = self.convert_frame_cont_to_array(feature) - - else: - - features_array = feature - - features_array_norm, _, _ = self.mean_std_normalize( - features_array, self.features_mean, self.features_std) - - scores = self.lr_machine.predict_proba(features_array_norm)[:, 0] - - return scores - - #========================================================================== - def score(self, toscore): - """ - Returns a probability of a sample being a real class. - - **Parameters:** - - ``toscore`` : 1D :py:class:`numpy.ndarray` - Vector with scores for each frame/sample defining the probability - of the frame being a sample of the real class. - - **Returns:** - - ``score`` : [:py:class:`float`] - If ``frame_level_scores_flag = False`` a single score is returned. - One score per video. This score is placed into a list, because - the ``score`` must be an iterable. - Score is a probability of a sample being a real class. - If ``frame_level_scores_flag = True`` a list of scores is returned. - One score per frame/sample. - """ - - if self.frame_level_scores_flag: - - score = list(toscore) - - else: - - score = [np.mean(toscore)] # compute a single score per video - - return score diff --git a/bob/pad/face/algorithm/VideoSvmPadAlgorithm.py b/bob/pad/face/algorithm/VideoSvmPadAlgorithm.py deleted file mode 100644 index ac5a09c78a6ccd68cf3579bf8e2ca56b5f7ed4c6..0000000000000000000000000000000000000000 --- a/bob/pad/face/algorithm/VideoSvmPadAlgorithm.py +++ /dev/null @@ -1,962 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- -""" -Created on Wed May 17 09:43:09 2017 - -@author: Olegs Nikisins -""" - -# ============================================================================== -# Import what is needed here: - -from bob.pad.base.algorithm import Algorithm -from bob.bio.video.utils import FrameContainer - -import itertools as it - -import numpy as np - -import bob.learn.libsvm - -import bob.io.base - -import os - -# ============================================================================== -# Main body : - - -class VideoSvmPadAlgorithm(Algorithm): - """ - This class is designed to train SVM given features (either numpy arrays or Frame Containers) - from real and attack classes. The trained SVM is then used to classify the - testing data as either real or attack. The SVM is trained in two stages. - First, the best parameters for SVM are estimated using train and - cross-validation subsets. The size of the subsets used in hyper-parameter - tuning is defined by ``n_samples`` parameter of this class. Once best - parameters are determined, the SVM machine is trained using complete training - set. - - **Parameters:** - - ``machine_type`` : :py:class:`str` - A type of the SVM machine. Please check ``bob.learn.libsvm`` for - more details. Default: 'C_SVC'. - - ``kernel_type`` : :py:class:`str` - A type of kerenel for the SVM machine. Please check ``bob.learn.libsvm`` - for more details. Default: 'RBF'. - - ``n_samples`` : :py:class:`int` - Number of uniformly selected feature vectors per class defining the - sizes of sub-sets used in the hyper-parameter grid search. - - ``trainer_grid_search_params`` : :py:class:`dict` - Dictionary containing the hyper-parameters of the SVM to be tested - in the grid-search. - Default: {'cost': [2**p for p in range(-5, 16, 2)], 'gamma': [2**p for p in range(-15, 4, 2)]}. - - ``mean_std_norm_flag`` : :py:class:`bool` - Perform mean-std normalization of data if set to True. Default: False. - - ``frame_level_scores_flag`` : :py:class:`bool` - Return scores for each frame individually if True. Otherwise, return a - single score per video. Should be used only when features are in Frame Containers. Default: False. - - ``save_debug_data_flag`` : :py:class:`bool` - Save the data, which might be usefull for debugging if ``True``. - Default: ``True``. - - ``reduced_train_data_flag`` : :py:class:`bool` - Reduce the amount of final training samples if set to ``True``. - Default: ``False``. - - ``n_train_samples`` : :py:class:`int` - Number of uniformly selected feature vectors per class defining the - sizes of sub-sets used in the final traing of the SVM. - Default: 50000. - """ - - def __init__( - self, - machine_type='C_SVC', - kernel_type='RBF', - n_samples=10000, - trainer_grid_search_params={ - 'cost': [2**p for p in range(-5, 16, 2)], - 'gamma': [2**p for p in range(-15, 4, 2)] - }, - mean_std_norm_flag=False, - frame_level_scores_flag=False, - save_debug_data_flag=True, - reduced_train_data_flag=False, - n_train_samples=50000): - - Algorithm.__init__( - self, - machine_type=machine_type, - kernel_type=kernel_type, - n_samples=n_samples, - trainer_grid_search_params=trainer_grid_search_params, - mean_std_norm_flag=mean_std_norm_flag, - frame_level_scores_flag=frame_level_scores_flag, - save_debug_data_flag=save_debug_data_flag, - reduced_train_data_flag=reduced_train_data_flag, - n_train_samples=n_train_samples, - performs_projection=True, - requires_projector_training=True) - - self.machine_type = machine_type - self.kernel_type = kernel_type - self.n_samples = n_samples - self.trainer_grid_search_params = trainer_grid_search_params - self.mean_std_norm_flag = mean_std_norm_flag - self.frame_level_scores_flag = frame_level_scores_flag - self.save_debug_data_flag = save_debug_data_flag - self.reduced_train_data_flag = reduced_train_data_flag - self.n_train_samples = n_train_samples - self.machine = None - - # ========================================================================== - def convert_frame_cont_to_array(self, frame_container): - """ - This function converts a single Frame Container into an array of features. - The rows are samples, the columns are features. - - **Parameters:** - - ``frame_container`` : object - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames. - The rows are samples, the columns are features. - """ - - feature_vectors = [] - - frame_dictionary = {} - - for frame in frame_container: - frame_dictionary[frame[0]] = frame[1] - - for idx, _ in enumerate(frame_container): - # Frames are stored in a mixed order, therefore we get them using incrementing frame index: - feature_vectors.append(frame_dictionary[str(idx)]) - - features_array = np.vstack(feature_vectors) - - return features_array - - # ========================================================================== - def convert_and_prepare_features(self, features): - """ - This function converts a list or a frame container of features into a 2D array of features. - If the input is a list of frame containers, features from different frame containers (individuals) - are concatenated into the same list. This list is then converted to an array. The rows are samples, - the columns are features. - - **Parameters:** - - ``features`` : [2D :py:class:`numpy.ndarray`] or [FrameContainer] - A list or 2D feature arrays or a list of Frame Containers, see ``bob.bio.video.utils.FrameContainer``. - Each frame Container contains feature vectors for the particular individual/person. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all samples and frames. - """ - - if isinstance( - features[0], - FrameContainer): # if FrameContainer convert to 2D numpy array - return self.convert_list_of_frame_cont_to_array(features) - else: - return np.vstack(features) - - # ========================================================================== - def convert_list_of_frame_cont_to_array(self, frame_containers): - """ - This function converts a list of Frame containers into an array of features. - Features from different frame containers (individuals) are concatenated into the - same list. This list is then converted to an array. The rows are samples, - the columns are features. - - **Parameters:** - - ``frame_containers`` : [FrameContainer] - A list of Frame Containers, , see ``bob.bio.video.utils.FrameContainer``. - Each frame Container contains feature vectors for the particular individual/person. - - **Returns:** - - ``features_array`` : 2D :py:class:`numpy.ndarray` - An array containing features for all frames of all individuals. - """ - - feature_vectors = [] - - for frame_container in frame_containers: - video_features_array = self.convert_frame_cont_to_array( - frame_container) - - feature_vectors.append(video_features_array) - - features_array = np.vstack(feature_vectors) - - return features_array - - # ========================================================================== - def combinations(self, input_dict): - """ - Obtain all possible key-value combinations in the input dictionary - containing list values. - - **Parameters:** - - ``input_dict`` : :py:class:`dict` - Input dictionary with list values. - - **Returns:** - - ``combinations`` : [:py:class:`dict`] - A list of dictionaries containing the combinations. - """ - - varNames = sorted(input_dict) - - combinations = [ - dict(zip(varNames, prod)) - for prod in it.product(*(input_dict[varName] - for varName in varNames)) - ] - - return combinations - - # ========================================================================== - def select_uniform_data_subset(self, features, n_samples): - """ - Uniformly select N samples/feature vectors from the input array of samples. - The rows in the input array are samples. The columns are features. - - **Parameters:** - - ``features`` : 2D :py:class:`numpy.ndarray` - Input array with feature vectors. The rows are samples, columns are features. - - ``n_samples`` : :py:class:`int` - The number of samples to be selected uniformly from the input array of features. - - **Returns:** - - ``features_subset`` : 2D :py:class:`numpy.ndarray` - Selected subset of features. - """ - - if features.shape[0] <= n_samples: - - features_subset = features - - else: - - uniform_step = np.int(features.shape[0] / n_samples) - - features_subset = features[0:np.int(uniform_step * n_samples): - uniform_step, :] - - return features_subset - - # ========================================================================== - def select_quasi_uniform_data_subset(self, features, n_samples): - """ - Select quasi uniformly N samples/feature vectors from the input array of samples. - The rows in the input array are samples. The columns are features. - Use this function if n_samples is close to the number of samples. - - **Parameters:** - - ``features`` : 2D :py:class:`numpy.ndarray` - Input array with feature vectors. The rows are samples, columns are features. - - ``n_samples`` : :py:class:`int` - The number of samples to be selected uniformly from the input array of features. - - **Returns:** - - ``features_subset`` : 2D :py:class:`numpy.ndarray` - Selected subset of features. - """ - - if features.shape[0] <= n_samples: - - features_subset = features - - else: - - uniform_step = (1.0 * features.shape[0]) / n_samples - - element_num_list = range(0, n_samples) - - idx = [np.int(uniform_step * item) for item in element_num_list] - - features_subset = features[idx, :] - - return features_subset - - # ========================================================================== - def split_data_to_train_cv(self, features): - """ - This function is designed to split the input array of features into two - subset namely train and cross-validation. These subsets can be used to tune the - hyper-parameters of the SVM. The splitting is 50/50, the first half of the - samples in the input are selected to be train set, and the second half of - samples is cross-validation. - - **Parameters:** - - ``features`` : 2D :py:class:`numpy.ndarray` - Input array with feature vectors. The rows are samples, columns are features. - - **Returns:** - - ``features_train`` : 2D :py:class:`numpy.ndarray` - Selected subset of train features. - - ``features_cv`` : 2D :py:class:`numpy.ndarray` - Selected subset of cross-validation features. - """ - - half_samples_num = np.int(features.shape[0] / 2) - - features_train = features[0:half_samples_num, :] - features_cv = features[half_samples_num:2 * half_samples_num + 1, :] - - return features_train, features_cv - - # ========================================================================== - def prepare_data_for_hyper_param_grid_search(self, training_features, - n_samples): - """ - This function converts a list of all training features returned by ``read_features`` - method of the extractor to the subsampled train and cross-validation arrays for both - real and attack classes. - - **Parameters:** - - ``training_features`` : [[FrameContainer], [FrameContainer]] - A list containing two elements: [0] - a list of Frame Containers with - feature vectors for the real class; [1] - a list of Frame Containers with - feature vectors for the attack class. - - ``n_samples`` : :py:class:`int` - Number of uniformly selected feature vectors per class. - - **Returns:** - - ``real_train`` : 2D :py:class:`numpy.ndarray` - Selected subset of train features for the real class. - The number of samples in this set is n_samples/2, which is defined - by split_data_to_train_cv method of this class. - - ``real_cv`` : 2D :py:class:`numpy.ndarray` - Selected subset of cross-validation features for the real class. - The number of samples in this set is n_samples/2, which is defined - by split_data_to_train_cv method of this class. - - ``attack_train`` : 2D :py:class:`numpy.ndarray` - Selected subset of train features for the attack class. - The number of samples in this set is n_samples/2, which is defined - by split_data_to_train_cv method of this class. - - ``attack_cv`` : 2D :py:class:`numpy.ndarray` - Selected subset of cross-validation features for the attack class. - The number of samples in this set is n_samples/2, which is defined - by split_data_to_train_cv method of this class. - """ - - # training_features[0] - training features for the REAL class. - real = self.convert_and_prepare_features( - training_features[0]) # output is array - # training_features[1] - training features for the ATTACK class. - attack = self.convert_and_prepare_features( - training_features[1]) # output is array - - # uniformly select subsets of features: - real_subset = self.select_uniform_data_subset(real, n_samples) - attack_subset = self.select_uniform_data_subset(attack, n_samples) - - # split the data into train and cross-validation: - real_train, real_cv = self.split_data_to_train_cv(real_subset) - attack_train, attack_cv = self.split_data_to_train_cv(attack_subset) - - return real_train, real_cv, attack_train, attack_cv - - # ========================================================================== - def comp_prediction_precision(self, machine, real, attack): - """ - This function computes the precision of the predictions as a ratio - of correctly classified samples to the total number of samples. - - **Parameters:** - - ``machine`` : object - A pre-trained SVM machine. - - ``real`` : 2D :py:class:`numpy.ndarray` - Array of features representing the real class. - - ``attack`` : 2D :py:class:`numpy.ndarray` - Array of features representing the attack class. - - **Returns:** - - ``precision`` : :py:class:`float` - The precision of the predictions. - """ - - labels_real = machine.predict_class(real) - - labels_attack = machine.predict_class(attack) - - samples_num = len(labels_real) + len(labels_attack) - - precision = (np.sum(labels_real == 1) + np.sum(labels_attack == -1) - ).astype(np.float) / samples_num - - return precision - - # ========================================================================== - def mean_std_normalize(self, - features, - features_mean=None, - features_std=None): - """ - The features in the input 2D array are mean-std normalized. - The rows are samples, the columns are features. If ``features_mean`` - and ``features_std`` are provided, then these vectors will be used for - normalization. Otherwise, the mean and std of the features is - computed on the fly. - - **Parameters:** - - ``features`` : 2D :py:class:`numpy.ndarray` - Array of features to be normalized. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. Default: None. - - ``features_std`` : 2D :py:class:`numpy.ndarray` - Standart deviation of the features. Default: None. - - **Returns:** - - ``features_norm`` : 2D :py:class:`numpy.ndarray` - Normalized array of features. - - ``features_mean`` : 1D :py:class:`numpy.ndarray` - Mean of the features. - - ``features_std`` : 2D :py:class:`numpy.ndarray` - Standart deviation of the features. - """ - - features = np.copy(features) - - # Compute mean and std if not given: - if features_mean is None: - features_mean = np.mean(features, axis=0) - - features_std = np.std(features, axis=0) - - row_norm_list = [] - - for row in features: # row is a sample - - row_norm = (row - features_mean) / features_std - - row_norm_list.append(row_norm) - - features_norm = np.vstack(row_norm_list) - - return features_norm, features_mean, features_std - - # ========================================================================== - def norm_train_cv_data(self, - real_train, - real_cv, - attack_train, - attack_cv, - one_class_flag=False): - """ - Mean-std normalization of train and cross-validation data arrays. - - **Parameters:** - - ``real_train`` : 2D :py:class:`numpy.ndarray` - Subset of train features for the real class. - - ``real_cv`` : 2D :py:class:`numpy.ndarray` - Subset of cross-validation features for the real class. - - ``attack_train`` : 2D :py:class:`numpy.ndarray` - Subset of train features for the attack class. - - ``attack_cv`` : 2D :py:class:`numpy.ndarray` - Subset of cross-validation features for the attack class. - - ``one_class_flag`` : :py:class:`bool` - If set to ``True``, only positive/real samples will be used to - compute the mean and std normalization vectors. Set to ``True`` if - using one-class SVM. Default: False. - - **Returns:** - - ``real_train_norm`` : 2D :py:class:`numpy.ndarray` - Normalized subset of train features for the real class. - - ``real_cv_norm`` : 2D :py:class:`numpy.ndarray` - Normalized subset of cross-validation features for the real class. - - ``attack_train_norm`` : 2D :py:class:`numpy.ndarray` - Normalized subset of train features for the attack class. - - ``attack_cv_norm`` : 2D :py:class:`numpy.ndarray` - Normalized subset of cross-validation features for the attack class. - """ - if not (one_class_flag): - - features_train = np.vstack([real_train, attack_train]) - - features_train_norm, features_mean, features_std = self.mean_std_normalize( - features_train) - - real_train_norm = features_train_norm[0:real_train.shape[0], :] - - attack_train_norm = features_train_norm[real_train.shape[0]:, :] - - real_cv_norm, _, _ = self.mean_std_normalize( - real_cv, features_mean, features_std) - - attack_cv_norm, _, _ = self.mean_std_normalize( - attack_cv, features_mean, features_std) - - else: # one-class SVM case - - # only real class used for training in one class SVM: - real_train_norm, features_mean, features_std = self.mean_std_normalize( - real_train) - - attack_train_norm, _, _ = self.mean_std_normalize( - attack_train, features_mean, features_std) - - real_cv_norm, _, _ = self.mean_std_normalize( - real_cv, features_mean, features_std) - - attack_cv_norm, _, _ = self.mean_std_normalize( - attack_cv, features_mean, features_std) - - return real_train_norm, real_cv_norm, attack_train_norm, attack_cv_norm - - # ========================================================================== - def train_svm( - self, - training_features, - n_samples=10000, - machine_type='C_SVC', - kernel_type='RBF', - trainer_grid_search_params={ - 'cost': [2**p for p in range(-5, 16, 2)], - 'gamma': [2**p for p in range(-15, 4, 2)] - }, - mean_std_norm_flag=False, - projector_file="", - save_debug_data_flag=True, - reduced_train_data_flag=False, - n_train_samples=50000): - """ - First, this function tunes the hyper-parameters of the SVM classifier using - grid search on the sub-sets of training data. Train and cross-validation - subsets for both classes are formed from the available input training_features. - - Once successfull parameters are determined the SVM is trained on the - whole training data set. The resulting machine is returned by the function. - - **Parameters:** - - ``training_features`` : [[FrameContainer], [FrameContainer]] - A list containing two elements: [0] - a list of Frame Containers with - feature vectors for the real class; [1] - a list of Frame Containers with - feature vectors for the attack class. - - ``n_samples`` : :py:class:`int` - Number of uniformly selected feature vectors per class defining the - sizes of sub-sets used in the hyper-parameter grid search. - - ``machine_type`` : :py:class:`str` - A type of the SVM machine. Please check ``bob.learn.libsvm`` for - more details. - - ``kernel_type`` : :py:class:`str` - A type of kerenel for the SVM machine. Please check ``bob.learn.libsvm`` - for more details. - - ``trainer_grid_search_params`` : :py:class:`dict` - Dictionary containing the hyper-parameters of the SVM to be tested - in the grid-search. - - ``mean_std_norm_flag`` : :py:class:`bool` - Perform mean-std normalization of data if set to True. Default: False. - - ``projector_file`` : :py:class:`str` - The name of the file to save the trained projector to. Only the path - of this file is used in this function. The file debug_data.hdf5 will - be save in this path. This file contains information, which might be - usefull for debugging. - - ``save_debug_data_flag`` : :py:class:`bool` - Save the data, which might be usefull for debugging if ``True``. - Default: ``True``. - - ``reduced_train_data_flag`` : :py:class:`bool` - Reduce the amount of final training samples if set to ``True``. - Default: ``False``. - - ``n_train_samples`` : :py:class:`int` - Number of uniformly selected feature vectors per class defining the - sizes of sub-sets used in the final traing of the SVM. - Default: 50000. - - **Returns:** - - ``machine`` : object - A trained SVM machine. - """ - - one_class_flag = ( - machine_type == 'ONE_CLASS') # True if one-class SVM is used - - # get the data for the hyper-parameter grid-search: - real_train, real_cv, attack_train, attack_cv = self.prepare_data_for_hyper_param_grid_search( - training_features, n_samples) - - if mean_std_norm_flag: - # normalize the data: - real_train, real_cv, attack_train, attack_cv = self.norm_train_cv_data( - real_train, real_cv, attack_train, attack_cv, one_class_flag) - - precisions_cv = [ - ] # for saving the precision on the cross-validation set - - precisions_train = [] - - trainer_grid_search_params_list = self.combinations( - trainer_grid_search_params - ) # list containing all combinations of params - - for trainer_grid_search_param in trainer_grid_search_params_list: - - # initialize the SVM trainer: - trainer = bob.learn.libsvm.Trainer( - machine_type=machine_type, - kernel_type=kernel_type, - probability=True) - - for key in trainer_grid_search_param.keys(): - setattr(trainer, key, trainer_grid_search_param[ - key]) # set the params of trainer - - if not (one_class_flag): # two-class SVM case - - data = [ - np.copy(real_train), - np.copy(attack_train) - ] # data used for training the machine in the grid-search - - else: # one class SVM case - - data = [np.copy(real_train) - ] # only real class is used for training - - machine = trainer.train(data) # train the machine - - precision_cv = self.comp_prediction_precision( - machine, np.copy(real_cv), np.copy(attack_cv)) - - precision_train = self.comp_prediction_precision( - machine, np.copy(real_train), np.copy(attack_train)) - - precisions_cv.append(precision_cv) - - precisions_train.append(precision_train) - - del data - del machine - del trainer - - selected_params = trainer_grid_search_params_list[np.argmax( - precisions_cv)] # best SVM parameters according to CV set - - trainer = bob.learn.libsvm.Trainer( - machine_type=machine_type, - kernel_type=kernel_type, - probability=True) - - for key in selected_params.keys(): - setattr(trainer, key, - selected_params[key]) # set the params of trainer - - # Save the data, which is usefull for debugging. - if save_debug_data_flag: - - debug_file = os.path.join( - os.path.split(projector_file)[0], "debug_data.hdf5") - debug_dict = {} - debug_dict['precisions_train'] = precisions_train - debug_dict['precisions_cv'] = precisions_cv - - for key in selected_params.keys(): - debug_dict[key] = selected_params[key] - - f = bob.io.base.HDF5File( - debug_file, 'w') # open hdf5 file to save the debug data - for key in debug_dict.keys(): - f.set(key, debug_dict[key]) - del f - - # training_features[0] - training features for the REAL class. - real = self.convert_and_prepare_features( - training_features[0]) # output is array - # training_features[1] - training features for the ATTACK class. - attack = self.convert_and_prepare_features( - training_features[1]) # output is array - - if mean_std_norm_flag: - # Normalize the data: - if not (one_class_flag): # two-class SVM case - - features = np.vstack([real, attack]) - features_norm, features_mean, features_std = self.mean_std_normalize( - features) - real = features_norm[0:real.shape[ - 0], :] # The array is now normalized - attack = features_norm[real.shape[ - 0]:, :] # The array is now normalized - - else: # one-class SVM case - - real, features_mean, features_std = self.mean_std_normalize( - real) # use only real class to compute normalizers - attack = self.mean_std_normalize(attack, features_mean, - features_std) - # ``real`` and ``attack`` arrays are now normalizaed - - if reduced_train_data_flag: - # uniformly select subsets of features: - real = self.select_quasi_uniform_data_subset(real, n_train_samples) - attack = self.select_quasi_uniform_data_subset( - attack, n_train_samples) - - if not (one_class_flag): # two-class SVM case - - data = [np.copy(real), np.copy(attack)] # data for final training - - else: # one-class SVM case - - data = [np.copy(real)] # only real class used for training - - machine = trainer.train(data) # train the machine - - if mean_std_norm_flag: - machine.input_subtract = features_mean # subtract the mean of train data - machine.input_divide = features_std # divide by std of train data - - del data - - return machine - - # ========================================================================== - def train_projector(self, training_features, projector_file): - """ - Train SVM feature projector and save the trained SVM to a given file. - The ``requires_projector_training = True`` flag must be set to True to - enable this function. - - **Parameters:** - - ``training_features`` : [[FrameContainer], [FrameContainer]] - A list containing two elements: [0] - a list of Frame Containers with - feature vectors for the real class; [1] - a list of Frame Containers with - feature vectors for the attack class. - - ``projector_file`` : :py:class:`str` - The file to save the trained projector to. - This file should be readable with the :py:meth:`load_projector` function. - """ - - machine = self.train_svm( - training_features=training_features, - n_samples=self.n_samples, - machine_type=self.machine_type, - kernel_type=self.kernel_type, - trainer_grid_search_params=self.trainer_grid_search_params, - mean_std_norm_flag=self.mean_std_norm_flag, - projector_file=projector_file, - save_debug_data_flag=self.save_debug_data_flag, - reduced_train_data_flag=self.reduced_train_data_flag, - n_train_samples=self.n_train_samples) - - f = bob.io.base.HDF5File(projector_file, - 'w') # open hdf5 file to save to - - machine.save(f) # save the machine and normalization parameters - - del f - - # ========================================================================== - def load_projector(self, projector_file): - """ - Load the pretrained projector/SVM from file to perform a feature projection. - This function usually is useful in combination with the - :py:meth:`train_projector` function. - - Please register `performs_projection = True` in the constructor to - enable this function. - - **Parameters:** - - ``projector_file`` : :py:class:`str` - The file to read the projector from. - """ - - f = bob.io.base.HDF5File(projector_file, 'a') - - self.machine = bob.learn.libsvm.Machine(f) - - del f - - # ========================================================================== - def project(self, feature): - """ - This function computes class probabilities for the input feature using pretrained SVM. - The feature in this case is a Frame Container with features for each frame. - The probabilities will be computed and returned for each frame. - - Set ``performs_projection = True`` in the constructor to enable this function. - It is assured that the :py:meth:`load_projector` was called before the - ``project`` function is executed. - - **Parameters:** - - ``feature`` : object - A Frame Container conteining the features of an individual, - see ``bob.bio.video.utils.FrameContainer``. - - **Returns:** - - ``probabilities`` : 1D or 2D :py:class:`numpy.ndarray` - 2D in the case of two-class SVM. - An array containing class probabilities for each frame. - First column contains probabilities for each frame being a real class. - Second column contains probabilities for each frame being an attack class. - 1D in the case of one-class SVM. - Vector with scores for each frame defining belonging to the real class. - Must be writable with the ``write_feature`` function and - readable with the ``read_feature`` function. - """ - - if isinstance( - feature, - FrameContainer): # if FrameContainer convert to 2D numpy array - - features_array = self.convert_frame_cont_to_array(feature) - - else: - - features_array = feature - - if not (self.machine_type == 'ONE_CLASS'): # two-class SVM case - - probabilities = self.machine.predict_class_and_probabilities( - features_array)[1] - - else: - - probabilities = self.machine.predict_class_and_scores( - features_array)[1] - - return probabilities - - # ========================================================================== - def score(self, toscore): - """ - Returns a probability of a sample being a real class. - - **Parameters:** - - ``toscore`` : 1D or 2D :py:class:`numpy.ndarray` - 2D in the case of two-class SVM. - An array containing class probabilities for each frame. - First column contains probabilities for each frame being a real class. - Second column contains probabilities for each frame being an attack class. - 1D in the case of one-class SVM. - Vector with scores for each frame defining belonging to the real class. - - **Returns:** - - ``score`` : :py:class:`float` or a 1D :py:class:`numpy.ndarray` - If ``frame_level_scores_flag = False`` a single score is returned. - One score per video. - Score is a probability of a sample being a real class. - If ``frame_level_scores_flag = True`` a 1D array of scores is returned. - One score per frame. - Score is a probability of a sample being a real class. - """ - - if self.frame_level_scores_flag: - - score = toscore[:, - 0] # here score is a 1D array containing scores for each frame - - else: - - score = np.mean(toscore[:, 0]) # compute a single score per sample - - return score - - # ========================================================================== - def score_for_multiple_projections(self, toscore): - """ - Returns a list of scores computed by the score method of this class. - - **Parameters:** - - ``toscore`` : 1D or 2D :py:class:`numpy.ndarray` - 2D in the case of two-class SVM. - An array containing class probabilities for each frame. - First column contains probabilities for each frame being a real class. - Second column contains probabilities for each frame being an attack class. - 1D in the case of one-class SVM. - Vector with scores for each frame defining belonging to the real class. - - **Returns:** - - ``list_of_scores`` : [:py:class:`float`] - A list containing the scores. - """ - - scores = self.score( - toscore) # returns float score or 1D array of scores - - if isinstance(scores, np.float): # if a single score - - list_of_scores = [scores] - - else: - - list_of_scores = list(scores) - - return list_of_scores diff --git a/bob/pad/face/algorithm/__init__.py b/bob/pad/face/algorithm/__init__.py deleted file mode 100644 index 75d02e109760e9194f931740826d510b5dc2e578..0000000000000000000000000000000000000000 --- a/bob/pad/face/algorithm/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -from .VideoSvmPadAlgorithm import VideoSvmPadAlgorithm -from .VideoCascadeSvmPadAlgorithm import VideoCascadeSvmPadAlgorithm -from .VideoLRPadAlgorithm import VideoLRPadAlgorithm -from .VideoGmmPadAlgorithm import VideoGmmPadAlgorithm - - -def __appropriate__(*args): - """Says object was actually declared here, and not in the import module. - Fixing sphinx warnings of not being able to find classes, when path is - shortened. - - Parameters - ---------- - *args - The objects that you want sphinx to believe that are defined here. - - Resolves `Sphinx referencing issues <https//github.com/sphinx- - doc/sphinx/issues/3048>` - """ - - for obj in args: - obj.__module__ = __name__ - - -__appropriate__( - VideoSvmPadAlgorithm, - VideoCascadeSvmPadAlgorithm, - VideoLRPadAlgorithm, - VideoGmmPadAlgorithm, -) -__all__ = [_ for _ in dir() if not _.startswith('_')] diff --git a/bob/pad/face/config/algorithm/video_cascade_svm_pad_algorithm.py b/bob/pad/face/config/algorithm/video_cascade_svm_pad_algorithm.py index 5856ef3d19c34c15d721c3e8146f490baf67775c..ac43229a0ac0e475937c4dffd36e144ef6a26540 100644 --- a/bob/pad/face/config/algorithm/video_cascade_svm_pad_algorithm.py +++ b/bob/pad/face/config/algorithm/video_cascade_svm_pad_algorithm.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from bob.pad.face.algorithm import VideoCascadeSvmPadAlgorithm +from bob.pad.base.algorithm import SVMCascadePCA #======================================================================================= # Define instances here: @@ -12,7 +12,7 @@ N = 2 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n2_gamma_02 = VideoCascadeSvmPadAlgorithm( +algorithm_n2_gamma_02 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -27,7 +27,7 @@ N = 2 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n2_gamma_01 = VideoCascadeSvmPadAlgorithm( +algorithm_n2_gamma_01 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -42,7 +42,7 @@ N = 2 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n2_gamma_005 = VideoCascadeSvmPadAlgorithm( +algorithm_n2_gamma_005 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -57,7 +57,7 @@ N = 2 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n2_gamma_001 = VideoCascadeSvmPadAlgorithm( +algorithm_n2_gamma_001 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -74,7 +74,7 @@ N = 10 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n10_gamma_01 = VideoCascadeSvmPadAlgorithm( +algorithm_n10_gamma_01 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -89,7 +89,7 @@ N = 10 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n10_gamma_005 = VideoCascadeSvmPadAlgorithm( +algorithm_n10_gamma_005 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -104,7 +104,7 @@ N = 10 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n10_gamma_001 = VideoCascadeSvmPadAlgorithm( +algorithm_n10_gamma_001 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -119,7 +119,7 @@ N = 10 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n10_gamma_0005 = VideoCascadeSvmPadAlgorithm( +algorithm_n10_gamma_0005 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -136,7 +136,7 @@ N = 20 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n20_gamma_05 = VideoCascadeSvmPadAlgorithm( +algorithm_n20_gamma_05 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -151,7 +151,7 @@ N = 20 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n20_gamma_02 = VideoCascadeSvmPadAlgorithm( +algorithm_n20_gamma_02 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -166,7 +166,7 @@ N = 20 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n20_gamma_01 = VideoCascadeSvmPadAlgorithm( +algorithm_n20_gamma_01 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -181,7 +181,7 @@ N = 20 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n20_gamma_005 = VideoCascadeSvmPadAlgorithm( +algorithm_n20_gamma_005 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -196,7 +196,7 @@ N = 20 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n20_gamma_001 = VideoCascadeSvmPadAlgorithm( +algorithm_n20_gamma_001 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -211,7 +211,7 @@ N = 20 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n20_gamma_0005 = VideoCascadeSvmPadAlgorithm( +algorithm_n20_gamma_0005 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -226,7 +226,7 @@ N = 20 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n20_gamma_0001 = VideoCascadeSvmPadAlgorithm( +algorithm_n20_gamma_0001 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -243,7 +243,7 @@ N = 2 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = False -algorithm_n2_gamma_01_video_level = VideoCascadeSvmPadAlgorithm( +algorithm_n2_gamma_01_video_level = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, @@ -262,7 +262,7 @@ N = 2 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm_n2_two_class_svm_c1_gamma_001 = VideoCascadeSvmPadAlgorithm( +algorithm_n2_two_class_svm_c1_gamma_001 = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=TRAINER_GRID_SEARCH_PARAMS, diff --git a/bob/pad/face/config/algorithm/video_gmm_pad_algorithm.py b/bob/pad/face/config/algorithm/video_gmm_pad_algorithm.py index 67787390e906a743b13d443795923c6a035fc696..3e132c9c24bae7c1724f2fac7e198b003ded63a4 100644 --- a/bob/pad/face/config/algorithm/video_gmm_pad_algorithm.py +++ b/bob/pad/face/config/algorithm/video_gmm_pad_algorithm.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from bob.pad.face.algorithm import VideoGmmPadAlgorithm +from bob.pad.base.algorithm import OneClassGMM #======================================================================================= # Define instances here: @@ -8,55 +8,55 @@ from bob.pad.face.algorithm import VideoGmmPadAlgorithm N_COMPONENTS = 2 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_2 = VideoGmmPadAlgorithm( +algorithm_gmm_2 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 3 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_3 = VideoGmmPadAlgorithm( +algorithm_gmm_3 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 4 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_4 = VideoGmmPadAlgorithm( +algorithm_gmm_4 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 5 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_5 = VideoGmmPadAlgorithm( +algorithm_gmm_5 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 6 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_6 = VideoGmmPadAlgorithm( +algorithm_gmm_6 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 7 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_7 = VideoGmmPadAlgorithm( +algorithm_gmm_7 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 8 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_8 = VideoGmmPadAlgorithm( +algorithm_gmm_8 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 9 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_9 = VideoGmmPadAlgorithm( +algorithm_gmm_9 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 10 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_10 = VideoGmmPadAlgorithm( +algorithm_gmm_10 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) #======================================================================================= @@ -65,31 +65,31 @@ algorithm_gmm_10 = VideoGmmPadAlgorithm( N_COMPONENTS = 12 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_12 = VideoGmmPadAlgorithm( +algorithm_gmm_12 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 14 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_14 = VideoGmmPadAlgorithm( +algorithm_gmm_14 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 16 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_16 = VideoGmmPadAlgorithm( +algorithm_gmm_16 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 18 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_18 = VideoGmmPadAlgorithm( +algorithm_gmm_18 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 20 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_20 = VideoGmmPadAlgorithm( +algorithm_gmm_20 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) #======================================================================================= @@ -98,37 +98,37 @@ algorithm_gmm_20 = VideoGmmPadAlgorithm( N_COMPONENTS = 25 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_25 = VideoGmmPadAlgorithm( +algorithm_gmm_25 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 30 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_30 = VideoGmmPadAlgorithm( +algorithm_gmm_30 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 35 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_35 = VideoGmmPadAlgorithm( +algorithm_gmm_35 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 40 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_40 = VideoGmmPadAlgorithm( +algorithm_gmm_40 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 45 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_45 = VideoGmmPadAlgorithm( +algorithm_gmm_45 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 50 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50 = VideoGmmPadAlgorithm( +algorithm_gmm_50 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) #======================================================================================= @@ -137,31 +137,31 @@ algorithm_gmm_50 = VideoGmmPadAlgorithm( N_COMPONENTS = 60 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_60 = VideoGmmPadAlgorithm( +algorithm_gmm_60 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 70 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_70 = VideoGmmPadAlgorithm( +algorithm_gmm_70 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 80 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_80 = VideoGmmPadAlgorithm( +algorithm_gmm_80 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 90 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_90 = VideoGmmPadAlgorithm( +algorithm_gmm_90 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) N_COMPONENTS = 100 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_100 = VideoGmmPadAlgorithm( +algorithm_gmm_100 = OneClassGMM( n_components=N_COMPONENTS, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) #======================================================================================= @@ -171,7 +171,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 0 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_0 = VideoGmmPadAlgorithm( +algorithm_gmm_50_0 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -180,7 +180,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 1 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_1 = VideoGmmPadAlgorithm( +algorithm_gmm_50_1 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -189,7 +189,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 2 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_2 = VideoGmmPadAlgorithm( +algorithm_gmm_50_2 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -198,7 +198,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 3 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_3 = VideoGmmPadAlgorithm( +algorithm_gmm_50_3 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -207,7 +207,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 4 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_4 = VideoGmmPadAlgorithm( +algorithm_gmm_50_4 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -216,7 +216,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 5 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_5 = VideoGmmPadAlgorithm( +algorithm_gmm_50_5 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -225,7 +225,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 6 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_6 = VideoGmmPadAlgorithm( +algorithm_gmm_50_6 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -234,7 +234,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 7 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_7 = VideoGmmPadAlgorithm( +algorithm_gmm_50_7 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -243,7 +243,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 8 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_8 = VideoGmmPadAlgorithm( +algorithm_gmm_50_8 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) @@ -252,7 +252,7 @@ N_COMPONENTS = 50 RANDOM_STATE = 9 FRAME_LEVEL_SCORES_FLAG = True -algorithm_gmm_50_9 = VideoGmmPadAlgorithm( +algorithm_gmm_50_9 = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) diff --git a/bob/pad/face/config/algorithm/video_svm_pad_algorithm.py b/bob/pad/face/config/algorithm/video_svm_pad_algorithm.py index 10fd1a7031360a224fc01a4bdb27f66e1ae76ddf..7d7e0f0935d9f40e4b6b5bcb3926ec0787d3ae10 100644 --- a/bob/pad/face/config/algorithm/video_svm_pad_algorithm.py +++ b/bob/pad/face/config/algorithm/video_svm_pad_algorithm.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from bob.pad.face.algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM #======================================================================================= # Define instances here: @@ -16,7 +16,7 @@ trainer_grid_search_params = { mean_std_norm_flag = True frame_level_scores_flag = False # one score per video(!) in this case -video_svm_pad_algorithm_10k_grid_mean_std = VideoSvmPadAlgorithm( +video_svm_pad_algorithm_10k_grid_mean_std = SVM( machine_type=machine_type, kernel_type=kernel_type, n_samples=n_samples, @@ -26,7 +26,7 @@ video_svm_pad_algorithm_10k_grid_mean_std = VideoSvmPadAlgorithm( frame_level_scores_flag = True # one score per frame(!) in this case -video_svm_pad_algorithm_10k_grid_mean_std_frame_level = VideoSvmPadAlgorithm( +video_svm_pad_algorithm_10k_grid_mean_std_frame_level = SVM( machine_type=machine_type, kernel_type=kernel_type, n_samples=n_samples, @@ -39,7 +39,7 @@ trainer_grid_search_params = { 'gamma': [0] } # set the default LibSVM parameters -video_svm_pad_algorithm_default_svm_param_mean_std_frame_level = VideoSvmPadAlgorithm( +video_svm_pad_algorithm_default_svm_param_mean_std_frame_level = SVM( machine_type=machine_type, kernel_type=kernel_type, n_samples=n_samples, diff --git a/bob/pad/face/config/frame_diff_svm.py b/bob/pad/face/config/frame_diff_svm.py index 4fa07081778046de489b21ae26c206d4a249e3ee..6d8ad4f259ca6f275cd75d6d73c88279bd839a04 100644 --- a/bob/pad/face/config/frame_diff_svm.py +++ b/bob/pad/face/config/frame_diff_svm.py @@ -58,7 +58,7 @@ The features are introduced in the following paper: [AM11]_. #======================================================================================= # define algorithm: -from ..algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM MACHINE_TYPE = 'C_SVC' KERNEL_TYPE = 'RBF' @@ -70,7 +70,7 @@ TRAINER_GRID_SEARCH_PARAMS = { MEAN_STD_NORM_FLAG = True # enable mean-std normalization FRAME_LEVEL_SCORES_FLAG = True # one score per frame(!) in this case -algorithm = VideoSvmPadAlgorithm( +algorithm = SVM( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, n_samples=N_SAMPLES, diff --git a/bob/pad/face/config/frame_diff_svm_aggregated_db.py b/bob/pad/face/config/frame_diff_svm_aggregated_db.py index 1bd47a16e872594d175cb02910a06306caff0f6f..30834c4fe6d293a65edc63a4628ef813042850ca 100644 --- a/bob/pad/face/config/frame_diff_svm_aggregated_db.py +++ b/bob/pad/face/config/frame_diff_svm_aggregated_db.py @@ -60,7 +60,7 @@ The features are introduced in the following paper: [AM11]_. #======================================================================================= # define algorithm: -from ..algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM MACHINE_TYPE = 'C_SVC' KERNEL_TYPE = 'RBF' @@ -75,7 +75,7 @@ SAVE_DEBUG_DATA_FLAG = True # save the data, which might be useful for debuggin REDUCED_TRAIN_DATA_FLAG = True # reduce the amount of training data in the final training stage N_TRAIN_SAMPLES = 50000 # number of training samples per class in the final SVM training stage -algorithm = VideoSvmPadAlgorithm( +algorithm = SVM( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, n_samples=N_SAMPLES, diff --git a/bob/pad/face/config/lbp_svm.py b/bob/pad/face/config/lbp_svm.py index 94866288340ec69d0ef3566a7143a27853b7c45c..0b7ff33efa23b097d369d0355ee315d953aa934b 100644 --- a/bob/pad/face/config/lbp_svm.py +++ b/bob/pad/face/config/lbp_svm.py @@ -79,7 +79,7 @@ The parameters are similar to the ones introduced in [CAM12]_. #======================================================================================= # define algorithm: -from ..algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM MACHINE_TYPE = 'C_SVC' KERNEL_TYPE = 'RBF' @@ -91,7 +91,7 @@ TRAINER_GRID_SEARCH_PARAMS = { MEAN_STD_NORM_FLAG = True # enable mean-std normalization FRAME_LEVEL_SCORES_FLAG = True # one score per frame(!) in this case -algorithm = VideoSvmPadAlgorithm( +algorithm = SVM( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, n_samples=N_SAMPLES, diff --git a/bob/pad/face/config/lbp_svm_aggregated_db.py b/bob/pad/face/config/lbp_svm_aggregated_db.py index e2daaa2f5f9728ac52e807b45a2a89887d4e5507..d8698a51dc9fe392ca7bdd835b40905f9f1cc3e2 100644 --- a/bob/pad/face/config/lbp_svm_aggregated_db.py +++ b/bob/pad/face/config/lbp_svm_aggregated_db.py @@ -80,7 +80,7 @@ The parameters are similar to the ones introduced in [CAM12]_. #======================================================================================= # define algorithm: -from ..algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM MACHINE_TYPE = 'C_SVC' KERNEL_TYPE = 'RBF' @@ -95,7 +95,7 @@ SAVE_DEBUG_DATA_FLAG = True # save the data, which might be useful for debuggin REDUCED_TRAIN_DATA_FLAG = True # reduce the amount of training data in the final training stage N_TRAIN_SAMPLES = 50000 # number of training samples per class in the final SVM training stage -algorithm = VideoSvmPadAlgorithm( +algorithm = SVM( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, n_samples=N_SAMPLES, diff --git a/bob/pad/face/config/qm_lr.py b/bob/pad/face/config/qm_lr.py index f971fdee05e374965bac4305d6e488e4b18e4726..92ae19858fc467d263a4c43493cd48329e07e0f9 100644 --- a/bob/pad/face/config/qm_lr.py +++ b/bob/pad/face/config/qm_lr.py @@ -69,12 +69,12 @@ The features to be computed are introduced in the following papers: [WHJ15]_ and #======================================================================================= # define algorithm: -from ..algorithm import VideoLRPadAlgorithm +from bob.pad.base.algorithm import LogRegr C = 1. # The regularization parameter for the LR classifier FRAME_LEVEL_SCORES_FLAG = True # Return one score per frame -algorithm = VideoLRPadAlgorithm( +algorithm = LogRegr( C=C, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) """ The Logistic Regression is used to classify the data into *real* and *attack* classes. diff --git a/bob/pad/face/config/qm_one_class_gmm.py b/bob/pad/face/config/qm_one_class_gmm.py index c74e7b7f2af1d2cf9963bc1ca4261c67894a5fe0..16a44c01d6584566a72b99afd73a806a2cbe019a 100644 --- a/bob/pad/face/config/qm_one_class_gmm.py +++ b/bob/pad/face/config/qm_one_class_gmm.py @@ -69,13 +69,13 @@ The features to be computed are introduced in the following papers: [WHJ15]_ and #======================================================================================= # define algorithm: -from ..algorithm import VideoGmmPadAlgorithm +from bob.pad.base.algorithm import OneClassGMM N_COMPONENTS = 50 RANDOM_STATE = 3 FRAME_LEVEL_SCORES_FLAG = True -algorithm = VideoGmmPadAlgorithm( +algorithm = OneClassGMM( n_components=N_COMPONENTS, random_state=RANDOM_STATE, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) diff --git a/bob/pad/face/config/qm_one_class_svm_aggregated_db.py b/bob/pad/face/config/qm_one_class_svm_aggregated_db.py index 07522368e4a3f8c3c95fc650c6ae92b69f838f1c..efebc10857c0bbb32bada822b84be4783804211a 100644 --- a/bob/pad/face/config/qm_one_class_svm_aggregated_db.py +++ b/bob/pad/face/config/qm_one_class_svm_aggregated_db.py @@ -71,7 +71,7 @@ The features to be computed are introduced in the following papers: [WHJ15]_ and #======================================================================================= # define algorithm: -from ..algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM MACHINE_TYPE = 'ONE_CLASS' KERNEL_TYPE = 'RBF' @@ -86,7 +86,7 @@ SAVE_DEBUG_DATA_FLAG = True # save the data, which might be useful for debuggin REDUCED_TRAIN_DATA_FLAG = False # DO NOT reduce the amount of training data in the final training stage N_TRAIN_SAMPLES = 50000 # number of training samples per class in the final SVM training stage (NOT considered, because REDUCED_TRAIN_DATA_FLAG = False) -algorithm = VideoSvmPadAlgorithm( +algorithm = SVM( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, n_samples=N_SAMPLES, diff --git a/bob/pad/face/config/qm_one_class_svm_cascade_aggregated_db.py b/bob/pad/face/config/qm_one_class_svm_cascade_aggregated_db.py index f98d25cdd497b73d2938343933d5540cb404f8a9..6b63e29df4a5adae7707ba4cdfedf7c0dec0ca10 100644 --- a/bob/pad/face/config/qm_one_class_svm_cascade_aggregated_db.py +++ b/bob/pad/face/config/qm_one_class_svm_cascade_aggregated_db.py @@ -71,7 +71,7 @@ The features to be computed are introduced in the following papers: [WHJ15]_ and #======================================================================================= # define algorithm: -from ..algorithm import VideoCascadeSvmPadAlgorithm +from bob.pad.base.algorithm import SVMCascadePCA MACHINE_TYPE = 'ONE_CLASS' KERNEL_TYPE = 'RBF' @@ -80,7 +80,7 @@ N = 2 POS_SCORES_SLOPE = 0.01 FRAME_LEVEL_SCORES_FLAG = True -algorithm = VideoCascadeSvmPadAlgorithm( +algorithm = SVMCascadePCA( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, svm_kwargs=SVM_KWARGS, diff --git a/bob/pad/face/config/qm_svm.py b/bob/pad/face/config/qm_svm.py index 003242142d6d92d85472e722fe89a11b4a9b3a43..609ab7def5380090b5678d889c136460bfc512df 100644 --- a/bob/pad/face/config/qm_svm.py +++ b/bob/pad/face/config/qm_svm.py @@ -69,7 +69,7 @@ The features to be computed are introduced in the following papers: [WHJ15]_ and #======================================================================================= # define algorithm: -from ..algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM MACHINE_TYPE = 'C_SVC' KERNEL_TYPE = 'RBF' @@ -81,7 +81,7 @@ TRAINER_GRID_SEARCH_PARAMS = { MEAN_STD_NORM_FLAG = True # enable mean-std normalization FRAME_LEVEL_SCORES_FLAG = True # one score per frame(!) in this case -algorithm = VideoSvmPadAlgorithm( +algorithm = SVM( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, n_samples=N_SAMPLES, diff --git a/bob/pad/face/config/qm_svm_aggregated_db.py b/bob/pad/face/config/qm_svm_aggregated_db.py index e260cdc4156fd5793a34c0a8b71b3106c86bb59b..01199315fef2bfd97d80b70e40a26ab004de2042 100644 --- a/bob/pad/face/config/qm_svm_aggregated_db.py +++ b/bob/pad/face/config/qm_svm_aggregated_db.py @@ -71,7 +71,7 @@ The features to be computed are introduced in the following papers: [WHJ15]_ and #======================================================================================= # define algorithm: -from ..algorithm import VideoSvmPadAlgorithm +from bob.pad.base.algorithm import SVM MACHINE_TYPE = 'C_SVC' KERNEL_TYPE = 'RBF' @@ -86,7 +86,7 @@ SAVE_DEBUG_DATA_FLAG = True # save the data, which might be useful for debuggin REDUCED_TRAIN_DATA_FLAG = True # reduce the amount of training data in the final training stage N_TRAIN_SAMPLES = 50000 # number of training samples per class in the final SVM training stage -algorithm = VideoSvmPadAlgorithm( +algorithm = SVM( machine_type=MACHINE_TYPE, kernel_type=KERNEL_TYPE, n_samples=N_SAMPLES, diff --git a/bob/pad/face/test/test.py b/bob/pad/face/test/test.py index d28cf49c0348755010d031d180008e1a5c474da1..af04373b138828931ac8faecd2c4324f31567a94 100644 --- a/bob/pad/face/test/test.py +++ b/bob/pad/face/test/test.py @@ -30,10 +30,6 @@ from ..extractor import VideoLBPHistogram from ..extractor import VideoQualityMeasure -from ..algorithm import VideoSvmPadAlgorithm - -from ..algorithm import VideoGmmPadAlgorithm - from ..utils import face_detection_utils import random @@ -426,129 +422,3 @@ def convert_array_to_list_of_frame_cont(data): frame_container) # add current frame to FrameContainer return frame_container_list - - -#============================================================================== -def test_video_svm_pad_algorithm(): - """ - Test the VideoSvmPadAlgorithm algorithm. - """ - - random.seed(7) - - N = 20000 - mu = 1 - sigma = 1 - real_array = np.transpose( - np.vstack([[random.gauss(mu, sigma) for _ in range(N)], - [random.gauss(mu, sigma) for _ in range(N)]])) - - mu = 5 - sigma = 1 - attack_array = np.transpose( - np.vstack([[random.gauss(mu, sigma) for _ in range(N)], - [random.gauss(mu, sigma) for _ in range(N)]])) - - real = convert_array_to_list_of_frame_cont(real_array) - attack = convert_array_to_list_of_frame_cont(attack_array) - - training_features = [real, attack] - - MACHINE_TYPE = 'C_SVC' - KERNEL_TYPE = 'RBF' - N_SAMPLES = 1000 - TRAINER_GRID_SEARCH_PARAMS = {'cost': [1], 'gamma': [0.5, 1]} - MEAN_STD_NORM_FLAG = True # enable mean-std normalization - FRAME_LEVEL_SCORES_FLAG = True # one score per frame(!) in this case - - algorithm = VideoSvmPadAlgorithm( - machine_type=MACHINE_TYPE, - kernel_type=KERNEL_TYPE, - n_samples=N_SAMPLES, - trainer_grid_search_params=TRAINER_GRID_SEARCH_PARAMS, - mean_std_norm_flag=MEAN_STD_NORM_FLAG, - frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) - - machine = algorithm.train_svm( - training_features=training_features, - n_samples=algorithm.n_samples, - machine_type=algorithm.machine_type, - kernel_type=algorithm.kernel_type, - trainer_grid_search_params=algorithm.trainer_grid_search_params, - mean_std_norm_flag=algorithm.mean_std_norm_flag, - projector_file="", - save_debug_data_flag=False) - - assert machine.n_support_vectors == [148, 150] - assert machine.gamma == 0.5 - - real_sample = algorithm.convert_frame_cont_to_array(real[0]) - - prob = machine.predict_class_and_probabilities(real_sample)[1] - - assert prob[0, 0] > prob[0, 1] - - precision = algorithm.comp_prediction_precision(machine, real_array, - attack_array) - - assert precision > 0.99 - - -#============================================================================== -def test_video_gmm_pad_algorithm(): - """ - Test the VideoGmmPadAlgorithm algorithm. - """ - - random.seed(7) - - N = 1000 - mu = 1 - sigma = 1 - real_array = np.transpose( - np.vstack([[random.gauss(mu, sigma) for _ in range(N)], - [random.gauss(mu, sigma) for _ in range(N)]])) - - mu = 5 - sigma = 1 - attack_array = np.transpose( - np.vstack([[random.gauss(mu, sigma) for _ in range(N)], - [random.gauss(mu, sigma) for _ in range(N)]])) - - real = convert_array_to_list_of_frame_cont(real_array) - - N_COMPONENTS = 1 - RANDOM_STATE = 3 - FRAME_LEVEL_SCORES_FLAG = True - - algorithm = VideoGmmPadAlgorithm( - n_components=N_COMPONENTS, - random_state=RANDOM_STATE, - frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG) - - # training_features[0] - training features for the REAL class. - real_array_converted = algorithm.convert_list_of_frame_cont_to_array( - real) # output is array - - assert (real_array == real_array_converted).all() - - # Train the GMM machine and get normalizers: - machine, features_mean, features_std = algorithm.train_gmm( - real=real_array_converted, - n_components=algorithm.n_components, - random_state=algorithm.random_state) - - algorithm.machine = machine - - algorithm.features_mean = features_mean - - algorithm.features_std = features_std - - scores_real = algorithm.project(real_array_converted) - - scores_attack = algorithm.project(attack_array) - - assert (np.min(scores_real) + 7.9423798970985917) < 0.000001 - assert (np.max(scores_real) + 1.8380480068281055) < 0.000001 - assert (np.min(scores_attack) + 38.831260843070098) < 0.000001 - assert (np.max(scores_attack) + 5.3633030621521272) < 0.000001