From e684c59d359939b9cc4b85d7482f8bc4ba62494d Mon Sep 17 00:00:00 2001
From: Olegs NIKISINS <onikisins@italix03.idiap.ch>
Date: Thu, 13 Jul 2017 16:34:46 +0200
Subject: [PATCH] Added the unit tests for the VideoSvmPadAlgorithm algorithm

---
 .../face/algorithm/VideoSvmPadAlgorithm.py    | 29 +++++---
 bob/pad/face/test/test.py                     | 70 +++++++++++++++++--
 2 files changed, 83 insertions(+), 16 deletions(-)

diff --git a/bob/pad/face/algorithm/VideoSvmPadAlgorithm.py b/bob/pad/face/algorithm/VideoSvmPadAlgorithm.py
index 110c0786..c8d55779 100644
--- a/bob/pad/face/algorithm/VideoSvmPadAlgorithm.py
+++ b/bob/pad/face/algorithm/VideoSvmPadAlgorithm.py
@@ -446,7 +446,8 @@ class VideoSvmPadAlgorithm(Algorithm):
                   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 = ""):
+                  projector_file = "",
+                  save_debug_data_flag = True):
         """
         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
@@ -487,6 +488,10 @@ class VideoSvmPadAlgorithm(Algorithm):
             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``.
+
         **Returns:**
 
         ``machine`` : object
@@ -544,16 +549,18 @@ class VideoSvmPadAlgorithm(Algorithm):
             setattr(trainer, key, selected_params[key]) # set the params of trainer
 
         # Save the data, which is usefull for debugging.
-        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
-        debug_dict['cost'] = selected_params['cost']
-        debug_dict['gamma'] = selected_params['gamma']
-        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
+        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
+            debug_dict['cost'] = selected_params['cost']
+            debug_dict['gamma'] = selected_params['gamma']
+            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_list_of_frame_cont_to_array(training_features[0]) # output is array
diff --git a/bob/pad/face/test/test.py b/bob/pad/face/test/test.py
index 54f5e302..160fbdc9 100644
--- a/bob/pad/face/test/test.py
+++ b/bob/pad/face/test/test.py
@@ -29,6 +29,10 @@ from ..extractor import FrameDiffFeatures
 
 from ..extractor import VideoLBPHistogram
 
+from ..algorithm import VideoSvmPadAlgorithm
+
+import random
+
 #==============================================================================
 def test_lbp_histogram():
     lbp = LBPHistogram()
@@ -257,37 +261,93 @@ def test_video_lbp_histogram():
     assert (lbp_histograms[0][1][-1] - 0.031737773152965658) < 0.000001
 
 
+#==============================================================================
+def convert_array_to_list_of_frame_cont(data):
+    """
+    Convert an input 2D array to a list of FrameContainers.
 
+    **Parameters:**
 
+    ``data`` : 2D :py:class:`numpy.ndarray`
+        Input data array of the dimensionality (N_samples X N_features ).
 
+        **Returns:**
 
+    ``frame_container_list`` : [FrameContainer]
+        A list of FrameContainers, see ``bob.bio.video.utils.FrameContainer``
+        for further details. Each frame container contains one feature vector.
+    """
 
+    frame_container_list = []
 
+    for idx, vec in enumerate(data):
 
+        frame_container = bob.bio.video.FrameContainer() # initialize the FrameContainer
 
+        frame_container.add(0, vec)
 
+        frame_container_list.append( 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
 
 
 
-- 
GitLab