Skip to content
Snippets Groups Projects
Commit 815716d3 authored by Joseph Larralde's avatar Joseph Larralde
Browse files

add rapidXmmTools machine learning module

parent 62a6cc8d
Branches
Tags
No related merge requests found
#include "rapidXmmTools.h"
#include "trainingData.h"
#include "machineLearning.h"
static bool trainingData2xmmTrainingSet(const rapidmix::trainingData& data, xmm::TrainingSet& set) {
if (data.trainingSet.size() <= 1) {
// no recorded phrase (only default one)
return false;
}
if (data.trainingSet.size() > 1 && data.trainingSet[1].elements.size() == 0) {
// empty recorded phrase
return false;
}
rapidmix::trainingData::element el = data.trainingSet[1].elements[0];
int dimIn = static_cast<int>(el.input.size());
int dimOut = static_cast<int>(el.output.size());
// translate and return true if data and set are compatible
// don't translate and return false otherwise
if (dimOut > 0 != set.bimodal()) {
return false;
}
xmm::Phrase xp;
if (set.bimodal()) {
set.dimension.set(dimIn + dimOut);
set.dimension_input.set(dimIn);
xp = xmm::Phrase(xmm::MemoryMode::OwnMemory, xmm::Multimodality::Bimodal);
xp.dimension.set(dimIn + dimOut);
xp.dimension_input.set(dimIn);
} else {
set.dimension.set(dimIn);
set.dimension_input.set(0);
xp = xmm::Phrase(xmm::MemoryMode::OwnMemory, xmm::Multimodality::Unimodal);
xp.dimension.set(dimIn);
xp.dimension_input.set(0);
}
set.clear();
//for (auto &phrase : data.trainingSet) {
// changed to look starting from index 1
// because phrase at index 0 is for unordered elements
for (int i = 1; i < data.trainingSet.size(); ++i) {
const rapidmix::trainingData::phrase &phrase = data.trainingSet[i];
xp.clear();
xp.label.set(phrase.label);
for (auto &element : phrase.elements) {
std::vector<float> obsIn(element.input.begin(), element.input.end());
std::vector<float> obsOut(element.output.begin(), element.output.end());
std::vector<float> obs;
obs.insert(obs.end(), obsIn.begin(), obsIn.end());
obs.insert(obs.end(), obsOut.begin(), obsOut.end());
xp.record(obs);
}
set.addPhrase(static_cast<int>(set.size()), xp);
}
return true;
}
//=============================== xmmTool ====================================//
template <class SingleClassModel, class Model>
bool xmmTool<SingleClassModel, Model>::train(const rapidmix::trainingData& newTrainingData) {
if (trainingData2xmmTrainingSet(newTrainingData, set)) {
model.train(&set);
model.reset();
return true;
}
return false;
}
////////// private JSON data manipulation methods :
//TODO: add a type field (gmm/gmr/hmm/hmr) in metadata when family is xmm
template <class SingleClassModel, class Model>
Json::Value xmmTool<SingleClassModel, Model>::toJSON(/*std::string modelType*/) {
Json::Value root;
Json::Value metadata;
Json::Value modelSet;
metadata["creator"] = "Rapid API C++";
metadata["version"] = "v0.1.1"; //TODO: This should be a macro someplace
metadata["family"] = "xmm";
root["metadata"] = metadata;
modelSet.append(model.toJson());
root["modelSet"] = modelSet;
return root;
}
template <class SingleClassModel, class Model>
bool xmmTool<SingleClassModel, Model>::fromJSON(Json::Value &jm) {
if (jm["metadata"]["family"].asString().compare("xmm") == 0 &&
jm["modelSet"].size() > 0) {
model.fromJson(jm["modelSet"][0]);
model.reset();
return true;
}
return false;
}
////////// public JSON file manipulation interface :
template <class SingleClassModel, class Model>
std::string xmmTool<SingleClassModel, Model>::getJSON() {
Json::Value result = toJSON();
return result.toStyledString();
}
template <class SingleClassModel, class Model>
void xmmTool<SingleClassModel, Model>::writeJSON(const std::string &filepath) {
Json::Value root = toJSON();
std::ofstream jsonOut;
jsonOut.open (filepath);
Json::StyledStreamWriter writer;
writer.write(jsonOut, root);
jsonOut.close();
}
template <class SingleClassModel, class Model>
bool xmmTool<SingleClassModel, Model>::putJSON(const std::string &jsonMessage) {
Json::Value parsedFromString;
Json::Reader reader;
bool parsingSuccessful = reader.parse(jsonMessage, parsedFromString);
return (parsingSuccessful && fromJSON(parsedFromString));
}
template <class SingleClassModel, class Model>
bool xmmTool<SingleClassModel, Model>::readJSON(const std::string &filepath) {
Json::Value root;
std::ifstream file(filepath);
file >> root;
return fromJSON(root);
}
//============================== xmmGmmTool ==================================//
std::vector<double> xmmGmmTool::process(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
return model.results.smoothed_normalized_likelihoods;
}
//============================== xmmGmrTool ==================================//
std::vector<double> xmmGmrTool::process(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
std::vector<float> *res = &model.results.output_values;
std::vector<double> dRes(res->begin(), res->end());
return dRes;
}
//============================== xmmHmmTool ==================================//
std::vector<double> xmmHmmTool::process(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
std::vector<double> res;
int i(0);
for (auto &m : model.models) {
res.push_back(model.results.smoothed_normalized_likelihoods[i]);
res.push_back(m.second.results.progress);
i++;
}
return res;
}
//============================== xmmHmrTool ==================================//
std::vector<double> xmmHmrTool::process(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
std::vector<float> *res = &model.results.output_values;
std::vector<double> dRes(res->begin(), res->end());
return dRes;
}
///////////////////////////////////////////////////////////////////////////
///// generic train method and forward declaration of specialized templates
///////////////////////////////////////////////////////////////////////////
template <class MachineLearningModule>
bool rapidmix::machineLearning<MachineLearningModule>::train(const trainingData &newTrainingData) {
return MachineLearningModule::train(newTrainingData);
}
template class rapidmix::machineLearning<xmmGmmTool>;
template class rapidmix::machineLearning<xmmGmrTool>;
template class rapidmix::machineLearning<xmmHmmTool>;
template class rapidmix::machineLearning<xmmHmrTool>;
#ifndef _RAPID_XMM_TOOLS_H_
#define _RAPID_XMM_TOOLS_H_
// this works !
#ifndef EXTERNAL_JSONCPP_PATH
// #define EXTERNAL_JSONCPP_PATH "../../../../json/json.h" // relative to xmmJson.h
#define EXTERNAL_JSONCPP_PATH "json.h"
#endif /* EXTERNAL_JSONCPP_PATH */
#include "xmm.h"
// forward declaration
namespace rapidmix { class trainingData; }
// original defined in xmmModelConfiguration.hpp
enum xmmRegressionEstimator {
xmmLikeliestRegression,
xmmMixtureRegression
};
// original defined in xmmGaussianDistribution.hpp
enum xmmCovarianceMode {
xmmFullCovariance,
xmmDiagonalCovariance
};
// original defined in xmmHmmParameters.hpp
enum xmmHmmTransitionMode {
xmmHmmLeftRightTransition,
xmmHmmErgodicTransition
};
// original defined in xmmHmmParameters.hpp
enum xmmHmmRegressionEstimator {
xmmHmmFullRegression,
xmmHmmWindowedRegression,
xmmHmmLikeliestRegression
};
// this is the optional argument of machineLearning<xmmWhateverTool>'s constructors
struct xmmToolConfig {
xmmToolConfig() :
gaussians(1),
relativeRegularization(0.01),
absoluteRegularization(0.01),
regressionEstimator(xmmMixtureRegression),
covarianceMode(xmmFullCovariance),
states(5),
hierarchical(true),
hmmTransitionMode(xmmHmmErgodicTransition),
hmmRegressionEstimator(xmmHmmFullRegression),
likelihoodWindow(5) {}
// general parameters :
uint32_t gaussians;
float relativeRegularization;
float absoluteRegularization;
xmmRegressionEstimator regressionEstimator;
xmmCovarianceMode covarianceMode;
// hmm specific :
uint32_t states;
bool hierarchical;
xmmHmmTransitionMode hmmTransitionMode;
xmmHmmRegressionEstimator hmmRegressionEstimator;
// run-time parameter :
uint32_t likelihoodWindow;
};
//========================== template base class =============================//
template <class SingleClassModel, class Model>
class xmmTool {
protected:
xmmTool(bool bimodal) {
model = Model(bimodal);
model.configuration.multithreading = xmm::MultithreadingMode::Sequential;
model.configuration.changed = true;
set = xmm::TrainingSet(xmm::MemoryMode::OwnMemory,
bimodal
? xmm::Multimodality::Bimodal
: xmm::Multimodality::Unimodal
);
}
virtual void preProcess(const std::vector<double> &inputVector) {
std::vector<float> fv(inputVector.begin(), inputVector.end());
model.filter(fv);
}
public:
virtual ~xmmTool() {}
virtual bool train(const rapidmix::trainingData &newTrainingData);
virtual bool reset() {
model.reset();
return true;
}
/** Get a JSON representation of the model in the form of a styled string */
virtual std::string getJSON();
/** Write a JSON model description to specified file path */
virtual void writeJSON(const std::string &filepath);
/** configure empty model with string. See getJSON() */
virtual bool putJSON(const std::string &jsonMessage);
/** read a JSON file at file path and build a modelSet from it */
virtual bool readJSON(const std::string &filepath);
protected:
Model model;
xmm::TrainingSet set;
Json::Value toJSON();
bool fromJSON(Json::Value &jm);
};
//======================= base class for GMM models ==========================//
template <class SingleClassModel, class Model>
class xmmStaticTool : public xmmTool<SingleClassModel, Model> {
protected:
xmmStaticTool(xmmToolConfig cfg, bool bimodal) :
xmmTool<SingleClassModel, Model>(bimodal) {
xmm::Configuration<SingleClassModel>& mCfg = this->model.configuration;
mCfg.gaussians.set(cfg.gaussians);
mCfg.relative_regularization.set(cfg.relativeRegularization);
mCfg.absolute_regularization.set(cfg.absoluteRegularization);
xmm::MultiClassRegressionEstimator mcre;
switch (cfg.regressionEstimator) {
case xmmLikeliestRegression:
mcre = xmm::MultiClassRegressionEstimator::Likeliest;
case xmmMixtureRegression:
default:
mcre = xmm::MultiClassRegressionEstimator::Mixture;
break;
}
mCfg.multiClass_regression_estimator = mcre;
xmm::GaussianDistribution::CovarianceMode gdcm;
switch (cfg.covarianceMode) {
case xmmFullCovariance:
gdcm = xmm::GaussianDistribution::CovarianceMode::Full;
break;
case xmmDiagonalCovariance:
default:
gdcm = xmm::GaussianDistribution::CovarianceMode::Diagonal;
break;
}
mCfg.covariance_mode.set(gdcm);
mCfg.changed = true;
this->model.shared_parameters->likelihood_window.set(cfg.likelihoodWindow);
}
public:
virtual ~xmmStaticTool() {}
};
//======================= base class for HMM models ==========================//
template <class SingleClassModel, class Model>
class xmmTemporalTool : public xmmStaticTool<SingleClassModel, Model> {
protected:
xmmTemporalTool(xmmToolConfig cfg, bool bimodal) :
xmmStaticTool<SingleClassModel, Model>(cfg, bimodal) {
xmm::Configuration<SingleClassModel>& mCfg = this->model.configuration;
mCfg.states.set(cfg.states);
mCfg.hierarchical.set(cfg.hierarchical);
xmm::HMM::TransitionMode htm;
switch (cfg.hmmTransitionMode) {
case xmmHmmLeftRightTransition:
htm = xmm::HMM::TransitionMode::LeftRight;
break;
case xmmHmmErgodicTransition:
default:
htm = xmm::HMM::TransitionMode::Ergodic;
break;
}
mCfg.transition_mode.set(htm);
xmm::HMM::RegressionEstimator hre;
switch (cfg.hmmRegressionEstimator) {
case xmmHmmFullRegression:
hre = xmm::HMM::RegressionEstimator::Full;
break;
case xmmHmmWindowedRegression:
hre = xmm::HMM::RegressionEstimator::Windowed;
break;
case xmmHmmLikeliestRegression:
default:
hre = xmm::HMM::RegressionEstimator::Likeliest;
break;
}
mCfg.regression_estimator.set(hre);
mCfg.changed = true;
}
public:
virtual ~xmmTemporalTool() {}
};
//================== actual classes used in machineLearning.h ================//
class xmmGmmTool : public xmmStaticTool<xmm::GMM, xmm::GMM> {
public:
xmmGmmTool(xmmToolConfig cfg = xmmToolConfig()) :
xmmStaticTool<xmm::GMM, xmm::GMM>(cfg, false) {}
~xmmGmmTool() {}
std::vector<double> process(const std::vector<double>& inputVector);
};
class xmmGmrTool : public xmmStaticTool<xmm::GMM, xmm::GMM> {
public:
xmmGmrTool(xmmToolConfig cfg = xmmToolConfig()) :
xmmStaticTool<xmm::GMM, xmm::GMM>(cfg, true) {}
~xmmGmrTool() {}
std::vector<double> process(const std::vector<double>& inputVector);
};
class xmmHmmTool : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
public:
xmmHmmTool(xmmToolConfig cfg = xmmToolConfig()) :
xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM>(cfg, false) {}
~xmmHmmTool() {}
std::vector<double> process(const std::vector<double>& inputVector);
};
class xmmHmrTool : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
public:
xmmHmrTool(xmmToolConfig cfg = xmmToolConfig()) :
xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM>(cfg, true) {}
~xmmHmrTool() {}
std::vector<double> process(const std::vector<double>& inputVector);
};
#endif /* _RAPID_XMM_TOOLS_H_ */
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