vector<ArrayXXb> PyArray_ToArraysXXb(PyObject* array) { if(PyArray_DESCR(array)->type != PyArray_DescrFromType(NPY_BOOL)->type) throw Exception("Can only handle arrays of bool values."); if(PyArray_NDIM(array) == 3) { vector<ArrayXXb> channels; if(PyArray_FLAGS(array) & NPY_F_CONTIGUOUS) for(int m = 0; m < PyArray_DIM(array, 2); ++m) channels.push_back(Matrix<bool, Dynamic, Dynamic, ColMajor>( PyArray_DIM(array, 0), PyArray_DIM(array, 1))); else if(PyArray_FLAGS(array) & NPY_C_CONTIGUOUS) for(int m = 0; m < PyArray_DIM(array, 2); ++m) channels.push_back(Matrix<bool, Dynamic, Dynamic, RowMajor>( PyArray_DIM(array, 0), PyArray_DIM(array, 1))); else throw Exception("Data must be stored in contiguous memory."); bool* data = reinterpret_cast<bool*>(PyArray_DATA(array)); for(int m = 0; m < channels.size(); ++m) for(int i = 0; i < channels[m].size(); ++i) channels[m].data()[i] = data[m * channels[m].size() + i]; return channels; } else { throw Exception("Can only handle three-dimensional arrays."); } }
bool CallbackInterface::operator()(int iter, const Trainable& cd) { CDObject* cdObj = reinterpret_cast<CDObject*>(CD_new(mType, 0, 0)); // TODO: fix this hack cdObj->cd = const_cast<Trainable*>(&cd); cdObj->owner = false; // call Python object PyObject* args = Py_BuildValue("(iO)", iter, cdObj); PyObject* result = PyObject_CallObject(mCallback, args); Py_DECREF(args); // if cont is false, training will be aborted bool cont = true; if(result) { if(PyBool_Check(result)) cont = (result == Py_True); Py_DECREF(result); Py_DECREF(cdObj); } else { Py_DECREF(cdObj); throw Exception("Some error occured during call to callback function."); } return cont; }
PyObject* MixtureComponent_train(MixtureComponentObject* self, PyObject* args, PyObject* kwds) { const char* kwlist[] = {"data", "weights", "parameters", 0}; PyObject* data; PyObject* weights = 0; PyObject* parameters = 0; // read arguments if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", const_cast<char**>(kwlist), &data, &weights, ¶meters)) return 0; if(weights == Py_None) weights = 0; // make sure data is stored in NumPy array data = PyArray_FROM_OTF(data, NPY_DOUBLE, NPY_F_CONTIGUOUS | NPY_ALIGNED); if(!data) { PyErr_SetString(PyExc_TypeError, "Data has to be stored in NumPy array."); return 0; } bool converged; try { Mixture::Component::Parameters* params = PyObject_ToMixtureComponentParameters(parameters); if(weights) { MatrixXd weightsMatrix = PyArray_ToMatrixXd(weights); MatrixXd dataMatrix = PyArray_ToMatrixXd(data); if(weightsMatrix.rows() != 1) weightsMatrix = weightsMatrix.transpose(); if(weightsMatrix.rows() != 1) throw Exception("Weights should be stored in a row vector."); converged = self->component->train(dataMatrix, weightsMatrix, *params); } else { converged = self->component->train(PyArray_ToMatrixXd(data), *params); } delete params; } catch(Exception exception) { Py_DECREF(data); PyErr_SetString(PyExc_RuntimeError, exception.message()); return 0; } Py_DECREF(data); if(converged) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } }
Trainable::Parameters* PyObject_ToMLRParameters(PyObject* parameters) { MLR::Parameters* params = dynamic_cast<MLR::Parameters*>( PyObject_ToParameters(parameters, new MLR::Parameters)); // read parameters from dictionary if(parameters && parameters != Py_None) { PyObject* callback = PyDict_GetItemString(parameters, "callback"); if(callback) if(PyCallable_Check(callback)) params->callback = new CallbackInterface(&MLR_type, callback); else if(callback != Py_None) throw Exception("callback should be a function or callable object."); PyObject* train_weights = PyDict_GetItemString(parameters, "train_weights"); if(train_weights) if(PyBool_Check(train_weights)) params->trainWeights = (train_weights == Py_True); else throw Exception("train_weights should be of type `bool`."); PyObject* train_biases = PyDict_GetItemString(parameters, "train_biases"); if(train_biases) if(PyBool_Check(train_biases)) params->trainBiases = (train_biases == Py_True); else throw Exception("train_biases should be of type `bool`."); PyObject* regularize_weights = PyDict_GetItemString(parameters, "regularize_weights"); if(regularize_weights) params->regularizeWeights = PyObject_ToRegularizer(regularize_weights); PyObject* regularize_biases = PyDict_GetItemString(parameters, "regularize_biases"); if(regularize_biases) params->regularizeBiases = PyObject_ToRegularizer(regularize_biases); } return params; }
MatrixXd PyArray_ToMatrixXd(PyObject* array) { if(PyArray_DESCR(array)->type != PyArray_DescrFromType(NPY_DOUBLE)->type) throw Exception("Can only handle arrays of double values."); if(PyArray_NDIM(array) == 1) { if(PyArray_FLAGS(array) & NPY_F_CONTIGUOUS) return Map<Matrix<double, Dynamic, Dynamic, ColMajor> >( reinterpret_cast<double*>(PyArray_DATA(array)), PyArray_DIM(array, 0), 1); else if(PyArray_FLAGS(array) & NPY_C_CONTIGUOUS) return Map<Matrix<double, Dynamic, Dynamic, RowMajor> >( reinterpret_cast<double*>(PyArray_DATA(array)), PyArray_DIM(array, 0), 1); else throw Exception("Data must be stored in contiguous memory."); } else if(PyArray_NDIM(array) == 2) { if(PyArray_FLAGS(array) & NPY_F_CONTIGUOUS) return Map<Matrix<double, Dynamic, Dynamic, ColMajor> >( reinterpret_cast<double*>(PyArray_DATA(array)), PyArray_DIM(array, 0), PyArray_DIM(array, 1)); else if(PyArray_FLAGS(array) & NPY_C_CONTIGUOUS) return Map<Matrix<double, Dynamic, Dynamic, RowMajor> >( reinterpret_cast<double*>(PyArray_DATA(array)), PyArray_DIM(array, 0), PyArray_DIM(array, 1)); else throw Exception("Data must be stored in contiguous memory."); } else { throw Exception("Can only handle one- and two-dimensional arrays."); } }
Tuples PyList_AsTuples(PyObject* list) { if(!PyList_Check(list)) throw Exception("Indices should be given in a list."); Tuples tuples; // convert list of tuples for(int i = 0; i < PyList_Size(list); ++i) { PyObject* tuple = PyList_GetItem(list, i); if(!PyTuple_Check(tuple) || PyTuple_Size(tuple) != 2) throw Exception("Indices should be stored in a list of 2-tuples."); int m, n; if(!PyArg_ParseTuple(tuple, "ii", &m, &n)) throw Exception("Indices should be integers."); tuples.push_back(make_pair(m, n)); } return tuples; }
Regularizer PyObject_ToRegularizer(PyObject* regularizer) { if(PyFloat_Check(regularizer)) return Regularizer(PyFloat_AsDouble(regularizer)); if(PyInt_Check(regularizer)) return Regularizer(static_cast<double>(PyInt_AsLong(regularizer))); if(PyDict_Check(regularizer)) { PyObject* r_strength = PyDict_GetItemString(regularizer, "strength"); PyObject* r_transform = PyDict_GetItemString(regularizer, "transform"); PyObject* r_norm = PyDict_GetItemString(regularizer, "norm"); if(r_transform == Py_None) r_transform = 0; Regularizer::Norm norm = Regularizer::L2; if(r_norm) { if(PyString_Size(r_norm) != 2) throw Exception("Regularizer norm should be 'L1' or 'L2'."); switch(PyString_AsString(r_norm)[1]) { default: throw Exception("Regularizer norm should be 'L1' or 'L2'."); case '1': norm = Regularizer::L1; break; case '2': norm = Regularizer::L2; break; } } double strength = r_transform ? 1. : 0.; if(r_strength) { if(PyInt_Check(r_strength)) { strength = static_cast<double>(PyInt_AsLong(r_strength)); } else { if(!PyFloat_Check(r_strength)) throw Exception("Regularizer strength should be of type `float`."); strength = PyFloat_AsDouble(r_strength); } } if(r_transform) { PyObject* matrix = PyArray_FROM_OTF(r_transform, NPY_DOUBLE, NPY_IN_ARRAY); if(!matrix) throw Exception("Regularizer transform should be of type `ndarray`."); return Regularizer(PyArray_ToMatrixXd(matrix), norm, strength); } else { return Regularizer(strength, norm); } } PyObject* matrix = PyArray_FROM_OTF(regularizer, NPY_DOUBLE, NPY_IN_ARRAY); if(matrix) return Regularizer(PyArray_ToMatrixXd(matrix)); throw Exception("Regularizer should be of type `dict`, `float` or `ndarray`."); }
Mixture::Component::Parameters* PyObject_ToMixtureComponentParameters(PyObject* parameters) { Mixture::Component::Parameters* params = new Mixture::Component::Parameters; if(parameters && parameters != Py_None) { PyObject* verbosity = PyDict_GetItemString(parameters, "verbosity"); if(verbosity) if(PyInt_Check(verbosity)) params->verbosity = PyInt_AsLong(verbosity); else if(PyFloat_Check(verbosity)) params->verbosity = static_cast<int>(PyFloat_AsDouble(verbosity)); else throw Exception("verbosity should be of type `int`."); PyObject* max_iter = PyDict_GetItemString(parameters, "max_iter"); if(max_iter) if(PyInt_Check(max_iter)) params->maxIter = PyInt_AsLong(max_iter); else if(PyFloat_Check(max_iter)) params->maxIter = static_cast<int>(PyFloat_AsDouble(max_iter)); else throw Exception("max_iter should be of type `int`."); PyObject* threshold = PyDict_GetItemString(parameters, "threshold"); if(threshold) if(PyFloat_Check(threshold)) params->threshold = PyFloat_AsDouble(threshold); else if(PyInt_Check(threshold)) params->threshold = static_cast<double>(PyFloat_AsDouble(threshold)); else throw Exception("threshold should be of type `float`."); PyObject* train_priors = PyDict_GetItemString(parameters, "train_priors"); if(train_priors) if(PyBool_Check(train_priors)) params->trainPriors = (train_priors == Py_True); else throw Exception("train_priors should be of type `bool`."); PyObject* train_covariance = PyDict_GetItemString(parameters, "train_covariance"); if(train_covariance) if(PyBool_Check(train_covariance)) params->trainCovariance = (train_covariance == Py_True); else throw Exception("train_covariance should be of type `bool`."); PyObject* train_scales = PyDict_GetItemString(parameters, "train_scales"); if(train_scales) if(PyBool_Check(train_scales)) params->trainScales = (train_scales == Py_True); else throw Exception("train_scales should be of type `bool`."); PyObject* train_mean = PyDict_GetItemString(parameters, "train_mean"); if(train_mean) if(PyBool_Check(train_mean)) params->trainMean = (train_mean == Py_True); else throw Exception("train_mean should be of type `bool`."); PyObject* regularize_priors = PyDict_GetItemString(parameters, "regularize_priors"); if(regularize_priors) if(PyFloat_Check(regularize_priors)) params->regularizePriors = PyFloat_AsDouble(regularize_priors); else if(PyInt_Check(regularize_priors)) params->regularizePriors = static_cast<double>(PyFloat_AsDouble(regularize_priors)); else throw Exception("regularize_priors should be of type `float`."); PyObject* regularize_covariance = PyDict_GetItemString(parameters, "regularize_covariance"); if(regularize_covariance) if(PyFloat_Check(regularize_covariance)) params->regularizeCovariance = PyFloat_AsDouble(regularize_covariance); else if(PyInt_Check(regularize_covariance)) params->regularizeCovariance = static_cast<double>(PyFloat_AsDouble(regularize_covariance)); else throw Exception("regularize_covariance should be of type `float`."); PyObject* regularize_scales = PyDict_GetItemString(parameters, "regularize_scales"); if(regularize_scales) if(PyFloat_Check(regularize_scales)) params->regularizeScales = PyFloat_AsDouble(regularize_scales); else if(PyInt_Check(regularize_scales)) params->regularizeScales = static_cast<double>(PyFloat_AsDouble(regularize_scales)); else throw Exception("regularize_scales should be of type `float`."); PyObject* regularize_mean = PyDict_GetItemString(parameters, "regularize_mean"); if(regularize_mean) if(PyFloat_Check(regularize_mean)) params->regularizeMean = PyFloat_AsDouble(regularize_mean); else if(PyInt_Check(regularize_mean)) params->regularizeMean = static_cast<double>(PyFloat_AsDouble(regularize_mean)); else throw Exception("regularize_mean should be of type `float`."); } return params; }
Mixture::Parameters* PyObject_ToMixtureParameters(PyObject* parameters) { Mixture::Parameters* params = new Mixture::Parameters; if(parameters && parameters != Py_None) { PyObject* verbosity = PyDict_GetItemString(parameters, "verbosity"); if(verbosity) if(PyInt_Check(verbosity)) params->verbosity = PyInt_AsLong(verbosity); else if(PyFloat_Check(verbosity)) params->verbosity = static_cast<int>(PyFloat_AsDouble(verbosity)); else throw Exception("verbosity should be of type `int`."); PyObject* max_iter = PyDict_GetItemString(parameters, "max_iter"); if(max_iter) if(PyInt_Check(max_iter)) params->maxIter = PyInt_AsLong(max_iter); else if(PyFloat_Check(max_iter)) params->maxIter = static_cast<int>(PyFloat_AsDouble(max_iter)); else throw Exception("max_iter should be of type `int`."); PyObject* threshold = PyDict_GetItemString(parameters, "threshold"); if(threshold) if(PyFloat_Check(threshold)) params->threshold = PyFloat_AsDouble(threshold); else if(PyInt_Check(threshold)) params->threshold = static_cast<double>(PyFloat_AsDouble(threshold)); else throw Exception("threshold should be of type `float`."); PyObject* val_iter = PyDict_GetItemString(parameters, "val_iter"); if(val_iter) if(PyInt_Check(val_iter)) params->valIter = PyInt_AsLong(val_iter); else if(PyFloat_Check(val_iter)) params->valIter = static_cast<int>(PyFloat_AsDouble(val_iter)); else throw Exception("val_iter should be of type `int`."); PyObject* val_look_ahead = PyDict_GetItemString(parameters, "val_look_ahead"); if(val_look_ahead) if(PyInt_Check(val_look_ahead)) params->valLookAhead = PyInt_AsLong(val_look_ahead); else if(PyFloat_Check(val_look_ahead)) params->valLookAhead = static_cast<int>(PyFloat_AsDouble(val_look_ahead)); else throw Exception("val_look_ahead should be of type `int`."); PyObject* initialize = PyDict_GetItemString(parameters, "initialize"); if(initialize) if(PyBool_Check(initialize)) params->initialize = (initialize == Py_True); else throw Exception("initialize should be of type `bool`."); PyObject* train_priors = PyDict_GetItemString(parameters, "train_priors"); if(train_priors) if(PyBool_Check(train_priors)) params->trainPriors = (train_priors == Py_True); else throw Exception("train_priors should be of type `bool`."); PyObject* train_components = PyDict_GetItemString(parameters, "train_components"); if(train_components) if(PyBool_Check(train_components)) params->trainComponents = (train_components == Py_True); else throw Exception("train_components should be of type `bool`."); PyObject* regularize_priors = PyDict_GetItemString(parameters, "regularize_priors"); if(regularize_priors) if(PyFloat_Check(regularize_priors)) params->regularizePriors = PyFloat_AsDouble(regularize_priors); else if(PyInt_Check(regularize_priors)) params->regularizePriors = static_cast<double>(PyFloat_AsDouble(regularize_priors)); else throw Exception("regularize_priors should be of type `float`."); } return params; }
Trainable::Parameters* PyObject_ToMCGSMParameters(PyObject* parameters) { MCGSM::Parameters* params = dynamic_cast<MCGSM::Parameters*>( PyObject_ToParameters(parameters, new MCGSM::Parameters)); // read parameters from dictionary if(parameters && parameters != Py_None) { PyObject* callback = PyDict_GetItemString(parameters, "callback"); if(callback) if(PyCallable_Check(callback)) params->callback = new CallbackInterface(&MCGSM_type, callback); else if(callback != Py_None) throw Exception("callback should be a function or callable object."); PyObject* train_priors = PyDict_GetItemString(parameters, "train_priors"); if(train_priors) if(PyBool_Check(train_priors)) params->trainPriors = (train_priors == Py_True); else throw Exception("train_priors should be of type `bool`."); PyObject* train_scales = PyDict_GetItemString(parameters, "train_scales"); if(train_scales) if(PyBool_Check(train_scales)) params->trainScales = (train_scales == Py_True); else throw Exception("train_scales should be of type `bool`."); PyObject* train_weights = PyDict_GetItemString(parameters, "train_weights"); if(train_weights) if(PyBool_Check(train_weights)) params->trainWeights = (train_weights == Py_True); else throw Exception("train_weights should be of type `bool`."); PyObject* train_features = PyDict_GetItemString(parameters, "train_features"); if(train_features) if(PyBool_Check(train_features)) params->trainFeatures = (train_features == Py_True); else throw Exception("train_features should be of type `bool`."); PyObject* train_cholesky_factors = PyDict_GetItemString(parameters, "train_cholesky_factors"); if(train_cholesky_factors) if(PyBool_Check(train_cholesky_factors)) params->trainCholeskyFactors = (train_cholesky_factors == Py_True); else throw Exception("train_cholesky_factors should be of type `bool`."); PyObject* train_predictors = PyDict_GetItemString(parameters, "train_predictors"); if(train_predictors) if(PyBool_Check(train_predictors)) params->trainPredictors = (train_predictors == Py_True); else throw Exception("train_predictors should be of type `bool`."); PyObject* train_linear_features = PyDict_GetItemString(parameters, "train_linear_features"); if(train_linear_features) if(PyBool_Check(train_linear_features)) params->trainLinearFeatures = (train_linear_features == Py_True); else throw Exception("train_linear_features should be of type `bool`."); PyObject* train_means = PyDict_GetItemString(parameters, "train_means"); if(train_means) if(PyBool_Check(train_means)) params->trainMeans = (train_means == Py_True); else throw Exception("train_means should be of type `bool`."); PyObject* regularize_features = PyDict_GetItemString(parameters, "regularize_features"); if(regularize_features) params->regularizeFeatures = PyObject_ToRegularizer(regularize_features); PyObject* regularize_predictors = PyDict_GetItemString(parameters, "regularize_predictors"); if(regularize_predictors) params->regularizePredictors = PyObject_ToRegularizer(regularize_predictors); PyObject* regularize_weights = PyDict_GetItemString(parameters, "regularize_weights"); if(regularize_weights) params->regularizeWeights = PyObject_ToRegularizer(regularize_weights); PyObject* regularize_linear_features = PyDict_GetItemString(parameters, "regularize_linear_features"); if(regularize_linear_features) params->regularizeLinearFeatures = PyObject_ToRegularizer(regularize_linear_features); PyObject* regularize_means = PyDict_GetItemString(parameters, "regularize_means"); if(regularize_means) params->regularizeMeans = PyObject_ToRegularizer(regularize_means); } return params; }