From 10de8afab5eb5c6957c88fe814e31767f6ba4527 Mon Sep 17 00:00:00 2001
From: Pavel Korshunov <pavel.korshunov@idiap.ch>
Date: Tue, 13 Feb 2018 21:49:43 +0100
Subject: [PATCH] Moved algos to bob.pad.base and renamed them

---
 bob/pad/face/__init__.py                      |    2 +-
 .../algorithm/VideoCascadeSvmPadAlgorithm.py  | 1088 -----------------
 .../face/algorithm/VideoGmmPadAlgorithm.py    |  506 --------
 bob/pad/face/algorithm/VideoLRPadAlgorithm.py |  594 ---------
 .../face/algorithm/VideoSvmPadAlgorithm.py    |  962 ---------------
 bob/pad/face/algorithm/__init__.py            |   31 -
 .../video_cascade_svm_pad_algorithm.py        |   36 +-
 .../algorithm/video_gmm_pad_algorithm.py      |   72 +-
 .../algorithm/video_svm_pad_algorithm.py      |    8 +-
 bob/pad/face/config/frame_diff_svm.py         |    4 +-
 .../config/frame_diff_svm_aggregated_db.py    |    4 +-
 bob/pad/face/config/lbp_svm.py                |    4 +-
 bob/pad/face/config/lbp_svm_aggregated_db.py  |    4 +-
 bob/pad/face/config/qm_lr.py                  |    4 +-
 bob/pad/face/config/qm_one_class_gmm.py       |    4 +-
 .../config/qm_one_class_svm_aggregated_db.py  |    4 +-
 .../qm_one_class_svm_cascade_aggregated_db.py |    4 +-
 bob/pad/face/config/qm_svm.py                 |    4 +-
 bob/pad/face/config/qm_svm_aggregated_db.py   |    4 +-
 bob/pad/face/test/test.py                     |  130 --
 20 files changed, 79 insertions(+), 3390 deletions(-)
 delete mode 100644 bob/pad/face/algorithm/VideoCascadeSvmPadAlgorithm.py
 delete mode 100644 bob/pad/face/algorithm/VideoGmmPadAlgorithm.py
 delete mode 100644 bob/pad/face/algorithm/VideoLRPadAlgorithm.py
 delete mode 100644 bob/pad/face/algorithm/VideoSvmPadAlgorithm.py
 delete mode 100644 bob/pad/face/algorithm/__init__.py

diff --git a/bob/pad/face/__init__.py b/bob/pad/face/__init__.py
index d1ea6f77..0c4f8c74 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 5da451bc..00000000
--- 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 a394cfc8..00000000
--- 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 2788e806..00000000
--- 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 ac5a09c7..00000000
--- 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 75d02e10..00000000
--- 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 5856ef3d..ac43229a 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 67787390..3e132c9c 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 10fd1a70..7d7e0f09 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 4fa07081..6d8ad4f2 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 1bd47a16..30834c4f 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 94866288..0b7ff33e 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 e2daaa2f..d8698a51 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 f971fdee..92ae1985 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 c74e7b7f..16a44c01 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 07522368..efebc108 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 f98d25cd..6b63e29d 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 00324214..609ab7de 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 e260cdc4..01199315 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 d28cf49c..af04373b 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
-- 
GitLab