diff --git a/bob/pad/base/algorithm/OCGMM.py b/bob/pad/base/algorithm/OCGMM.py new file mode 100644 index 0000000000000000000000000000000000000000..1b8c30333146aee443b385b2bb77044895312543 --- /dev/null +++ b/bob/pad/base/algorithm/OCGMM.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : + +import numpy +from bob.pad.base.algorithm import Algorithm + +import bob.learn.em +import bob.io.base + +class OCGMM(Algorithm): + """ + This class interfaces a GMM-based "classifier" to perform PAD experiments + + A GMM is used to model the bonafide features + + """ + + def __init__(self, n_gaussians=2, max_iter=1000, conv_threshold=1e-5, **kwargs): + + Algorithm.__init__(self, + performs_projection=True, + requires_projector_training=True, + **kwargs) + + self.n_gaussians = n_gaussians + self.max_iter = max_iter + self.conv_threshold = conv_threshold + + self.machine = None + self.trainer = bob.learn.em.ML_GMMTrainer(update_means=True, update_variances=True, update_weights=True) + + + def train_projector(self, training_features, projector_file): + """ + Trains the GMM using Expectation-Maximimazation with Maximum Likelihood criterion + + **Parameters** + + training_features: + """ + # training_features[0] - training features for the REAL class. + # training_features[1] - training features for the ATTACK class. + + # The data - "positive class only" + pos = numpy.array(training_features[0]) + features_dim = pos.shape[1] + + # The machine + self.machine = bob.learn.em.GMMMachine(self.n_gaussians, features_dim) + + # train + bob.learn.em.train(self.trainer, self.machine, pos, max_iterations=self.max_iter, convergence_threshold=self.conv_threshold) + f = bob.io.base.HDF5File(projector_file, 'w') + self.machine.save(f) + + + def project(self, feature): + """ + Compute the log-likelihood of the feature + """ + return self.machine(feature) + + def score(self, toscore): + return [toscore[0]] diff --git a/bob/pad/base/algorithm/SKLGMM.py b/bob/pad/base/algorithm/SKLGMM.py new file mode 100644 index 0000000000000000000000000000000000000000..c50a7adeeb88d410bc157ede8c632a2110a28500 --- /dev/null +++ b/bob/pad/base/algorithm/SKLGMM.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : + +import numpy +from bob.pad.base.algorithm import Algorithm + +import bob.io.base +from sklearn import mixture + +class SKLGMM(Algorithm): + """ + This class interfaces a GMM-based "classifier" to perform PAD experiments + + A GMM is used to model the bonafide features + + """ + + def __init__(self, n_gaussians=2, max_iter=1000, conv_threshold=1e-5, **kwargs): + + Algorithm.__init__(self, + performs_projection=True, + requires_projector_training=True, + **kwargs) + + self.n_gaussians = n_gaussians + self.max_iter = max_iter + self.conv_threshold = conv_threshold + + self.machine = mixture.GaussianMixture(n_components=n_gaussians, tol=conv_threshold, max_iter=max_iter) + self.parameters_keys = [ "covariance_type", "covariances_", "lower_bound_", "means_", + "n_components", "weights_", "converged_", "precisions_", "precisions_cholesky_"] + + + def train_projector(self, training_features, projector_file): + """ + Trains the GMM using Expectation-Maximimazation with Maximum Likelihood criterion + + **Parameters** + + training_features: + """ + # training_features[0] - training features for the REAL class. + # training_features[1] - training features for the ATTACK class. + + # The data - "positive class only" + pos = numpy.array(training_features[0]) + features_dim = pos.shape[1] + + # train + self.machine.fit(pos) + + # save + f = bob.io.base.HDF5File(projector_file, 'w') + for key in self.parameters_keys: + data = getattr(self.machine, key) + f.set(key, data) + + def load_projector(self, projector_file): + + f = bob.io.base.HDF5File(projector_file, 'r') # file to read the machine from + self.machine = mixture.GaussianMixture() + + for key in self.parameters_keys: + data = f.read(key) + setattr(self.machine, key, data) + + def project(self, feature): + """ + Compute the log-likelihood of the feature + """ + # load + return self.machine.score_samples(feature) + + def score(self, toscore): + return [toscore[0]]