Commit c720a2cb authored by Guillaume HEUSCH's avatar Guillaume HEUSCH

[algorithm] added LDA and unit tests, fixed the doc index to include algorithms

parent e03ae9ea
......@@ -21,8 +21,12 @@ class MLP(Algorithm):
----------
hidden_units : :py:obj:`tuple` of :any:`int`
The number of hidden units in each hidden layer
max_iter : int
max_iter : :any:`int`
The maximum number of training iterations
precision : :any:`float`
criterion to stop the training: if the difference
between current and last loss is smaller than
this number, then stop training.
"""
def __init__(self, hidden_units=(10, 10), max_iter=1000, precision=0.001, **kwargs):
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
import numpy
from bob.bio.base.algorithm import LDA
class PadLDA(LDA):
"""Wrapper for bob.bio.base.algorithm.LDA,
Here, LDA is used in a PAD context. This means that the feature
will be projected on a two-dimensional subspace, where the two
dimensions represents the real and attack classes.
For more details, you may want to have a look at
`bob.learn.linear Documentation`_
.. _bob.learn.linear Documentation:
https://www.idiap.ch/software/bob/docs/bob/bob.learn.linear/stable/index.html
Attributes
----------
lda_subspace_dimension : int
the dimension of the LDA subspace. In the PAD case, the default
value is *always* used, and corresponds to the number of classes
in the training set (i.e. 2).
pca_subspace_dimension : int
The dimension of the PCA subspace to be applied
before on the data, before applying LDA.
use_pinv : bool
Use the pseudo-inverse in LDA computation.
"""
def __init__(self,
lda_subspace_dimension = None, # if set, the LDA subspace will be truncated to the given number of dimensions; by default it is limited to the number of classes in the training set
pca_subspace_dimension = None, # if set, a PCA subspace truncation is performed before applying LDA; might be integral or float
use_pinv = False,
**kwargs
):
"""Init function
Parameters
----------
lda_subspace_dimension : int
the dimension of the LDA subspace. In the PAD case, the default
value is *always* used, and corresponds to the number of classes
in the training set (i.e. 2).
pca_subspace_dimension : int
The dimension of the PCA subspace to be applied
before on the data, before applying LDA.
use_pinv : bool
Use the pseudo-inverse in LDA computation.
"""
super(PadLDA, self).__init__(
lda_subspace_dimension = lda_subspace_dimension,
pca_subspace_dimension = pca_subspace_dimension,
use_pinv = use_pinv,
**kwargs
)
def read_toscore_object(self, toscore_object_file):
"""Reads the toscore_object feature from a file.
By default, the toscore_object feature is identical to the projected feature.
Hence, this base class implementation simply calls :py:meth:`bob.pad.base.algorithm.Algorithm.read_feature`.
If your algorithm requires different behavior, please overwrite this function.
Parameters
----------
toscore_object_file : str or :py:class:`bob.io.base.HDF5File`
The file open for reading, or the file name to read from.
Returns
-------
object:
The toscore_object that was read from file.
"""
return self.read_feature(toscore_object_file)
def score(self, toscore):
return [toscore[0]]
......@@ -6,6 +6,7 @@ from .SVMCascadePCA import SVMCascadePCA
from .Predictions import Predictions
from .MLP import MLP
from .PadLDA import PadLDA
# to fix sphinx warnings of not able to find classes, when path is shortened
def __appropriate__(*args):
......@@ -33,6 +34,8 @@ __appropriate__(
LogRegr,
SVMCascadePCA,
Predictions,
MLP,
PadLDA
)
# gets sphinx autodoc done right - don't remove it
......
......@@ -203,9 +203,36 @@ def test_MLP():
mlp.train_projector(training_features, '/tmp/mlp.hdf5')
real_sample = real_array[0]
prob = mlp.project(real_sample)
assert prob[0] > prob[1]
def test_LDA():
"""
Test the LDA PAD 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)]]))
training_features = [real_array, attack_array]
lda = PadLDA()
lda.train_projector(training_features, '/tmp/lda.hdf5')
real_sample = real_array[0]
prob = lda.project(real_sample)
assert prob[0] > prob[1]
......@@ -28,6 +28,7 @@ Algorithm
.. autosummary::
bob.pad.base.tools.train_projector
bob.pad.base.tools.project
bob.pad.base.algorithm
Scoring
~~~~~~~
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment