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