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

Binded IVectorMachine

parent 3799f0e1
No related branches found
No related tags found
No related merge requests found
...@@ -18,7 +18,7 @@ bob::learn::misc::IVectorMachine::IVectorMachine() ...@@ -18,7 +18,7 @@ bob::learn::misc::IVectorMachine::IVectorMachine()
bob::learn::misc::IVectorMachine::IVectorMachine(const boost::shared_ptr<bob::learn::misc::GMMMachine> ubm, bob::learn::misc::IVectorMachine::IVectorMachine(const boost::shared_ptr<bob::learn::misc::GMMMachine> ubm,
const size_t rt, const double variance_threshold): const size_t rt, const double variance_threshold):
m_ubm(ubm), m_rt(rt), m_ubm(ubm), m_rt(rt),
m_T(getDimCD(),rt), m_sigma(getDimCD()), m_T(getSupervectorLength(),rt), m_sigma(getSupervectorLength()),
m_variance_threshold(variance_threshold) m_variance_threshold(variance_threshold)
{ {
resizePrecompute(); resizePrecompute();
...@@ -204,7 +204,7 @@ void bob::learn::misc::IVectorMachine::resizeTmp() ...@@ -204,7 +204,7 @@ void bob::learn::misc::IVectorMachine::resizeTmp()
void bob::learn::misc::IVectorMachine::forward(const bob::learn::misc::GMMStats& gs, void bob::learn::misc::IVectorMachine::forward(const bob::learn::misc::GMMStats& gs,
blitz::Array<double,1>& ivector) const blitz::Array<double,1>& ivector) const
{ {
bob::core::array::assertSameDimensionLength(ivector.extent(0), (int)m_rt); bob::core::array::assertSameDimensionLength(ivector.extent(0), (int)m_rt);
forward_(gs, ivector); forward_(gs, ivector);
} }
...@@ -214,7 +214,7 @@ void bob::learn::misc::IVectorMachine::computeIdTtSigmaInvT( ...@@ -214,7 +214,7 @@ void bob::learn::misc::IVectorMachine::computeIdTtSigmaInvT(
// Computes \f$(Id + \sum_{c=1}^{C} N_{i,j,c} T^{T} \Sigma_{c}^{-1} T)\f$ // Computes \f$(Id + \sum_{c=1}^{C} N_{i,j,c} T^{T} \Sigma_{c}^{-1} T)\f$
blitz::Range rall = blitz::Range::all(); blitz::Range rall = blitz::Range::all();
bob::math::eye(output); bob::math::eye(output);
for (int c=0; c<(int)getDimC(); ++c) for (int c=0; c<(int)getNGaussians(); ++c)
output += gs.n(c) * m_cache_Tct_sigmacInv_Tc(c, rall, rall); output += gs.n(c) * m_cache_Tct_sigmacInv_Tc(c, rall, rall);
} }
...@@ -224,7 +224,7 @@ void bob::learn::misc::IVectorMachine::computeTtSigmaInvFnorm( ...@@ -224,7 +224,7 @@ void bob::learn::misc::IVectorMachine::computeTtSigmaInvFnorm(
// Computes \f$T^{T} \Sigma^{-1} \sum_{c=1}^{C} (F_c - N_c ubmmean_{c})\f$ // Computes \f$T^{T} \Sigma^{-1} \sum_{c=1}^{C} (F_c - N_c ubmmean_{c})\f$
blitz::Range rall = blitz::Range::all(); blitz::Range rall = blitz::Range::all();
output = 0; output = 0;
for (int c=0; c<(int)getDimC(); ++c) for (int c=0; c<(int)getNGaussians(); ++c)
{ {
m_tmp_d = gs.sumPx(c,rall) - gs.n(c) * m_ubm->getGaussian(c)->getMean(); m_tmp_d = gs.sumPx(c,rall) - gs.n(c) * m_ubm->getGaussian(c)->getMean();
blitz::Array<double,2> Tct_sigmacInv = m_cache_Tct_sigmacInv(c, rall, rall); blitz::Array<double,2> Tct_sigmacInv = m_cache_Tct_sigmacInv(c, rall, rall);
......
...@@ -48,13 +48,11 @@ static int PyBobLearnMiscGMMMachine_init_number(PyBobLearnMiscGMMMachineObject* ...@@ -48,13 +48,11 @@ static int PyBobLearnMiscGMMMachine_init_number(PyBobLearnMiscGMMMachineObject*
if(n_gaussians < 0){ if(n_gaussians < 0){
PyErr_Format(PyExc_TypeError, "gaussians argument must be greater than or equal to zero"); PyErr_Format(PyExc_TypeError, "gaussians argument must be greater than or equal to zero");
GMMMachine_doc.print_usage();
return -1; return -1;
} }
if(n_inputs < 0){ if(n_inputs < 0){
PyErr_Format(PyExc_TypeError, "input argument must be greater than or equal to zero"); PyErr_Format(PyExc_TypeError, "input argument must be greater than or equal to zero");
GMMMachine_doc.print_usage();
return -1; return -1;
} }
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#define BOB_LEARN_MISC_IVECTOR_MACHINE_H #define BOB_LEARN_MISC_IVECTOR_MACHINE_H
#include <blitz/array.h> #include <blitz/array.h>
#include <bob.learn.misc/Machine.h>
#include <bob.learn.misc/GMMMachine.h> #include <bob.learn.misc/GMMMachine.h>
#include <bob.learn.misc/GMMStats.h> #include <bob.learn.misc/GMMStats.h>
#include <bob.io.base/HDF5File.h> #include <bob.io.base/HDF5File.h>
...@@ -24,7 +23,7 @@ namespace bob { namespace learn { namespace misc { ...@@ -24,7 +23,7 @@ namespace bob { namespace learn { namespace misc {
* N. Dehak, P. Kenny, R. Dehak, P. Dumouchel, P. Ouellet, * N. Dehak, P. Kenny, R. Dehak, P. Dumouchel, P. Ouellet,
* IEEE Trans. on Audio, Speech and Language Processing * IEEE Trans. on Audio, Speech and Language Processing
*/ */
class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStats, blitz::Array<double,1> > class IVectorMachine
{ {
public: public:
/** /**
...@@ -124,7 +123,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat ...@@ -124,7 +123,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat
* @warning An exception is thrown if no Universal Background Model has * @warning An exception is thrown if no Universal Background Model has
* been set yet. * been set yet.
*/ */
const size_t getDimC() const const size_t getNGaussians() const
{ return m_ubm->getNGaussians(); } { return m_ubm->getNGaussians(); }
/** /**
...@@ -132,7 +131,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat ...@@ -132,7 +131,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat
* @warning An exception is thrown if no Universal Background Model has * @warning An exception is thrown if no Universal Background Model has
* been set yet. * been set yet.
*/ */
const size_t getDimD() const const size_t getNInputs() const
{ return m_ubm->getNInputs(); } { return m_ubm->getNInputs(); }
/** /**
...@@ -141,7 +140,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat ...@@ -141,7 +140,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat
* @warning An exception is thrown if no Universal Background Model has * @warning An exception is thrown if no Universal Background Model has
* been set yet. * been set yet.
*/ */
const size_t getDimCD() const const size_t getSupervectorLength() const
{ return m_ubm->getNGaussians()*m_ubm->getNInputs(); } { return m_ubm->getNGaussians()*m_ubm->getNInputs(); }
/** /**
...@@ -229,7 +228,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat ...@@ -229,7 +228,7 @@ class IVectorMachine: public bob::learn::misc::Machine<bob::learn::misc::GMMStat
*/ */
void forward_(const bob::learn::misc::GMMStats& input, blitz::Array<double,1>& output) const; void forward_(const bob::learn::misc::GMMStats& input, blitz::Array<double,1>& output) const;
protected: private:
/** /**
* @brief Apply the variance flooring thresholds. * @brief Apply the variance flooring thresholds.
* This method is called when using setVarianceThresholds() * This method is called when using setVarianceThresholds()
......
...@@ -82,6 +82,11 @@ static int PyBobLearnMiscISVBase_init_ubm(PyBobLearnMiscISVBaseObject* self, PyO ...@@ -82,6 +82,11 @@ static int PyBobLearnMiscISVBase_init_ubm(PyBobLearnMiscISVBaseObject* self, PyO
return -1; return -1;
} }
if(ru < 0){
PyErr_Format(PyExc_TypeError, "ru argument must be greater than or equal to one");
return -1;
}
self->cxx.reset(new bob::learn::misc::ISVBase(ubm->cxx, ru)); self->cxx.reset(new bob::learn::misc::ISVBase(ubm->cxx, ru));
return 0; return 0;
} }
......
/**
* @date Wed Jan 28 17:46:15 2015 +0200
* @author Tiago de Freitas Pereira <tiago.pereira@idiap.ch>
*
* @brief Python API for bob::learn::em
*
* Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
*/
#include "main.h"
/******************************************************************/
/************ Constructor Section *********************************/
/******************************************************************/
static auto IVectorMachine_doc = bob::extension::ClassDoc(
BOB_EXT_MODULE_PREFIX ".IVectorMachine",
"An IVectorMachine consists of a Total Variability subspace \f$T\f$ and allows the extraction of IVector"
"References: [Dehak2010]",
""
).add_constructor(
bob::extension::FunctionDoc(
"__init__",
"Constructor. Builds a new IVectorMachine",
"",
true
)
.add_prototype("ubm, rt, variance_threshold","")
.add_prototype("other","")
.add_prototype("hdf5","")
.add_parameter("ubm", ":py:class:`bob.learn.misc.GMMMachine`", "The Universal Background Model.")
.add_parameter("rt", "int", "Size of the Total Variability matrix (CD x rt).")
.add_parameter("variance_threshold", "double", "Variance flooring threshold for the Sigma (diagonal) matrix")
.add_parameter("other", ":py:class:`bob.learn.misc.IVectorMachine`", "A IVectorMachine object to be copied.")
.add_parameter("hdf5", ":py:class:`bob.io.base.HDF5File`", "An HDF5 file open for reading")
);
static int PyBobLearnMiscIVectorMachine_init_copy(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwargs) {
char** kwlist = IVectorMachine_doc.kwlist(1);
PyBobLearnMiscIVectorMachineObject* o;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &PyBobLearnMiscIVectorMachine_Type, &o)){
IVectorMachine_doc.print_usage();
return -1;
}
self->cxx.reset(new bob::learn::misc::IVectorMachine(*o->cxx));
return 0;
}
static int PyBobLearnMiscIVectorMachine_init_hdf5(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwargs) {
char** kwlist = IVectorMachine_doc.kwlist(2);
PyBobIoHDF5FileObject* config = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&", kwlist, &PyBobIoHDF5File_Converter, &config)){
IVectorMachine_doc.print_usage();
return -1;
}
self->cxx.reset(new bob::learn::misc::IVectorMachine(*(config->f)));
return 0;
}
static int PyBobLearnMiscIVectorMachine_init_ubm(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwargs) {
char** kwlist = IVectorMachine_doc.kwlist(0);
PyBobLearnMiscGMMMachineObject* gmm_machine;
int rt = 1;
double variance_threshold = 1e-10;
//Here we have to select which keyword argument to read
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!i|d", kwlist, &PyBobLearnMiscGMMMachine_Type, &gmm_machine, &rt, &variance_threshold)){
IVectorMachine_doc.print_usage();
return -1;
}
if(rt < 1){
PyErr_Format(PyExc_TypeError, "rt argument must be greater than or equal to one");
return -1;
}
if(variance_threshold <= 0){
PyErr_Format(PyExc_TypeError, "variance_threshold argument must be greater than zero");
return -1;
}
self->cxx.reset(new bob::learn::misc::IVectorMachine(gmm_machine->cxx, rt, variance_threshold));
return 0;
}
static int PyBobLearnMiscIVectorMachine_init(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwargs) {
BOB_TRY
// get the number of command line arguments
int nargs = (args?PyTuple_Size(args):0) + (kwargs?PyDict_Size(kwargs):0);
if(nargs == 1){
//Reading the input argument
PyObject* arg = 0;
if (PyTuple_Size(args))
arg = PyTuple_GET_ITEM(args, 0);
else {
PyObject* tmp = PyDict_Values(kwargs);
auto tmp_ = make_safe(tmp);
arg = PyList_GET_ITEM(tmp, 0);
}
// If the constructor input is Gaussian object
if (PyBobLearnMiscIVectorMachine_Check(arg))
return PyBobLearnMiscIVectorMachine_init_copy(self, args, kwargs);
// If the constructor input is a HDF5
else
return PyBobLearnMiscIVectorMachine_init_hdf5(self, args, kwargs);
}
else if ((nargs == 2) || (nargs == 3))
PyBobLearnMiscIVectorMachine_init_ubm(self, args, kwargs);
else{
PyErr_Format(PyExc_RuntimeError, "number of arguments mismatch - %s requires 1,2 or 3 argument, but you provided %d (see help)", Py_TYPE(self)->tp_name, nargs);
IVectorMachine_doc.print_usage();
return -1;
}
BOB_CATCH_MEMBER("cannot create IVectorMachine", 0)
return 0;
}
static void PyBobLearnMiscIVectorMachine_delete(PyBobLearnMiscIVectorMachineObject* self) {
self->cxx.reset();
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject* PyBobLearnMiscIVectorMachine_RichCompare(PyBobLearnMiscIVectorMachineObject* self, PyObject* other, int op) {
BOB_TRY
if (!PyBobLearnMiscIVectorMachine_Check(other)) {
PyErr_Format(PyExc_TypeError, "cannot compare `%s' with `%s'", Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name);
return 0;
}
auto other_ = reinterpret_cast<PyBobLearnMiscIVectorMachineObject*>(other);
switch (op) {
case Py_EQ:
if (*self->cxx==*other_->cxx) Py_RETURN_TRUE; else Py_RETURN_FALSE;
case Py_NE:
if (*self->cxx==*other_->cxx) Py_RETURN_FALSE; else Py_RETURN_TRUE;
default:
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
BOB_CATCH_MEMBER("cannot compare IVectorMachine objects", 0)
}
int PyBobLearnMiscIVectorMachine_Check(PyObject* o) {
return PyObject_IsInstance(o, reinterpret_cast<PyObject*>(&PyBobLearnMiscIVectorMachine_Type));
}
/******************************************************************/
/************ Variables Section ***********************************/
/******************************************************************/
/***** shape *****/
static auto shape = bob::extension::VariableDoc(
"shape",
"(int,int, int)",
"A tuple that represents the number of gaussians, dimensionality of each Gaussian, dimensionality of the rT (total variability matrix) ``(#Gaussians, #Inputs, #rT)``.",
""
);
PyObject* PyBobLearnMiscIVectorMachine_getShape(PyBobLearnMiscIVectorMachineObject* self, void*) {
BOB_TRY
return Py_BuildValue("(i,i,i)", self->cxx->getNGaussians(), self->cxx->getNInputs(), self->cxx->getDimRt());
BOB_CATCH_MEMBER("shape could not be read", 0)
}
/***** supervector_length *****/
static auto supervector_length = bob::extension::VariableDoc(
"supervector_length",
"int",
"Returns the supervector length."
"NGaussians x NInputs: Number of Gaussian components by the feature dimensionality",
"@warning An exception is thrown if no Universal Background Model has been set yet."
);
PyObject* PyBobLearnMiscIVectorMachine_getSupervectorLength(PyBobLearnMiscIVectorMachineObject* self, void*) {
BOB_TRY
return Py_BuildValue("i", self->cxx->getSupervectorLength());
BOB_CATCH_MEMBER("supervector_length could not be read", 0)
}
/***** T *****/
static auto T = bob::extension::VariableDoc(
"t",
"array_like <float, 2D>",
"Returns the Total Variability matrix",
""
);
PyObject* PyBobLearnMiscIVectorMachine_getT(PyBobLearnMiscIVectorMachineObject* self, void*){
BOB_TRY
return PyBlitzArrayCxx_AsConstNumpy(self->cxx->getT());
BOB_CATCH_MEMBER("`t` could not be read", 0)
}
int PyBobLearnMiscIVectorMachine_setT(PyBobLearnMiscIVectorMachineObject* self, PyObject* value, void*){
BOB_TRY
PyBlitzArrayObject* o;
if (!PyBlitzArray_Converter(value, &o)){
PyErr_Format(PyExc_RuntimeError, "%s %s expects a 2D array of floats", Py_TYPE(self)->tp_name, T.name());
return -1;
}
auto o_ = make_safe(o);
auto b = PyBlitzArrayCxx_AsBlitz<double,2>(o, "t");
if (!b) return -1;
self->cxx->setT(*b);
return 0;
BOB_CATCH_MEMBER("`t` vector could not be set", -1)
}
/***** sigma *****/
static auto sigma = bob::extension::VariableDoc(
"sigma",
"array_like <float, 1D>",
"The residual matrix of the model sigma",
""
);
PyObject* PyBobLearnMiscIVectorMachine_getSigma(PyBobLearnMiscIVectorMachineObject* self, void*){
BOB_TRY
return PyBlitzArrayCxx_AsConstNumpy(self->cxx->getSigma());
BOB_CATCH_MEMBER("`sigma` could not be read", 0)
}
int PyBobLearnMiscIVectorMachine_setSigma(PyBobLearnMiscIVectorMachineObject* self, PyObject* value, void*){
BOB_TRY
PyBlitzArrayObject* o;
if (!PyBlitzArray_Converter(value, &o)){
PyErr_Format(PyExc_RuntimeError, "%s %s expects a 1D array of floats", Py_TYPE(self)->tp_name, sigma.name());
return -1;
}
auto o_ = make_safe(o);
auto b = PyBlitzArrayCxx_AsBlitz<double,1>(o, "sigma");
if (!b) return -1;
self->cxx->setSigma(*b);
return 0;
BOB_CATCH_MEMBER("`sigma` vector could not be set", -1)
}
/***** variance_threshold *****/
static auto variance_threshold = bob::extension::VariableDoc(
"variance_threshold",
"double",
"Threshold for the variance contained in sigma",
""
);
PyObject* PyBobLearnMiscIVectorMachine_getVarianceThreshold(PyBobLearnMiscIVectorMachineObject* self, void*) {
BOB_TRY
return Py_BuildValue("d", self->cxx->getVarianceThreshold());
BOB_CATCH_MEMBER("variance_threshold could not be read", 0)
}
int PyBobLearnMiscIVectorMachine_setVarianceThreshold(PyBobLearnMiscIVectorMachineObject* self, PyObject* value, void*){
BOB_TRY
if (!PyNumber_Check(value)){
PyErr_Format(PyExc_RuntimeError, "%s %s expects an double", Py_TYPE(self)->tp_name, variance_threshold.name());
return -1;
}
if (PyFloat_AS_DOUBLE(value) < 0){
PyErr_Format(PyExc_TypeError, "variance_threshold must be greater than or equal to zero");
return -1;
}
self->cxx->setVarianceThreshold(PyFloat_AS_DOUBLE(value));
BOB_CATCH_MEMBER("variance_threshold could not be set", -1)
return 0;
}
static PyGetSetDef PyBobLearnMiscIVectorMachine_getseters[] = {
{
shape.name(),
(getter)PyBobLearnMiscIVectorMachine_getShape,
0,
shape.doc(),
0
},
{
supervector_length.name(),
(getter)PyBobLearnMiscIVectorMachine_getSupervectorLength,
0,
supervector_length.doc(),
0
},
{
T.name(),
(getter)PyBobLearnMiscIVectorMachine_getT,
(setter)PyBobLearnMiscIVectorMachine_setT,
T.doc(),
0
},
{
variance_threshold.name(),
(getter)PyBobLearnMiscIVectorMachine_getVarianceThreshold,
(setter)PyBobLearnMiscIVectorMachine_setVarianceThreshold,
variance_threshold.doc(),
0
},
{
sigma.name(),
(getter)PyBobLearnMiscIVectorMachine_getSigma,
(setter)PyBobLearnMiscIVectorMachine_setSigma,
sigma.doc(),
0
},
{0} // Sentinel
};
/******************************************************************/
/************ Functions Section ***********************************/
/******************************************************************/
/*** save ***/
static auto save = bob::extension::FunctionDoc(
"save",
"Save the configuration of the IVectorMachine to a given HDF5 file"
)
.add_prototype("hdf5")
.add_parameter("hdf5", ":py:class:`bob.io.base.HDF5File`", "An HDF5 file open for writing");
static PyObject* PyBobLearnMiscIVectorMachine_Save(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwargs) {
BOB_TRY
// get list of arguments
char** kwlist = save.kwlist(0);
PyBobIoHDF5FileObject* hdf5;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&", kwlist, PyBobIoHDF5File_Converter, &hdf5)) return 0;
auto hdf5_ = make_safe(hdf5);
self->cxx->save(*hdf5->f);
BOB_CATCH_MEMBER("cannot save the data", 0)
Py_RETURN_NONE;
}
/*** load ***/
static auto load = bob::extension::FunctionDoc(
"load",
"Load the configuration of the IVectorMachine to a given HDF5 file"
)
.add_prototype("hdf5")
.add_parameter("hdf5", ":py:class:`bob.io.base.HDF5File`", "An HDF5 file open for reading");
static PyObject* PyBobLearnMiscIVectorMachine_Load(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwargs) {
BOB_TRY
char** kwlist = load.kwlist(0);
PyBobIoHDF5FileObject* hdf5;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&", kwlist, PyBobIoHDF5File_Converter, &hdf5)) return 0;
auto hdf5_ = make_safe(hdf5);
self->cxx->load(*hdf5->f);
BOB_CATCH_MEMBER("cannot load the data", 0)
Py_RETURN_NONE;
}
/*** is_similar_to ***/
static auto is_similar_to = bob::extension::FunctionDoc(
"is_similar_to",
"Compares this IVectorMachine with the ``other`` one to be approximately the same.",
"The optional values ``r_epsilon`` and ``a_epsilon`` refer to the "
"relative and absolute precision for the ``weights``, ``biases`` "
"and any other values internal to this machine."
)
.add_prototype("other, [r_epsilon], [a_epsilon]","output")
.add_parameter("other", ":py:class:`bob.learn.misc.IVectorMachine`", "A IVectorMachine object to be compared.")
.add_parameter("r_epsilon", "float", "Relative precision.")
.add_parameter("a_epsilon", "float", "Absolute precision.")
.add_return("output","bool","True if it is similar, otherwise false.");
static PyObject* PyBobLearnMiscIVectorMachine_IsSimilarTo(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwds) {
/* Parses input arguments in a single shot */
char** kwlist = is_similar_to.kwlist(0);
//PyObject* other = 0;
PyBobLearnMiscIVectorMachineObject* other = 0;
double r_epsilon = 1.e-5;
double a_epsilon = 1.e-8;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|dd", kwlist,
&PyBobLearnMiscIVectorMachine_Type, &other,
&r_epsilon, &a_epsilon)){
is_similar_to.print_usage();
return 0;
}
if (self->cxx->is_similar_to(*other->cxx, r_epsilon, a_epsilon))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
/*** forward ***/
static auto forward = bob::extension::FunctionDoc(
"forward",
"Execute the machine",
"",
true
)
.add_prototype("stats")
.add_parameter("stats", ":py:class:`bob.learn.misc.GMMStats`", "Statistics as input");
static PyObject* PyBobLearnMiscIVectorMachine_Forward(PyBobLearnMiscIVectorMachineObject* self, PyObject* args, PyObject* kwargs) {
BOB_TRY
char** kwlist = forward.kwlist(0);
PyBobLearnMiscGMMStatsObject* stats = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &PyBobLearnMiscGMMStats_Type, &stats))
Py_RETURN_NONE;
blitz::Array<double,1> ivector(self->cxx->getDimRt());
self->cxx->forward(*stats->cxx, ivector);
return PyBlitzArrayCxx_AsConstNumpy(ivector);
BOB_CATCH_MEMBER("cannot forward", 0)
}
static PyMethodDef PyBobLearnMiscIVectorMachine_methods[] = {
{
save.name(),
(PyCFunction)PyBobLearnMiscIVectorMachine_Save,
METH_VARARGS|METH_KEYWORDS,
save.doc()
},
{
load.name(),
(PyCFunction)PyBobLearnMiscIVectorMachine_Load,
METH_VARARGS|METH_KEYWORDS,
load.doc()
},
{
is_similar_to.name(),
(PyCFunction)PyBobLearnMiscIVectorMachine_IsSimilarTo,
METH_VARARGS|METH_KEYWORDS,
is_similar_to.doc()
},
/*
{
forward.name(),
(PyCFunction)PyBobLearnMiscIVectorMachine_Forward,
METH_VARARGS|METH_KEYWORDS,
forward.doc()
},*/
{0} /* Sentinel */
};
/******************************************************************/
/************ Module Section **************************************/
/******************************************************************/
// Define the JFA type struct; will be initialized later
PyTypeObject PyBobLearnMiscIVectorMachine_Type = {
PyVarObject_HEAD_INIT(0,0)
0
};
bool init_BobLearnMiscIVectorMachine(PyObject* module)
{
// initialize the type struct
PyBobLearnMiscIVectorMachine_Type.tp_name = IVectorMachine_doc.name();
PyBobLearnMiscIVectorMachine_Type.tp_basicsize = sizeof(PyBobLearnMiscIVectorMachineObject);
PyBobLearnMiscIVectorMachine_Type.tp_flags = Py_TPFLAGS_DEFAULT;
PyBobLearnMiscIVectorMachine_Type.tp_doc = IVectorMachine_doc.doc();
// set the functions
PyBobLearnMiscIVectorMachine_Type.tp_new = PyType_GenericNew;
PyBobLearnMiscIVectorMachine_Type.tp_init = reinterpret_cast<initproc>(PyBobLearnMiscIVectorMachine_init);
PyBobLearnMiscIVectorMachine_Type.tp_dealloc = reinterpret_cast<destructor>(PyBobLearnMiscIVectorMachine_delete);
PyBobLearnMiscIVectorMachine_Type.tp_richcompare = reinterpret_cast<richcmpfunc>(PyBobLearnMiscIVectorMachine_RichCompare);
PyBobLearnMiscIVectorMachine_Type.tp_methods = PyBobLearnMiscIVectorMachine_methods;
PyBobLearnMiscIVectorMachine_Type.tp_getset = PyBobLearnMiscIVectorMachine_getseters;
PyBobLearnMiscIVectorMachine_Type.tp_call = reinterpret_cast<ternaryfunc>(PyBobLearnMiscIVectorMachine_Forward);
// check that everything is fine
if (PyType_Ready(&PyBobLearnMiscIVectorMachine_Type) < 0) return false;
// add the type to the module
Py_INCREF(&PyBobLearnMiscIVectorMachine_Type);
return PyModule_AddObject(module, "IVectorMachine", (PyObject*)&PyBobLearnMiscIVectorMachine_Type) >= 0;
}
...@@ -84,6 +84,16 @@ static int PyBobLearnMiscJFABase_init_ubm(PyBobLearnMiscJFABaseObject* self, PyO ...@@ -84,6 +84,16 @@ static int PyBobLearnMiscJFABase_init_ubm(PyBobLearnMiscJFABaseObject* self, PyO
return -1; return -1;
} }
if(ru < 0){
PyErr_Format(PyExc_TypeError, "ru argument must be greater than or equal to one");
return -1;
}
if(rv < 0){
PyErr_Format(PyExc_TypeError, "rv argument must be greater than or equal to one");
return -1;
}
self->cxx.reset(new bob::learn::misc::JFABase(ubm->cxx, ru, rv)); self->cxx.reset(new bob::learn::misc::JFABase(ubm->cxx, ru, rv));
return 0; return 0;
} }
......
...@@ -52,7 +52,8 @@ static PyObject* create_module (void) { ...@@ -52,7 +52,8 @@ static PyObject* create_module (void) {
if (!init_BobLearnMiscISVBase(module)) return 0; if (!init_BobLearnMiscISVBase(module)) return 0;
if (!init_BobLearnMiscJFAMachine(module)) return 0; if (!init_BobLearnMiscJFAMachine(module)) return 0;
if (!init_BobLearnMiscISVMachine(module)) return 0; if (!init_BobLearnMiscISVMachine(module)) return 0;
if (!init_BobLearnMiscIVectorMachine(module)) return 0;
static void* PyBobLearnMisc_API[PyBobLearnMisc_API_pointers]; static void* PyBobLearnMisc_API[PyBobLearnMisc_API_pointers];
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <bob.learn.misc/JFAMachine.h> #include <bob.learn.misc/JFAMachine.h>
#include <bob.learn.misc/ISVMachine.h> #include <bob.learn.misc/ISVMachine.h>
#include <bob.learn.misc/IVectorMachine.h>
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
...@@ -204,5 +205,16 @@ bool init_BobLearnMiscISVMachine(PyObject* module); ...@@ -204,5 +205,16 @@ bool init_BobLearnMiscISVMachine(PyObject* module);
int PyBobLearnMiscISVMachine_Check(PyObject* o); int PyBobLearnMiscISVMachine_Check(PyObject* o);
// IVectorMachine
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::learn::misc::IVectorMachine> cxx;
} PyBobLearnMiscIVectorMachineObject;
extern PyTypeObject PyBobLearnMiscIVectorMachine_Type;
bool init_BobLearnMiscIVectorMachine(PyObject* module);
int PyBobLearnMiscIVectorMachine_Check(PyObject* o);
#endif // BOB_LEARN_EM_MAIN_H #endif // BOB_LEARN_EM_MAIN_H
...@@ -32,14 +32,15 @@ class IVectorMachinePy(): ...@@ -32,14 +32,15 @@ class IVectorMachinePy():
def resize(self): def resize(self):
if self.m_ubm: if self.m_ubm:
dim_cd = self.m_ubm.dim_c * self.m_ubm.dim_d dim_cd = self.m_ubm.shape[0] * self.m_ubm.shape[1]
self.m_t = numpy.random.randn(dim_cd, self.m_dim_t) self.m_t = numpy.random.randn(dim_cd, self.m_dim_t)
self.m_sigma = numpy.random.randn(dim_cd) self.m_sigma = numpy.random.randn(dim_cd)
def precompute(self): def precompute(self):
if self.m_ubm and self.m_t is not None and self.m_sigma is not None: if self.m_ubm and self.m_t is not None and self.m_sigma is not None:
dim_c = self.m_ubm.dim_c #dim_c = self.m_ubm.dim_c
dim_d = self.m_ubm.dim_d #dim_d = self.m_ubm.dim_d
dim_c,dim_d = self.m_ubm.shape
self.m_cache_TtSigmaInv = {} self.m_cache_TtSigmaInv = {}
self.m_cache_TtSigmaInvT = {} self.m_cache_TtSigmaInvT = {}
for c in range(dim_c): for c in range(dim_c):
...@@ -78,13 +79,14 @@ class IVectorMachinePy(): ...@@ -78,13 +79,14 @@ class IVectorMachinePy():
def _get_TtSigmaInv_Fnorm(self, N, F): def _get_TtSigmaInv_Fnorm(self, N, F):
# Initialization # Initialization
dim_c = self.m_ubm.dim_c #dim_c = self.m_ubm.dim_c
dim_d = self.m_ubm.dim_d #dim_d = self.m_ubm.dim_d
dim_c,dim_d = self.m_ubm.shape
mean_supervector = self.m_ubm.mean_supervector mean_supervector = self.m_ubm.mean_supervector
TtSigmaInv_Fnorm = numpy.zeros(shape=(self.m_dim_t,), dtype=numpy.float64) TtSigmaInv_Fnorm = numpy.zeros(shape=(self.m_dim_t,), dtype=numpy.float64)
# Loop over each Gaussian component # Loop over each Gaussian component
dim_c = self.m_ubm.dim_c dim_c = self.m_ubm.shape[0]
for c in range(dim_c): for c in range(dim_c):
start = c*dim_d start = c*dim_d
end = (c+1)*dim_d end = (c+1)*dim_d
...@@ -94,8 +96,9 @@ class IVectorMachinePy(): ...@@ -94,8 +96,9 @@ class IVectorMachinePy():
def _get_I_TtSigmaInvNT(self, N): def _get_I_TtSigmaInvNT(self, N):
# Initialization # Initialization
dim_c = self.m_ubm.dim_c #dim_c = self.m_ubm.dim_c
dim_d = self.m_ubm.dim_d #dim_d = self.m_ubm.dim_d
dim_c, dim_d = self.m_ubm.shape
TtSigmaInvNT = numpy.eye(self.m_dim_t, dtype=numpy.float64) TtSigmaInvNT = numpy.eye(self.m_dim_t, dtype=numpy.float64)
for c in range(dim_c): for c in range(dim_c):
...@@ -152,5 +155,5 @@ def test_machine(): ...@@ -152,5 +155,5 @@ def test_machine():
mc.sigma = sigma mc.sigma = sigma
wij_ref = numpy.array([-0.04213415, 0.21463343]) # Reference from original Chris implementation wij_ref = numpy.array([-0.04213415, 0.21463343]) # Reference from original Chris implementation
wij = mc.forward(gs) wij = mc(gs)
assert numpy.allclose(wij_ref, wij, 1e-5) assert numpy.allclose(wij_ref, wij, 1e-5)
...@@ -30,6 +30,7 @@ References ...@@ -30,6 +30,7 @@ References
.. [Reynolds2000] *Reynolds, Douglas A., Thomas F. Quatieri, and Robert B. Dunn*. **Speaker Verification Using Adapted Gaussian Mixture Models**, Digital signal processing 10.1 (2000): 19-41. .. [Reynolds2000] *Reynolds, Douglas A., Thomas F. Quatieri, and Robert B. Dunn*. **Speaker Verification Using Adapted Gaussian Mixture Models**, Digital signal processing 10.1 (2000): 19-41.
.. [Vogt2008] *R. Vogt, S. Sridharan*. **'Explicit Modelling of Session Variability for Speaker Verification'**, Computer Speech & Language, 2008, vol. 22, no. 1, pp. 17-38 .. [Vogt2008] *R. Vogt, S. Sridharan*. **'Explicit Modelling of Session Variability for Speaker Verification'**, Computer Speech & Language, 2008, vol. 22, no. 1, pp. 17-38
.. [McCool2013] *C. McCool, R. Wallace, M. McLaren, L. El Shafey, S. Marcel*. **'Session Variability Modelling for Face Authentication'**, IET Biometrics, 2013 .. [McCool2013] *C. McCool, R. Wallace, M. McLaren, L. El Shafey, S. Marcel*. **'Session Variability Modelling for Face Authentication'**, IET Biometrics, 2013
.. [Dehak2010] *N. Dehak, P. Kenny, R. Dehak, P. Dumouchel, P. Ouellet*, **'Front End Factor Analysis for Speaker Verification'**, IEEE Transactions on Audio, Speech and Language Processing, 2010, vol. 19, issue 4, pp. 788-798
Indices and tables Indices and tables
......
...@@ -57,7 +57,7 @@ setup( ...@@ -57,7 +57,7 @@ setup(
"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",
#"bob/learn/misc/cpp/IVectorMachine.cpp", "bob/learn/misc/cpp/IVectorMachine.cpp",
"bob/learn/misc/cpp/KMeansMachine.cpp", "bob/learn/misc/cpp/KMeansMachine.cpp",
"bob/learn/misc/cpp/LinearScoring.cpp", "bob/learn/misc/cpp/LinearScoring.cpp",
#"bob/learn/misc/cpp/PLDAMachine.cpp", #"bob/learn/misc/cpp/PLDAMachine.cpp",
...@@ -117,6 +117,8 @@ setup( ...@@ -117,6 +117,8 @@ setup(
"bob/learn/misc/isv_base.cpp", "bob/learn/misc/isv_base.cpp",
"bob/learn/misc/jfa_machine.cpp", "bob/learn/misc/jfa_machine.cpp",
"bob/learn/misc/isv_machine.cpp", "bob/learn/misc/isv_machine.cpp",
"bob/learn/misc/ivector_machine.cpp",
"bob/learn/misc/main.cpp", "bob/learn/misc/main.cpp",
], ],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment