Skip to content
Snippets Groups Projects
Commit 50bb9cbd authored by Tiago de Freitas Pereira's avatar Tiago de Freitas Pereira
Browse files

Merge branch '2.0.1a1' of github.com:bioidiap/bob.learn.misc into 2.0.1a1

parents 9fcafb6d 24226732
No related branches found
No related tags found
No related merge requests found
/**
* @date Tue Jun 5 16:54:27 CEST 2012
* @author Manuel Guenther <Manuel.Guenther@idiap.ch>
*
* Copyright (C) Idiap Research Institute, Martigny, Switzerland
*/
#ifndef BOB_LEARN_MISC_BICMACHINE_H
#define BOB_LEARN_MISC_BICMACHINE_H
#include <blitz/array.h>
#include <bob.io.base/HDF5File.h>
#include <bob.learn.misc/Machine.h>
namespace bob { namespace learn { namespace misc {
/**
* This class computes the Bayesian Intrapersonal/Extrapersonal Classifier (BIC),
* (see "Beyond Eigenfaces: Probabilistic Matching for Face Recognition" from Moghaddam, Wahid and Pentland)
* which estimates the posterior probability that the given <b>image difference vector</b>
* is of the intrapersonal class, i.e., both images stem from the same person.
*
* There are two possible implementations of the BIC:
* <ul>
* <li> "The Bayesian Intrapersonal/Extrapersonal Classifier" from Teixeira.<br>
* A full projection of the data is performed. No prior for the classes has to be selected.</li>
*
* <li> "Face Detection and Recognition using Maximum Likelihood Classifiers on Gabor Graphs" from Günther and Würtz.<br>
* Only mean and variance of the difference vectors are calculated. There is no subspace truncation and no priors.</li>
* </ul>
* In any of the two implementations, the resulting score (using the forward() method) is a log-likelihood estimate,
* using Mahalanobis(-like) distance measures.
*
*/
class BICMachine: public Machine<blitz::Array<double,1>, double>
{
public:
//! generates an empty BIC machine
BICMachine(bool use_DFFS = false);
//! Copy constructor
BICMachine(const BICMachine& other);
//! Assignment Operator
BICMachine& operator =(const BICMachine &other);
//! Equality operator
bool operator ==(const BICMachine& other) const;
//! Inequality operator
bool operator !=(const BICMachine& other) const;
//! Similarity operator
bool is_similar_to(const BICMachine& other, const double r_epsilon=1e-5, const double a_epsilon=1e-8) const;
//! computes the BIC probability score for the given input difference vector
void forward_(const blitz::Array<double,1>& input, double& output) const;
//! performs some checks before calling the forward_ method
void forward (const blitz::Array<double,1>& input, double& output) const;
//! sets the IEC vectors of the given class
void setIEC(bool clazz, const blitz::Array<double,1>& mean, const blitz::Array<double,1>& variances, bool copy_data = false);
//! sets the BIC projection details of the given class
void setBIC(bool clazz, const blitz::Array<double,1>& mean, const blitz::Array<double,1>& variances, const blitz::Array<double,2>& projection, const double rho, bool copy_data = false);
//! loads this machine from the given hdf5 file.
void load (bob::io::base::HDF5File& config);
//! saves this machine to the given hdf5 file.
void save (bob::io::base::HDF5File& config) const;
//! Use the Distance From Feature Space
void use_DFFS(bool use_DFFS = true);
//! Use the Distance From Feature Space
bool use_DFFS() const {return m_use_DFFS;}
private:
//! initializes internal data storages for the given class
void initialize(bool clazz, int input_length, int projected_length);
//! project data?
bool m_project_data;
//! mean vectors
blitz::Array<double, 1> m_mu_I, m_mu_E;
//! variances (eigenvalues)
blitz::Array<double, 1> m_lambda_I, m_lambda_E;
///
// only required when projection is enabled
//! add the distance from feature space?
bool m_use_DFFS;
//! projection matrices (PCA)
blitz::Array<double, 2> m_Phi_I, m_Phi_E;
//! averaged eigenvalues to calculate DFFS
double m_rho_I, m_rho_E;
//! temporary storage
mutable blitz::Array<double, 1> m_diff_I, m_diff_E;
mutable blitz::Array<double, 1> m_proj_I, m_proj_E;
};
} } } // namespaces
#endif // BOB_LEARN_MISC_BICMACHINE_H
/**
* @date Wed Jun 6 10:29:09 CEST 2012
* @author Manuel Guenther <Manuel.Guenther@idiap.ch>
*
* Copyright (C) Idiap Research Institute, Martigny, Switzerland
*/
#ifndef BOB_LEARN_MISC_BICTRAINER_H
#define BOB_LEARN_MISC_BICTRAINER_H
#include <bob.learn.misc/BICMachine.h>
namespace bob { namespace learn { namespace misc {
class BICTrainer {
public:
//! initializes a BICTrainer to train IEC (without subspace estimation)
BICTrainer() : m_M_I(0), m_M_E(0) {}
//! initializes a BICTrainer to train BIC (including subspace truncation)
BICTrainer(int intra_dim, int extra_dim) : m_M_I(intra_dim), m_M_E(extra_dim) {}
//! trains the intrapersonal and extrapersonal classes of the given BICMachine
void train(bob::learn::misc::BICMachine& machine, const blitz::Array<double,2>& intra_differences, const blitz::Array<double,2>& extra_differences) const {
train_single(false, machine, intra_differences);
train_single(true, machine, extra_differences);
}
//! trains the intrapersonal or the extrapersonal class of the given BICMachine
void train_single(bool clazz, bob::learn::misc::BICMachine& machine, const blitz::Array<double,2>& differences) const;
private:
//! dimensions of the intrapersonal and extrapersonal subspace;
//! zero if training IEC.
int m_M_I, m_M_E;
};
} } } // namespaces
#endif // BOB_LEARN_MISC_BICTRAINER_H
/**
* @author Manuel Guenther <Manuel.Guenther@idiap.ch>
* @date Wed Jun 6 10:29:09 CEST 2012
*
* Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
*/
#include <bob.blitz/capi.h>
#include <bob.blitz/cleanup.h>
#include <bob.io.base/api.h>
#include "ndarray.h"
#include <bob.learn.misc/BICMachine.h>
static double bic_call_(const bob::learn::misc::BICMachine& machine, bob::python::const_ndarray input){
double o;
machine.forward_(input.bz<double,1>(), o);
return o;
}
static double bic_call(const bob::learn::misc::BICMachine& machine, bob::python::const_ndarray input){
double o;
machine.forward(input.bz<double,1>(), o);
return o;
}
static void bic_load(bob::learn::misc::BICMachine& machine, boost::python::object file){
if (!PyBobIoHDF5File_Check(file.ptr())) PYTHON_ERROR(TypeError, "Would have expected a bob.io.base.HDF5File");
PyBobIoHDF5FileObject* hdf5 = (PyBobIoHDF5FileObject*) file.ptr();
machine.load(*hdf5->f);
}
static void bic_save(const bob::learn::misc::BICMachine& machine, boost::python::object file){
if (!PyBobIoHDF5File_Check(file.ptr())) PYTHON_ERROR(TypeError, "Would have expected a bob.io.base.HDF5File");
PyBobIoHDF5FileObject* hdf5 = (PyBobIoHDF5FileObject*) file.ptr();
machine.save(*hdf5->f);
}
void bind_machine_bic(){
// bind BICMachine
boost::python::class_<bob::learn::misc::BICMachine, boost::shared_ptr<bob::learn::misc::BICMachine> > (
"BICMachine",
"This machine is designed to classify image differences to be either intrapersonal or extrapersonal. "
"There are two possible implementations of the BIC:\n"
"\n"
"* 'The Bayesian Intrapersonal/Extrapersonal Classifier' from Teixeira [1]_. "
" A full projection of the data is performed. No prior for the classes has to be selected.\n"
"* 'Face Detection and Recognition using Maximum Likelihood Classifiers on Gabor Graphs' from Guenther and Wuertz [2]_."
" Only mean and variance of the difference vectors are calculated. There is no subspace truncation and no priors.\n"
"\n"
"What kind of machine is used is dependent on the way, this class is trained via the BICTrainer.\n"
"\n"
".. [1] Marcio Luis Teixeira. The Bayesian intrapersonal/extrapersonal classifier. Colorado State University, 2003.\n"
".. [2] Manuel Guenther and Rolf P. Wuertz. Face detection and recognition using maximum likelihood classifiers on Gabor graphs. International Journal of Pattern Recognition and Artificial Intelligence, 23(3):433-461, 2009.",
boost::python::init<bool>(
(boost::python::arg("self"), boost::python::arg("use_dffs") = false),
"Initializes an empty BICMachine. The optional boolean parameter specifies whether to use the DFFS in the BIC implementation. \n\n.. warning :: Use this flag with care, the default value 'False' is usually the best choice!"
)
)
.def(
boost::python::init<const bob::learn::misc::BICMachine&>(
(boost::python::arg("self"), boost::python::arg("other")),
"Constructs one BICMachine from another one by doing a deep copy."
)
)
.def(
boost::python::self == boost::python::self
)
.def(
"is_similar_to",
&bob::learn::misc::BICMachine::is_similar_to,
(boost::python::arg("self"), boost::python::arg("other"), boost::python::arg("r_epsilon") = 1e-5, boost::python::arg("a_epsilon") = 1e-8),
"Compares this BICMachine with the 'other' one to be approximately the same."
)
.def(
"load",
&bic_load,
(boost::python::arg("self"), boost::python::arg("file")),
"Loads the configuration parameters from an hdf5 file."
)
.def(
"save",
&bic_save,
(boost::python::arg("self"), boost::python::arg("file")),
"Saves the configuration parameters to an hdf5 file."
)
.def(
"__call__",
&bic_call,
(
boost::python::arg("self"),
boost::python::arg("input")
),
"Computes the BIC or IEC score for the given input vector, which results of a comparison of two (facial) images. "
"The resulting value is returned as a single float value. "
"The score itself is the log-likelihood score of the given input vector belonging to the intrapersonal class. "
"No sanity checks of input and output are performed."
)
.def(
"forward_",
&bic_call_,
(
boost::python::arg("self"),
boost::python::arg("input")
),
"Computes the BIC or IEC score for the given input vector, which results of a comparison of two (facial) images. "
"The score itself is the log-likelihood score of the given input vector belonging to the intrapersonal class. "
"No sanity checks of input are performed."
)
.def(
"forward",
&bic_call,
(
boost::python::arg("self"),
boost::python::arg("input")
),
"Computes the BIC or IEC score for the given input vector, which results of a comparison of two (facial) images. "
"The score itself is the log-likelihood score of the given input vector belonging to the intrapersonal class. "
"Sanity checks of input shape are performed."
)
.add_property(
"use_dffs",
// cast overloaded function with the same name to its type...
static_cast<bool (bob::learn::misc::BICMachine::*)() const>(&bob::learn::misc::BICMachine::use_DFFS),
static_cast<void (bob::learn::misc::BICMachine::*)(bool)>(&bob::learn::misc::BICMachine::use_DFFS),
"Should the Distance From Feature Space (DFFS) measure be added during scoring? \n\n.. warning :: Only set this flag to True if the number of intrapersonal and extrapersonal training pairs is approximately equal. Otherwise, weird thing may happen!"
);
}
/**
* @file trainer/python/bic.cc
* @date Wed Jun 6 10:29:09 CEST 2012
* @author Manuel Guenther <Manuel.Guenther@idiap.ch>
*
* Copyright (C) 2011-2013 Idiap Research Institute, Martigny, Switzerland
*/
#include "ndarray.h"
#include <bob.learn.misc/BICTrainer.h>
void py_train(const bob::learn::misc::BICTrainer& t,
bob::learn::misc::BICMachine& m, bob::python::const_ndarray intra_differences,
bob::python::const_ndarray extra_differences)
{
t.train(m, intra_differences.bz<double,2>(),
extra_differences.bz<double,2>());
}
void bind_trainer_bic(){
boost::python::class_<bob::learn::misc::BICTrainer, boost::shared_ptr<bob::learn::misc::BICTrainer> > (
"BICTrainer",
"A Trainer for a BICMachine. It trains either a BIC model (including projection matrix and eigenvalues), "
"or an IEC model (containing mean and variance only). See :py:class:`bob.machine.BICMachine` for more details.",
boost::python::init<int,int>(
(
boost::python::arg("self"),
boost::python::arg("intra_dim"),
boost::python::arg("extra_dim")
),
"Initializes the BICTrainer to train a BIC model with the given resulting dimensions of the intraperonal and extrapersonal subspaces."
)
)
.def(
boost::python::init<>(
(boost::python::arg("self")),
"Initializes the BICTrainer to train a IEC model."
)
)
.def(
"train",
&py_train,
(
boost::python::arg("self"),
boost::python::arg("machine"),
boost::python::arg("intra_differences"),
boost::python::arg("extra_differences")
),
"Trains the given machine (should be of type :py:class:`bob.machine.BICMachine`) to classify intrapersonal image differences vs. extrapersonal ones. "
"The given difference vectors might be the result of any image comparison function, e.g., the pixel difference of the images."
);
}
...@@ -25,7 +25,6 @@ void bind_core_bz_numpy(); ...@@ -25,7 +25,6 @@ void bind_core_bz_numpy();
/** machine bindings **/ /** machine bindings **/
void bind_machine_base(); void bind_machine_base();
void bind_machine_bic();
void bind_machine_gaussian(); void bind_machine_gaussian();
void bind_machine_gmm(); void bind_machine_gmm();
void bind_machine_kmeans(); void bind_machine_kmeans();
...@@ -44,7 +43,6 @@ void bind_trainer_ivector(); ...@@ -44,7 +43,6 @@ void bind_trainer_ivector();
void bind_trainer_plda(); void bind_trainer_plda();
void bind_trainer_wiener(); void bind_trainer_wiener();
void bind_trainer_empca(); void bind_trainer_empca();
void bind_trainer_bic();
BOOST_PYTHON_MODULE(_old_library) { BOOST_PYTHON_MODULE(_old_library) {
...@@ -77,7 +75,6 @@ BOOST_PYTHON_MODULE(_old_library) { ...@@ -77,7 +75,6 @@ BOOST_PYTHON_MODULE(_old_library) {
/** machine bindings **/ /** machine bindings **/
bind_machine_base(); bind_machine_base();
bind_machine_bic();
bind_machine_gaussian(); bind_machine_gaussian();
bind_machine_gmm(); bind_machine_gmm();
bind_machine_kmeans(); bind_machine_kmeans();
...@@ -96,6 +93,5 @@ BOOST_PYTHON_MODULE(_old_library) { ...@@ -96,6 +93,5 @@ BOOST_PYTHON_MODULE(_old_library) {
bind_trainer_plda(); bind_trainer_plda();
bind_trainer_wiener(); bind_trainer_wiener();
bind_trainer_empca(); bind_trainer_empca();
bind_trainer_bic();
} }
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# Manuel Guenther <Manuel.Guenther@idiap.ch>
# Thu Jun 14 14:45:06 CEST 2012
#
# Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
"""Test BIC trainer and machine
"""
import numpy
import nose.tools
from . import BICMachine, BICTrainer
eps = 1e-5
def equals(x, y, epsilon):
return (abs(x - y) < epsilon).all()
def training_data():
data = numpy.array([
(10., 4., 6., 8., 2.),
(8., 2., 4., 6., 0.),
(12., 6., 8., 10., 4.),
(11., 3., 7., 7., 3.),
(9., 5., 5., 9., 1.)], dtype='float64')
return data, -1. * data
def eval_data(which):
eval_data = numpy.ndarray((5,), dtype=numpy.float64)
if which == 0:
eval_data.fill(0.)
elif which == 1:
eval_data.fill(10.)
return eval_data
def test_IEC():
# Tests the IEC training of the BICTrainer
intra_data, extra_data = training_data()
# train BIC machine
machine = BICMachine()
trainer = BICTrainer()
# train machine with intrapersonal data only
trainer.train(machine, intra_data, intra_data)
# => every result should be zero
assert abs(machine(eval_data(0))) < eps
assert abs(machine(eval_data(1))) < eps
# re-train the machine with intra- and extrapersonal data
trainer.train(machine, intra_data, extra_data)
# now, only the input vector 0 should give log-likelihood 0
assert abs(machine(eval_data(0))) < eps
# while a positive vector should give a positive result
assert machine(eval_data(1)) > 0.
@nose.tools.raises(RuntimeError)
def test_raises():
# Tests the BIC training of the BICTrainer
intra_data, extra_data = training_data()
# train BIC machine
trainer = BICTrainer(2,2)
# The data are chosen such that the third eigenvalue is zero.
# Hence, calculating rho (i.e., using the Distance From Feature Space) is impossible
machine = BICMachine(True)
trainer.train(machine, intra_data, intra_data)
def test_BIC():
# Tests the BIC training of the BICTrainer
intra_data, extra_data = training_data()
# train BIC machine
trainer = BICTrainer(2,2)
# So, now without rho...
machine = BICMachine(False)
# First, train the machine with intrapersonal data only
trainer.train(machine, intra_data, intra_data)
# => every result should be zero
assert abs(machine(eval_data(0))) < eps
assert abs(machine(eval_data(1))) < eps
# re-train the machine with intra- and extrapersonal data
trainer.train(machine, intra_data, extra_data)
# now, only the input vector 0 should give log-likelihood 0
assert abs(machine(eval_data(0))) < eps
# while a positive vector should give a positive result
assert machine(eval_data(1)) > 0.
...@@ -54,7 +54,6 @@ setup( ...@@ -54,7 +54,6 @@ setup(
Library("bob.learn.misc.bob_learn_misc", Library("bob.learn.misc.bob_learn_misc",
[ [
"bob/learn/misc/cpp/BICMachine.cpp",
"bob/learn/misc/cpp/Gaussian.cpp", "bob/learn/misc/cpp/Gaussian.cpp",
"bob/learn/misc/cpp/GMMMachine.cpp", "bob/learn/misc/cpp/GMMMachine.cpp",
"bob/learn/misc/cpp/GMMStats.cpp", "bob/learn/misc/cpp/GMMStats.cpp",
...@@ -66,7 +65,6 @@ setup( ...@@ -66,7 +65,6 @@ setup(
"bob/learn/misc/cpp/WienerMachine.cpp", "bob/learn/misc/cpp/WienerMachine.cpp",
"bob/learn/misc/cpp/ZTNorm.cpp", "bob/learn/misc/cpp/ZTNorm.cpp",
"bob/learn/misc/cpp/BICTrainer.cpp",
"bob/learn/misc/cpp/EMPCATrainer.cpp", "bob/learn/misc/cpp/EMPCATrainer.cpp",
"bob/learn/misc/cpp/GMMTrainer.cpp", "bob/learn/misc/cpp/GMMTrainer.cpp",
"bob/learn/misc/cpp/IVectorTrainer.cpp", "bob/learn/misc/cpp/IVectorTrainer.cpp",
...@@ -104,8 +102,6 @@ setup( ...@@ -104,8 +102,6 @@ setup(
Extension("bob.learn.misc._old_library", Extension("bob.learn.misc._old_library",
[ [
"bob/learn/misc/old/bic.cc",
"bob/learn/misc/old/bic_trainer.cc",
"bob/learn/misc/old/empca_trainer.cc", "bob/learn/misc/old/empca_trainer.cc",
"bob/learn/misc/old/gaussian.cc", "bob/learn/misc/old/gaussian.cc",
"bob/learn/misc/old/gmm.cc", "bob/learn/misc/old/gmm.cc",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment