diff --git a/bob/learn/misc/cpp/KMeansTrainer.cpp b/bob/learn/misc/cpp/KMeansTrainer.cpp index 583543f7bbc1b249a435cc3242fabbf14c251e84..cbc2e2a2a3741a5f5bf49a0f9e2e8dda2066c8c6 100644 --- a/bob/learn/misc/cpp/KMeansTrainer.cpp +++ b/bob/learn/misc/cpp/KMeansTrainer.cpp @@ -8,9 +8,10 @@ #include <bob.learn.misc/KMeansTrainer.h> #include <bob.core/array_copy.h> -#include <bob.core/random.h> #include <boost/random.hpp> +#include <bob.core/random.h> + /* bob::learn::misc::KMeansTrainer::KMeansTrainer(double convergence_threshold, @@ -30,15 +31,13 @@ bob::learn::misc::KMeansTrainer::KMeansTrainer(double convergence_threshold, } */ -bob::learn::misc::KMeansTrainer::KMeansTrainer(InitializationMethod i_m) +bob::learn::misc::KMeansTrainer::KMeansTrainer(InitializationMethod i_m): +m_rng(new boost::mt19937()), +m_zeroethOrderStats(0), +m_firstOrderStats(0), +m_average_min_distance(0) { - m_initialization_method = i_m; - m_zeroethOrderStats = 0; - m_firstOrderStats = 0; - m_average_min_distance = 0; - - //m_rng(new boost::mt19937()); } @@ -218,8 +217,7 @@ void bob::learn::misc::KMeansTrainer::eStep(bob::learn::misc::KMeansMachine& kme m_average_min_distance /= static_cast<double>(ar.extent(0)); } -void bob::learn::misc::KMeansTrainer::mStep(bob::learn::misc::KMeansMachine& kmeans, - const blitz::Array<double,2>&) +void bob::learn::misc::KMeansTrainer::mStep(bob::learn::misc::KMeansMachine& kmeans) { blitz::Array<double,2>& means = kmeans.updateMeans(); for(size_t i=0; i<kmeans.getNMeans(); ++i) diff --git a/bob/learn/misc/include/bob.learn.misc/KMeansTrainer.h b/bob/learn/misc/include/bob.learn.misc/KMeansTrainer.h index caba9f64a1c2df62f7f71d344cdaa280d9af152b..fcf394cd0f8eded29a9a5773646f59ca0bb22655 100644 --- a/bob/learn/misc/include/bob.learn.misc/KMeansTrainer.h +++ b/bob/learn/misc/include/bob.learn.misc/KMeansTrainer.h @@ -104,8 +104,7 @@ class KMeansTrainer /** * @brief Updates the mean based on the statistics from the E-step. */ - void mStep(bob::learn::misc::KMeansMachine& kmeans, - const blitz::Array<double,2>&); + void mStep(bob::learn::misc::KMeansMachine& kmeans); /** * @brief This functions returns the average min (Square Euclidean) diff --git a/bob/learn/misc/kmeans_machine.cpp b/bob/learn/misc/kmeans_machine.cpp index 39e467d4f3ccacd990727491784be44278c6a57b..436bb9ad7a0bb26c6f9a76b76123e574a2e073a0 100644 --- a/bob/learn/misc/kmeans_machine.cpp +++ b/bob/learn/misc/kmeans_machine.cpp @@ -24,7 +24,7 @@ static auto KMeansMachine_doc = bob::extension::ClassDoc( "", true ) - .add_prototype("n_gaussians,n_inputs","") + .add_prototype("n_means,n_inputs","") .add_prototype("other","") .add_prototype("hdf5","") .add_prototype("","") diff --git a/bob/learn/misc/kmeans_trainer.cpp b/bob/learn/misc/kmeans_trainer.cpp index 8ce8bc3deab8f87ecdcf842222f64c64c995c3e8..7e13cd19f648c338bd890bbaf5de9cc10237fd09 100644 --- a/bob/learn/misc/kmeans_trainer.cpp +++ b/bob/learn/misc/kmeans_trainer.cpp @@ -13,6 +13,18 @@ /************ Constructor Section *********************************/ /******************************************************************/ +// InitializationMethod type conversion +static const std::map<std::string, bob::learn::misc::KMeansTrainer::InitializationMethod> IM = {{"random", bob::learn::misc::KMeansTrainer::InitializationMethod::RANDOM}, {"random_no_duplicate", bob::learn::misc::KMeansTrainer::InitializationMethod::RANDOM_NO_DUPLICATE}, {"kmeans_plus_plus", bob::learn::misc::KMeansTrainer::InitializationMethod::KMEANS_PLUS_PLUS}}; +static inline bob::learn::misc::KMeansTrainer::InitializationMethod string2IM(const std::string& o){ /* converts string to InitializationMethod type */ + auto it = IM.find(o); + if (it == IM.end()) throw std::runtime_error("The given InitializationMethod '" + o + "' is not known; choose one of ('random', 'random_no_duplicate', 'kmeans_plus_plus')"); + else return it->second; +} +static inline const std::string& IM2string(bob::learn::misc::KMeansTrainer::InitializationMethod o){ /* converts InitializationMethod type to string */ + for (auto it = IM.begin(); it != IM.end(); ++it) if (it->second == o) return it->first; + throw std::runtime_error("The given InitializationMethod type is not known"); +} + static auto KMeansTrainer_doc = bob::extension::ClassDoc( BOB_EXT_MODULE_PREFIX ".KMeansTrainer", @@ -31,7 +43,7 @@ static auto KMeansTrainer_doc = bob::extension::ClassDoc( .add_prototype("other","") .add_prototype("","") - .add_parameter("initialization_method", ":py:class:`bob.learn.misc.KMeansTrainer.getInitializationMethod`", "The initialization method of the means") + .add_parameter("initialization_method", "str", "The initialization method of the means") .add_parameter("other", ":py:class:`bob.learn.misc.KMeansTrainer`", "A KMeansTrainer object to be copied.") ); @@ -50,13 +62,54 @@ static int PyBobLearnMiscKMeansTrainer_init_copy(PyBobLearnMiscKMeansTrainerObje return 0; } +static int PyBobLearnMiscKMeansTrainer_init_str(PyBobLearnMiscKMeansTrainerObject* self, PyObject* args, PyObject* kwargs) { + + char** kwlist = KMeansTrainer_doc.kwlist(0); + char* value; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &value)){ + KMeansTrainer_doc.print_usage(); + return -1; + } + self->cxx.reset(new bob::learn::misc::KMeansTrainer(string2IM(std::string(value)))); + return 0; +} + static int PyBobLearnMiscKMeansTrainer_init(PyBobLearnMiscKMeansTrainerObject* 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); - + int nargs = (args?PyTuple_Size(args):0) + (kwargs?PyDict_Size(kwargs):0); + + switch (nargs) { + + case 0:{ //default initializer () + self->cxx.reset(new bob::learn::misc::KMeansTrainer()); + return 0; + } + case 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 KMeansTrainer object + if (PyBobLearnMiscKMeansTrainer_Check(arg)) + return PyBobLearnMiscKMeansTrainer_init_copy(self, args, kwargs); + else if(PyString_Check(arg)) + return PyBobLearnMiscKMeansTrainer_init_str(self, args, kwargs); + //return PyBobLearnMiscKMeansTrainer_init_str(self, arg); + } + default:{ + PyErr_Format(PyExc_RuntimeError, "number of arguments mismatch - %s requires 0 or 1 arguments, but you provided %d (see help)", Py_TYPE(self)->tp_name, nargs); + KMeansTrainer_doc.print_usage(); + return -1; + } + } BOB_CATCH_MEMBER("cannot create KMeansTrainer", 0) return 0; } @@ -72,12 +125,213 @@ int PyBobLearnMiscKMeansTrainer_Check(PyObject* o) { return PyObject_IsInstance(o, reinterpret_cast<PyObject*>(&PyBobLearnMiscKMeansTrainer_Type)); } + +static PyObject* PyBobLearnMiscKMeansTrainer_RichCompare(PyBobLearnMiscKMeansTrainerObject* self, PyObject* other, int op) { + BOB_TRY + + if (!PyBobLearnMiscKMeansTrainer_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<PyBobLearnMiscKMeansTrainerObject*>(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 KMeansTrainer objects", 0) +} + + /******************************************************************/ /************ Variables Section ***********************************/ /******************************************************************/ +/***** initialization_method *****/ +static auto initialization_method = bob::extension::VariableDoc( + "initialization_method", + "str", + "Initialization method.", + "" +); +PyObject* PyBobLearnMiscKMeansTrainer_getInitializationMethod(PyBobLearnMiscKMeansTrainerObject* self, void*) { + BOB_TRY + return Py_BuildValue("s", IM2string(self->cxx->getInitializationMethod()).c_str()); + BOB_CATCH_MEMBER("initialization method could not be read", 0) +} +int PyBobLearnMiscKMeansTrainer_setInitializationMethod(PyBobLearnMiscKMeansTrainerObject* self, PyObject* value, void*) { + BOB_TRY + + if (!PyString_Check(value)){ + PyErr_Format(PyExc_RuntimeError, "%s %s expects an str", Py_TYPE(self)->tp_name, initialization_method.name()); + return -1; + } + self->cxx->setInitializationMethod(string2IM(PyString_AS_STRING(value))); + + return 0; + BOB_CATCH_MEMBER("initialization method could not be set", 0) +} + + +/***** zeroeth_order_statistics *****/ +static auto zeroeth_order_statistics = bob::extension::VariableDoc( + "zeroeth_order_statistics", + "array_like <float, 1D>", + "Returns the internal statistics. Useful to parallelize the E-step", + "" +); +PyObject* PyBobLearnMiscKMeansTrainer_getZeroethOrderStatistics(PyBobLearnMiscKMeansTrainerObject* self, void*){ + BOB_TRY + return PyBlitzArrayCxx_AsConstNumpy(self->cxx->getZeroethOrderStats()); + BOB_CATCH_MEMBER("zeroeth_order_statistics could not be read", 0) +} +int PyBobLearnMiscKMeansTrainer_setZeroethOrderStatistics(PyBobLearnMiscKMeansTrainerObject* 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, zeroeth_order_statistics.name()); + return -1; + } + auto o_ = make_safe(o); + auto b = PyBlitzArrayCxx_AsBlitz<double,1>(o, "zeroeth_order_statistics"); + if (!b) return -1; + self->cxx->setZeroethOrderStats(*b); + return 0; + BOB_CATCH_MEMBER("zeroeth_order_statistics could not be set", -1) +} + + +/***** first_order_statistics *****/ +static auto first_order_statistics = bob::extension::VariableDoc( + "first_order_statistics", + "array_like <float, 2D>", + "Returns the internal statistics. Useful to parallelize the E-step", + "" +); +PyObject* PyBobLearnMiscKMeansTrainer_getFirstOrderStatistics(PyBobLearnMiscKMeansTrainerObject* self, void*){ + BOB_TRY + return PyBlitzArrayCxx_AsConstNumpy(self->cxx->getFirstOrderStats()); + BOB_CATCH_MEMBER("first_order_statistics could not be read", 0) +} +int PyBobLearnMiscKMeansTrainer_setFirstOrderStatistics(PyBobLearnMiscKMeansTrainerObject* 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, first_order_statistics.name()); + return -1; + } + auto o_ = make_safe(o); + auto b = PyBlitzArrayCxx_AsBlitz<double,2>(o, "first_order_statistics"); + if (!b) return -1; + self->cxx->setFirstOrderStats(*b); + return 0; + BOB_CATCH_MEMBER("first_order_statistics could not be set", -1) +} + + +/***** average_min_distance *****/ +static auto average_min_distance = bob::extension::VariableDoc( + "average_min_distance", + "str", + "Average min (square Euclidean) distance. Useful to parallelize the E-step.", + "" +); +PyObject* PyBobLearnMiscKMeansTrainer_getAverageMinDistance(PyBobLearnMiscKMeansTrainerObject* self, void*) { + BOB_TRY + return Py_BuildValue("d", self->cxx->getAverageMinDistance()); + BOB_CATCH_MEMBER("Average Min Distance method could not be read", 0) +} +int PyBobLearnMiscKMeansTrainer_setAverageMinDistance(PyBobLearnMiscKMeansTrainerObject* self, PyObject* value, void*) { + BOB_TRY + + if (!PyNumber_Check(value)){ + PyErr_Format(PyExc_RuntimeError, "%s %s expects an double", Py_TYPE(self)->tp_name, average_min_distance.name()); + return -1; + } + self->cxx->setAverageMinDistance(PyFloat_AS_DOUBLE(value)); + + return 0; + BOB_CATCH_MEMBER("Average Min Distance could not be set", 0) +} + + + +/***** rng *****/ +static auto rng = bob::extension::VariableDoc( + "rng", + "str", + "The Mersenne Twister mt19937 random generator used for the initialization of subspaces/arrays before the EM loop.", + "" +); +PyObject* PyBobLearnMiscKMeansTrainer_getRng(PyBobLearnMiscKMeansTrainerObject* self, void*) { + BOB_TRY + //Allocating the correspondent python object + + PyBoostMt19937Object* retval = + (PyBoostMt19937Object*)PyBoostMt19937_Type.tp_alloc(&PyBoostMt19937_Type, 0); + + retval->rng = self->cxx->getRng().get(); + return Py_BuildValue("O", retval); + BOB_CATCH_MEMBER("Rng method could not be read", 0) +} +int PyBobLearnMiscKMeansTrainer_setRng(PyBobLearnMiscKMeansTrainerObject* self, PyObject* value, void*) { + BOB_TRY + + if (!PyBoostMt19937_Check(value)){ + PyErr_Format(PyExc_RuntimeError, "%s %s expects an PyBoostMt19937_Check", Py_TYPE(self)->tp_name, average_min_distance.name()); + return -1; + } + + PyBoostMt19937Object* boostObject = 0; + PyBoostMt19937_Converter(value, &boostObject); + self->cxx->setRng((boost::shared_ptr<boost::mt19937>)boostObject->rng); + + return 0; + BOB_CATCH_MEMBER("Rng could not be set", 0) +} + + static PyGetSetDef PyBobLearnMiscKMeansTrainer_getseters[] = { + { + initialization_method.name(), + (getter)PyBobLearnMiscKMeansTrainer_getInitializationMethod, + (setter)PyBobLearnMiscKMeansTrainer_setInitializationMethod, + initialization_method.doc(), + 0 + }, + { + zeroeth_order_statistics.name(), + (getter)PyBobLearnMiscKMeansTrainer_getZeroethOrderStatistics, + (setter)PyBobLearnMiscKMeansTrainer_setZeroethOrderStatistics, + zeroeth_order_statistics.doc(), + 0 + }, + { + first_order_statistics.name(), + (getter)PyBobLearnMiscKMeansTrainer_getFirstOrderStatistics, + (setter)PyBobLearnMiscKMeansTrainer_setFirstOrderStatistics, + first_order_statistics.doc(), + 0 + }, + { + average_min_distance.name(), + (getter)PyBobLearnMiscKMeansTrainer_getAverageMinDistance, + (setter)PyBobLearnMiscKMeansTrainer_setAverageMinDistance, + average_min_distance.doc(), + 0 + }, + { + rng.name(), + (getter)PyBobLearnMiscKMeansTrainer_getRng, + 0, + rng.doc(), + 0 + }, {0} // Sentinel }; @@ -86,10 +340,226 @@ static PyGetSetDef PyBobLearnMiscKMeansTrainer_getseters[] = { /************ Functions Section ***********************************/ /******************************************************************/ +/*** initialize ***/ +static auto initialize = bob::extension::FunctionDoc( + "initialize", + "Initialise the means randomly", + "Data is split into as many chunks as there are means, then each mean is set to a random example within each chunk.", + true +) +.add_prototype("kmeans_machine,data") +.add_parameter("kmeans_machine", ":py:class:`bob.learn.misc.KMeansMachine`", "KMeansMachine Object") +.add_parameter("data", "array_like <float, 2D>", "Input data"); +static PyObject* PyBobLearnMiscKMeansTrainer_initialize(PyBobLearnMiscKMeansTrainerObject* self, PyObject* args, PyObject* kwargs) { + BOB_TRY + + /* Parses input arguments in a single shot */ + char** kwlist = initialize.kwlist(0); + + PyBobLearnMiscKMeansMachineObject* kmeans_machine = 0; + PyBlitzArrayObject* data = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O&", kwlist, &PyBobLearnMiscKMeansMachine_Type, &kmeans_machine, + &PyBlitzArray_Converter, &data)) Py_RETURN_NONE; + auto data_ = make_safe(data); + + self->cxx->initialize(*kmeans_machine->cxx, *PyBlitzArrayCxx_AsBlitz<double,2>(data)); + + BOB_CATCH_MEMBER("cannot perform the initialize method", 0) + + Py_RETURN_NONE; +} + + +/*** eStep ***/ +static auto eStep = bob::extension::FunctionDoc( + "eStep", + "Compute the eStep, which is basically the distances ", + "Accumulate across the dataset:" + " -zeroeth and first order statistics" + " -average (Square Euclidean) distance from the closest mean", + true +) +.add_prototype("kmeans_machine,data") +.add_parameter("kmeans_machine", ":py:class:`bob.learn.misc.KMeansMachine`", "KMeansMachine Object") +.add_parameter("data", "array_like <float, 2D>", "Input data"); +static PyObject* PyBobLearnMiscKMeansTrainer_eStep(PyBobLearnMiscKMeansTrainerObject* self, PyObject* args, PyObject* kwargs) { + BOB_TRY + + /* Parses input arguments in a single shot */ + char** kwlist = eStep.kwlist(0); + + PyBobLearnMiscKMeansMachineObject* kmeans_machine; + PyBlitzArrayObject* data = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O&", kwlist, &PyBobLearnMiscKMeansMachine_Type, &kmeans_machine, + &PyBlitzArray_Converter, &data)) Py_RETURN_NONE; + auto data_ = make_safe(data); + + self->cxx->eStep(*kmeans_machine->cxx, *PyBlitzArrayCxx_AsBlitz<double,2>(data)); + + + BOB_CATCH_MEMBER("cannot perform the eStep method", 0) + + Py_RETURN_NONE; +} + + +/*** mStep ***/ +static auto mStep = bob::extension::FunctionDoc( + "mStep", + "Updates the mean based on the statistics from the E-step", + 0, + true +) +.add_prototype("kmeans_machine") +.add_parameter("kmeans_machine", ":py:class:`bob.learn.misc.KMeansMachine`", "KMeansMachine Object"); +static PyObject* PyBobLearnMiscKMeansTrainer_mStep(PyBobLearnMiscKMeansTrainerObject* self, PyObject* args, PyObject* kwargs) { + BOB_TRY + + /* Parses input arguments in a single shot */ + char** kwlist = mStep.kwlist(0); + + PyBobLearnMiscKMeansMachineObject* kmeans_machine; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &PyBobLearnMiscKMeansMachine_Type, &kmeans_machine)) Py_RETURN_NONE; + + self->cxx->mStep(*kmeans_machine->cxx); + + BOB_CATCH_MEMBER("cannot perform the mStep method", 0) + + Py_RETURN_NONE; +} + + +/*** computeLikelihood ***/ +static auto compute_likelihood = bob::extension::FunctionDoc( + "compute_likelihood", + "This functions returns the average min (Square Euclidean) distance (average distance to the closest mean)", + 0, + true +) +.add_prototype("kmeans_machine") +.add_parameter("kmeans_machine", ":py:class:`bob.learn.misc.KMeansMachine`", "KMeansMachine Object"); +static PyObject* PyBobLearnMiscKMeansTrainer_compute_likelihood(PyBobLearnMiscKMeansTrainerObject* self, PyObject* args, PyObject* kwargs) { + BOB_TRY + + /* Parses input arguments in a single shot */ + char** kwlist = compute_likelihood.kwlist(0); + + PyBobLearnMiscKMeansMachineObject* kmeans_machine; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &PyBobLearnMiscKMeansMachine_Type, &kmeans_machine)) Py_RETURN_NONE; + + double value = self->cxx->computeLikelihood(*kmeans_machine->cxx); + return Py_BuildValue("d", value); + + BOB_CATCH_MEMBER("cannot perform the computeLikelihood method", 0) +} + + +/*** reset_accumulators ***/ +static auto reset_accumulators = bob::extension::FunctionDoc( + "reset_accumulators", + "Reset the statistics accumulators to the correct size and a value of zero.", + 0, + true +) +.add_prototype("kmeans_machine") +.add_parameter("kmeans_machine", ":py:class:`bob.learn.misc.KMeansMachine`", "KMeansMachine Object"); +static PyObject* PyBobLearnMiscKMeansTrainer_reset_accumulators(PyBobLearnMiscKMeansTrainerObject* self, PyObject* args, PyObject* kwargs) { + BOB_TRY + + /* Parses input arguments in a single shot */ + char** kwlist = reset_accumulators.kwlist(0); + + PyBobLearnMiscKMeansMachineObject* kmeans_machine; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &PyBobLearnMiscKMeansMachine_Type, &kmeans_machine)) Py_RETURN_NONE; + + bool value = self->cxx->resetAccumulators(*kmeans_machine->cxx); + return Py_BuildValue("b", value); + + BOB_CATCH_MEMBER("cannot perform the reset_accumulators method", 0) +} + + +/*** is_similar_to ***/ +/* +static auto is_similar_to = bob::extension::FunctionDoc( + "is_similar_to", + + "Compares this KMeansTrainer 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 trainer." +) +.add_prototype("other, [r_epsilon], [a_epsilon]","output") +.add_parameter("other", ":py:class:`bob.learn.misc.KMeansTrainer`", "A KMeansMachine 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* PyBobLearnMiscKMeansTrainer_IsSimilarTo(PyBobLearnMiscKMeansTrainerObject* self, PyObject* args, PyObject* kwds) { + + // Parses input arguments in a single shot + char** kwlist = is_similar_to.kwlist(0); + + //PyObject* other = 0; + PyBobLearnMiscKMeansTrainerObject* other = 0; + double r_epsilon = 1.e-5; + double a_epsilon = 1.e-8; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|dd", kwlist, + &PyBobLearnMiscKMeansTrainer_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; +} +*/ static PyMethodDef PyBobLearnMiscKMeansTrainer_methods[] = { + { + initialize.name(), + (PyCFunction)PyBobLearnMiscKMeansTrainer_initialize, + METH_VARARGS|METH_KEYWORDS, + initialize.doc() + }, + { + eStep.name(), + (PyCFunction)PyBobLearnMiscKMeansTrainer_eStep, + METH_VARARGS|METH_KEYWORDS, + eStep.doc() + }, + { + mStep.name(), + (PyCFunction)PyBobLearnMiscKMeansTrainer_mStep, + METH_VARARGS|METH_KEYWORDS, + mStep.doc() + }, + { + compute_likelihood.name(), + (PyCFunction)PyBobLearnMiscKMeansTrainer_compute_likelihood, + METH_VARARGS|METH_KEYWORDS, + compute_likelihood.doc() + }, + { + reset_accumulators.name(), + (PyCFunction)PyBobLearnMiscKMeansTrainer_reset_accumulators, + METH_VARARGS|METH_KEYWORDS, + reset_accumulators.doc() + }, +/* + { + is_similar_to.name(), + (PyCFunction)PyBobLearnMiscKMeansTrainer_IsSimilarTo, + METH_VARARGS|METH_KEYWORDS, + is_similar_to.doc() + }, +*/ {0} /* Sentinel */ }; @@ -116,10 +586,10 @@ bool init_BobLearnMiscKMeansTrainer(PyObject* module) PyBobLearnMiscKMeansTrainer_Type.tp_new = PyType_GenericNew; PyBobLearnMiscKMeansTrainer_Type.tp_init = reinterpret_cast<initproc>(PyBobLearnMiscKMeansTrainer_init); PyBobLearnMiscKMeansTrainer_Type.tp_dealloc = reinterpret_cast<destructor>(PyBobLearnMiscKMeansTrainer_delete); - //PyBobLearnMiscKMeansTrainer_Type.tp_richcompare = reinterpret_cast<richcmpfunc>(PyBobLearnMiscKMeansTrainer_RichCompare); + PyBobLearnMiscKMeansTrainer_Type.tp_richcompare = reinterpret_cast<richcmpfunc>(PyBobLearnMiscKMeansTrainer_RichCompare); PyBobLearnMiscKMeansTrainer_Type.tp_methods = PyBobLearnMiscKMeansTrainer_methods; PyBobLearnMiscKMeansTrainer_Type.tp_getset = PyBobLearnMiscKMeansTrainer_getseters; - //PyBobLearnMiscGMMMachine_Type.tp_call = reinterpret_cast<ternaryfunc>(PyBobLearnMiscGMMMachine_loglikelihood); + PyBobLearnMiscGMMMachine_Type.tp_call = reinterpret_cast<ternaryfunc>(PyBobLearnMiscKMeansTrainer_compute_likelihood); // check that everything is fine