Commit 1f602e53 authored by Manuel Günther's avatar Manuel Günther

Moved BIC from bob.learn.misc to here.

parent 60b887b3
......@@ -20,7 +20,7 @@ before_install:
- if [ -n "${NUMPYSPEC}" ]; then sudo apt-get install -qq gfortran; fi
- if [ -n "${NUMPYSPEC}" ]; then pip install --upgrade pip setuptools; fi
- if [ -n "${NUMPYSPEC}" ]; then pip install --find-links http://wheels.astropy.org/ --find-links http://wheels2.astropy.org/ --use-wheel numpy$NUMPYSPEC; fi
- pip install --find-links http://wheels.astropy.org/ --find-links http://wheels2.astropy.org/ --use-wheel sphinx nose==1.3.0 jinja2==2.6 cpp-coveralls setuptools==7.0
- pip install --find-links http://wheels.astropy.org/ --find-links http://wheels2.astropy.org/ --use-wheel sphinx nose==1.3.0 jinja2==2.6 cpp-coveralls pygments==1.6 setuptools==7.0
install:
- python bootstrap.py
- CFLAGS=-coverage ./bin/buildout
......
This diff is collapsed.
This diff is collapsed.
......@@ -16,6 +16,7 @@
#include <bob.learn.linear/logreg.h>
#include <bob.learn.linear/whitening.h>
#include <bob.learn.linear/wccn.h>
#include <bob.learn.linear/bic.h>
#define BOB_LEARN_LINEAR_MODULE_PREFIX bob.learn.linear
#define BOB_LEARN_LINEAR_MODULE_NAME _library
......@@ -46,6 +47,12 @@ enum _PyBobLearnLinear_ENUM{
// Bindings for bob.learn.linear.WCCNTrainer
PyBobLearnLinearWCCNTrainer_Type_NUM,
PyBobLearnLinearWCCNTrainer_Check_NUM,
// Bindings for bob.learn.linear.BICMachine
PyBobLearnLinearBICMachine_Type_NUM,
PyBobLearnLinearBICMachine_Check_NUM,
// Bindings for bob.learn.linear.BICTrainer
PyBobLearnLinearBICTrainer_Type_NUM,
PyBobLearnLinearBICTrainer_Check_NUM,
// Total number of C API pointers
PyBobLearnLinear_API_pointers
};
......@@ -144,6 +151,36 @@ typedef struct {
#define PyBobLearnLinearWCCNTrainer_Check_PROTO (PyObject* o)
/**********************************************
* Bindings for bob.learn.linear.BICMachine *
**********************************************/
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::learn::linear::BICMachine> cxx;
} PyBobLearnLinearBICMachineObject;
#define PyBobLearnLinearBICMachine_Type_TYPE PyTypeObject
#define PyBobLearnLinearBICMachine_Check_RET int
#define PyBobLearnLinearBICMachine_Check_PROTO (PyObject* o)
/**********************************************
* Bindings for bob.learn.linear.BICTrainer *
**********************************************/
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::learn::linear::BICTrainer> cxx;
} PyBobLearnLinearBICTrainerObject;
#define PyBobLearnLinearBICTrainer_Type_TYPE PyTypeObject
#define PyBobLearnLinearBICTrainer_Check_RET int
#define PyBobLearnLinearBICTrainer_Check_PROTO (PyObject* o)
#ifdef BOB_LEARN_LINEAR_MODULE
/* This section is used when compiling `bob.learn.linear' itself */
......@@ -204,6 +241,22 @@ typedef struct {
PyBobLearnLinearWCCNTrainer_Check_RET PyBobLearnLinearWCCNTrainer_Check PyBobLearnLinearWCCNTrainer_Check_PROTO;
/**********************************************
* Bindings for bob.learn.linear.BICMachine *
**********************************************/
extern PyBobLearnLinearBICMachine_Type_TYPE PyBobLearnLinearBICMachine_Type;
PyBobLearnLinearBICMachine_Check_RET PyBobLearnLinearBICMachine_Check PyBobLearnLinearBICMachine_Check_PROTO;
/**********************************************
* Bindings for bob.learn.linear.BICTrainer *
**********************************************/
extern PyBobLearnLinearBICTrainer_Type_TYPE PyBobLearnLinearBICTrainer_Type;
PyBobLearnLinearBICTrainer_Check_RET PyBobLearnLinearBICTrainer_Check PyBobLearnLinearBICTrainer_Check_PROTO;
#else
/* This section is used in modules that use `bob.learn.linear's' C-API */
......@@ -286,6 +339,22 @@ typedef struct {
# define PyBobLearnLinearWCCNTrainer_Check (*(PyBobLearnLinearWCCNTrainer_Check_RET (*)PyBobLearnLinearWCCNTrainer_Check_PROTO) PyBobLearnLinear_API[PyBobLearnLinearWCCNTrainer_Check_NUM])
/**********************************************
* Bindings for bob.learn.linear.BICMachine *
**********************************************/
# define PyBobLearnLinearBICMachine_Type (*(PyBobLearnLinearBICMachine_Type_TYPE *)PyBobLearnLinear_API[PyBobLearnLinearBICMachine_Type_NUM])
# define PyBobLearnLinearBICMachine_Check (*(PyBobLearnLinearBICMachine_Check_RET (*)PyBobLearnLinearBICMachine_Check_PROTO) PyBobLearnLinear_API[PyBobLearnLinearBICMachine_Check_NUM])
/**********************************************
* Bindings for bob.learn.linear.BICTrainer *
**********************************************/
# define PyBobLearnLinearBICTrainer_Type (*(PyBobLearnLinearBICTrainer_Type_TYPE *)PyBobLearnLinear_API[PyBobLearnLinearBICTrainer_Type_NUM])
# define PyBobLearnLinearBICTrainer_Check (*(PyBobLearnLinearBICTrainer_Check_RET (*)PyBobLearnLinearBICTrainer_Check_PROTO) PyBobLearnLinear_API[PyBobLearnLinearBICTrainer_Check_NUM])
# if !defined(NO_IMPORT_ARRAY)
/**
......
/**
* @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_LINEAR_BIC_H
#define BOB_LEARN_LINEAR_BIC_H
#include <blitz/array.h>
#include <bob.io.base/HDF5File.h>
namespace bob { namespace learn { namespace linear {
/**
* 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:
//! generates an empty BIC machine
BICMachine(bool use_DFFS = false);
//! Copy constructor
BICMachine(const BICMachine& other);
//! Load from file
BICMachine(bob::io::base::HDF5File& hdf5);
//! 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
double forward_(const blitz::Array<double,1>& input) const;
//! performs some checks before calling the forward_ method
double forward (const blitz::Array<double,1>& input) const;
//! sets the IEC vectors of the given class (used by the trainer only; not bound to python)
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 (used by the trainer only; not bound to python)
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& hdf5);
//! saves this machine to the given hdf5 file.
void save(bob::io::base::HDF5File& hdf5) const;
//! Use the Distance From Feature Space
void use_DFFS(bool use_DFFS);
//! 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;
};
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(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, 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_BICMACHINE_H
......@@ -9,6 +9,6 @@
#define BOB_LEARN_LINEAR_CONFIG_H
/* Macros that define versions and important names */
#define BOB_LEARN_LINEAR_API_VERSION 0x0200
#define BOB_LEARN_LINEAR_API_VERSION 0x0201
#endif /* BOB_LEARN_LINEAR_CONFIG_H */
......@@ -35,6 +35,8 @@ static PyModuleDef module_definition = {
};
#endif
extern bool init_BobLearnLinearBIC(PyObject* module);
static PyObject* create_module (void) {
PyBobLearnLinearMachine_Type.tp_new = PyType_GenericNew;
......@@ -86,6 +88,8 @@ static PyObject* create_module (void) {
Py_INCREF(&PyBobLearnLinearWCCNTrainer_Type);
if (PyModule_AddObject(m, "WCCNTrainer", (PyObject *)&PyBobLearnLinearWCCNTrainer_Type) < 0) return 0;
if (!init_BobLearnLinearBIC(m)) return 0;
static void* PyBobLearnLinear_API[PyBobLearnLinear_API_pointers];
/* exhaustive list of C APIs */
......
#!/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
import bob.learn.linear
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 = bob.learn.linear.BICMachine()
trainer = bob.learn.linear.BICTrainer()
# train machine with intrapersonal data only
trainer.train(intra_data, intra_data, machine)
# => 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(intra_data, extra_data, machine)
# 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.
machine2 = trainer.train(intra_data, extra_data)
assert machine.is_similar_to(machine2)
@nose.tools.raises(RuntimeError)
def test_raises():
# Tests the BIC training of the BICTrainer
intra_data, extra_data = training_data()
# train BIC machine
trainer = bob.learn.linear.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 = bob.learn.linear.BICMachine(True)
trainer.train(intra_data, intra_data, machine)
def test_BIC():
# Tests the BIC training of the BICTrainer
intra_data, extra_data = training_data()
# train BIC machine
trainer = bob.learn.linear.BICTrainer(2,2)
# So, now without rho...
machine = bob.learn.linear.BICMachine(False)
# First, train the machine with intrapersonal data only
trainer.train(intra_data, intra_data, machine)
# => 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(intra_data, extra_data, machine)
# 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.
machine2 = trainer.train(intra_data, extra_data)
assert machine == machine2
if __name__ == '__main__':
test_IEC()
......@@ -61,6 +61,7 @@ setup(
"bob/learn/linear/cpp/logreg.cpp",
"bob/learn/linear/cpp/whitening.cpp",
"bob/learn/linear/cpp/wccn.cpp",
"bob/learn/linear/cpp/bic.cpp",
],
bob_packages = bob_packages,
version = version,
......@@ -76,6 +77,7 @@ setup(
"bob/learn/linear/logreg.cpp",
"bob/learn/linear/whitening.cpp",
"bob/learn/linear/wccn.cpp",
"bob/learn/linear/bic.cpp",
"bob/learn/linear/main.cpp",
],
bob_packages = bob_packages,
......
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