30 this->numParticles = numParticles;
31 this->numClustersPerState = numClustersPerState;
32 this->stateTransitionSmoothingCoeff = stateTransitionSmoothingCoeff;
33 this->measurementNoise = measurementNoise;
34 classType =
"FiniteStateMachine";
35 classifierType = classType;
36 classifierMode = TIMESERIES_CLASSIFIER_MODE;
37 debugLog.setProceedingText(
"[DEBUG FiniteStateMachine]");
38 errorLog.setProceedingText(
"[ERROR FiniteStateMachine]");
39 trainingLog.setProceedingText(
"[TRAINING FiniteStateMachine]");
40 warningLog.setProceedingText(
"[WARNING FiniteStateMachine]");
49 classType =
"FiniteStateMachine";
50 classifierType = classType;
51 classifierMode = STANDARD_CLASSIFIER_MODE;
52 debugLog.setProceedingText(
"[DEBUG FiniteStateMachine]");
53 errorLog.setProceedingText(
"[ERROR FiniteStateMachine]");
54 trainingLog.setProceedingText(
"[TRAINING FiniteStateMachine]");
55 warningLog.setProceedingText(
"[WARNING FiniteStateMachine]");
72 this->numParticles = rhs.numParticles;
73 this->numClustersPerState = rhs.numClustersPerState;
74 this->stateTransitionSmoothingCoeff = rhs.stateTransitionSmoothingCoeff;
75 this->measurementNoise = rhs.measurementNoise;
76 this->particles = rhs.particles;
77 this->stateTransitions = rhs.stateTransitions;
78 this->stateEmissions = rhs.stateEmissions;
81 this->initParticles();
89 if( classifier == NULL )
return false;
99 errorLog <<
"deepCopyFrom(const Classifier *classifier) - Failed to deep copy classifier base class!" << std::endl;
103 this->numParticles = ptr->numParticles;
104 this->numClustersPerState = ptr->numClustersPerState;
105 this->stateTransitionSmoothingCoeff = ptr->stateTransitionSmoothingCoeff;
106 this->measurementNoise = ptr->measurementNoise;
107 this->particles = ptr->particles;
108 this->stateTransitions = ptr->stateTransitions;
109 this->stateEmissions = ptr->stateEmissions;
112 this->initParticles();
126 errorLog <<
"train_(ClassificationData &trainingData) - Training data has zero samples!" << std::endl;
135 for(
unsigned int i=0; i<M; i++){
136 timeseries.
addSample(trainingData[i].getClassLabel(), trainingData[i].getSample());
140 if( !
train_( timeseries ) ){
142 errorLog <<
"train_(ClassificationData &trainingData) - Failed to train particle filter!" << std::endl;
155 errorLog <<
"train_(TimeSeriesClassificationData &trainingData) - Training data has zero samples!" << std::endl;
164 for(
unsigned int i=0; i<M; i++){
165 for(
unsigned int j=0; j<trainingData[i].getLength(); j++){
166 timeseries.
addSample(trainingData[i].getClassLabel(), trainingData[i].getData().getRow(j));
171 if( !
train_( timeseries ) ){
173 errorLog <<
"train_(TimeSeriesClassificationData &trainingData) - Failed to train particle filter!" << std::endl;
193 numInputDimensions = N;
203 stateTransitions.
resize(K, K);
211 UINT currentStateIndex = 0;
214 stateTransitions[ lastStateIndex ][ currentStateIndex ]++;
215 lastStateIndex = currentStateIndex;
220 for(UINT i=0; i<K; i++){
222 for(UINT j=0; j<K; j++){
223 sum += stateTransitions[i][j] + stateTransitionSmoothingCoeff;
225 for(UINT j=0; j<K; j++){
226 stateTransitions[i][j] /= sum;
231 for(UINT k=0; k<K; k++){
235 for(UINT i=0; i<M; i++){
236 if( data[i].getClassLabel() == classLabels[k] ){
237 classData.
push_back( data[i].getSample() );
242 if( classData.
getNumRows() < numClustersPerState ){
243 errorLog <<
"train_(TimeSeriesClassificationDataStream &trainingData) - There are not enough samples in state " << classLabels[k] <<
"! You should reduce the numClustersPerState to: " << classData.
getNumRows() << std::endl;
255 if( !kmeans.
train_( classData ) ){
256 errorLog <<
"train_(TimeSeriesClassificationDataStream &trainingData) - Failed to train kmeans cluster for class k: " << classLabels[k] << std::endl;
262 stateEmissions.push_back( kmeans.getClusters() );
282 errorLog <<
"predict_(VectorFloat &inputVector) - Model Not Trained!" << std::endl;
286 predictedClassLabel = 0;
287 maxLikelihood = -10000;
289 if( inputVector.size() != numInputDimensions ){
290 errorLog <<
"predict_(VectorFloat &inputVector) - The size of the input vector (" << inputVector.size() <<
") does not match the num features in the model (" << numInputDimensions << std::endl;
295 for(UINT n=0; n<numInputDimensions; n++){
296 inputVector[n] =
scale(inputVector[n], ranges[n].minValue, ranges[n].maxValue, 0, 1);
300 if( classLikelihoods.size() != numClasses ) classLikelihoods.
resize(numClasses,0);
301 if( classDistances.size() != numClasses ) classDistances.
resize(numClasses,0);
303 std::fill(classLikelihoods.begin(),classLikelihoods.end(),0);
304 std::fill(classDistances.begin(),classDistances.end(),0);
307 particles.
filter( inputVector );
311 for(UINT i=0; i<numParticles; i++){
312 sum += particles[i].w;
313 classLikelihoods[ particles[i].currentState ] += particles[i].w;
314 classDistances[ particles[i].currentState ] += particles[i].w;
319 predictedClassLabel = 0;
320 for(UINT i=0; i<numClasses; i++){
321 classLikelihoods[ i ] /= sum;
323 if( classLikelihoods[i] > maxLikelihood ){
324 maxLikelihood = classLikelihoods[i];
325 predictedClassLabel = classLabels[i];
336 for(UINT i=0; i<numParticles; i++){
351 stateTransitions.
clear();
352 stateEmissions.clear();
362 infoLog <<
"FiniteStateMachineModel" << std::endl;
363 infoLog <<
"NumParticles: " << numParticles << std::endl;
364 infoLog <<
"NumClustersPerState: " << numClustersPerState << std::endl;
365 infoLog <<
"StateTransitionSmoothingCoeff: " << stateTransitionSmoothingCoeff << std::endl;
368 infoLog <<
"StateTransitions: " << std::endl;
369 for(
unsigned int i=0; i<stateTransitions.
getNumRows(); i++){
370 for(
unsigned int j=0; j<stateTransitions.
getNumCols(); j++){
371 infoLog << stateTransitions[i][j] <<
" ";
373 infoLog << std::endl;
376 infoLog <<
"StateEmissions: " << std::endl;
377 for(
unsigned int k=0; k<stateEmissions.size(); k++){
378 for(
unsigned int i=0; i<stateEmissions[k].getNumRows(); i++){
379 for(
unsigned int j=0; j<stateEmissions[k].getNumCols(); j++){
380 infoLog << stateEmissions[k][i][j] <<
" ";
382 infoLog << std::endl;
394 errorLog <<
"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
399 file <<
"GRT_FSM_MODEL_FILE_V1.0\n";
403 errorLog <<
"saveModelToFile(fstream &file) - Failed to save classifier base settings to file!" << std::endl;
407 file <<
"NumParticles: " << numParticles << std::endl;
408 file <<
"NumClustersPerState: " << numClustersPerState << std::endl;
409 file <<
"StateTransitionSmoothingCoeff: " << stateTransitionSmoothingCoeff << std::endl;
412 file <<
"StateTransitions:" << std::endl;
413 for(
unsigned int i=0; i<stateTransitions.
getNumRows(); i++){
414 for(
unsigned int j=0; j<stateTransitions.
getNumCols(); j++){
415 file << stateTransitions[i][j] <<
" ";
420 file <<
"StateEmissions:" << std::endl;
421 for(
unsigned int k=0; k<numClasses; k++){
422 for(
unsigned int i=0; i<stateEmissions[k].getNumRows(); i++){
423 for(
unsigned int j=0; j<stateEmissions[k].getNumCols(); j++){
424 file << stateEmissions[k][i][j] <<
" ";
431 file <<
"Ranges: " << std::endl;
432 for(UINT i=0; i<ranges.size(); i++){
433 file << ranges[i].minValue <<
"\t" << ranges[i].maxValue << std::endl;
448 errorLog <<
"loadModelFromFile(string filename) - Could not open file to load model" << std::endl;
456 if( word !=
"GRT_FSM_MODEL_FILE_V1.0" ){
457 errorLog <<
"loadModelFromFile(string filename) - Could not find Model File Header" << std::endl;
463 errorLog <<
"loadModelFromFile(string filename) - Failed to load base settings from file!" << std::endl;
469 if( word !=
"NumParticles:" ){
470 errorLog <<
"loadModelFromFile(string filename) - Could not find NumParticles Header" << std::endl;
473 file >> numParticles;
477 if( word !=
"NumClustersPerState:" ){
478 errorLog <<
"loadModelFromFile(string filename) - Could not find NumClustersPerState Header" << std::endl;
481 file >> numClustersPerState;
485 if( word !=
"StateTransitionSmoothingCoeff:" ){
486 errorLog <<
"loadModelFromFile(string filename) - Could not find stateTransitionSmoothingCoeff Header" << std::endl;
489 file >> stateTransitionSmoothingCoeff;
495 if( word !=
"StateTransitions:" ){
496 errorLog <<
"loadModelFromFile(string filename) - Could not find StateTransitions Header" << std::endl;
499 stateTransitions.
resize(numClasses, numClasses);
501 for(
unsigned int i=0; i<stateTransitions.
getNumRows(); i++){
502 for(
unsigned int j=0; j<stateTransitions.
getNumCols(); j++){
503 file >> stateTransitions[i][j];
509 if( word !=
"StateEmissions:" ){
510 errorLog <<
"loadModelFromFile(string filename) - Could not find StateEmissions Header" << std::endl;
513 stateEmissions.
resize( numClasses );
515 for(
unsigned int k=0; k<numClasses; k++){
516 stateEmissions[k].
resize( numClustersPerState, numInputDimensions );
517 for(
unsigned int i=0; i<stateEmissions[k].getNumRows(); i++){
518 for(
unsigned int j=0; j<stateEmissions[k].getNumCols(); j++){
519 file >> stateEmissions[k][i][j];
527 if( word !=
"Ranges:" ){
528 errorLog <<
"loadModelFromFile(string filename) - Failed to read Ranges header!" << std::endl;
532 ranges.
resize(numInputDimensions);
534 for(UINT i=0; i<ranges.size(); i++){
535 file >> ranges[i].minValue;
536 file >> ranges[i].maxValue;
546 bool FiniteStateMachine::recomputePT(){
549 warningLog <<
"recomputePT() - Failed to init particles, the model has not been trained!" << std::endl;
557 for(UINT i=0; i<K; i++){
559 for(UINT j=0; j<K; j++){
561 model[j].value = stateTransitions[i][j];
563 pt.push_back( model );
569 bool FiniteStateMachine::recomputePE(){
572 warningLog <<
"recomputePE() - Failed to init particles, the model has not been trained!" << std::endl;
578 const UINT K = stateEmissions.
getSize();
581 for(UINT k=0; k<K; k++){
585 model.reserve( numClustersPerState );
586 for(UINT i=0; i<stateEmissions[k].getNumRows(); i++){
587 model.push_back( stateEmissions[k].getRow(i) );
590 pe.push_back( model );
596 bool FiniteStateMachine::initParticles(){
599 warningLog <<
"initParticles() - Failed to init particles, the model has not been trained!" << std::endl;
605 VectorFloat initProcessNoise( numInputDimensions, 0 );
606 VectorFloat initMeasurementNoise( numInputDimensions, 0 );
609 for(
unsigned int i=0; i<numInputDimensions; i++){
610 initModel[i][0] = useScaling ? 0 : ranges[i].minValue;
611 initModel[i][1] = useScaling ? 1 : ranges[i].maxValue;
615 for(
unsigned int i=0; i<numInputDimensions; i++){
616 initMeasurementNoise[i] = measurementNoise;
619 particles.
init(numParticles, initModel, initProcessNoise, initMeasurementNoise);
625 particles.setLookupTables(
pt,
pe );
633 bool FiniteStateMachine::setNumParticles(
const UINT numParticles){
637 this->numParticles = numParticles;
642 bool FiniteStateMachine::setNumClustersPerState(
const UINT numClustersPerState){
646 this->numClustersPerState = numClustersPerState;
651 bool FiniteStateMachine::setStateTransitionSmoothingCoeff(
const Float stateTransitionSmoothingCoeff){
655 this->stateTransitionSmoothingCoeff = stateTransitionSmoothingCoeff;
660 bool FiniteStateMachine::setMeasurementNoise(
const Float measurementNoise){
664 this->measurementNoise = measurementNoise;
bool saveBaseSettingsToFile(std::fstream &file) const
virtual bool filter(SENSOR_DATA &data)
UINT getNumSamples() const
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
std::string getClassifierType() const
FiniteStateMachine(const UINT numParticles=200, const UINT numClustersPerState=20, const Float stateTransitionSmoothingCoeff=0.0, const Float measurementNoise=10.0)
virtual bool resize(const unsigned int size)
virtual bool train_(MatrixFloat &data)
virtual bool print() const
UINT getClassLabelIndexValue(UINT classLabel) const
bool scale(const Float minTarget, const Float maxTarget)
bool setMinChange(const Float minChange)
Vector< UINT > getClassLabels() const
unsigned int getSize() const
bool setAllValues(const T &value)
UINT getNumDimensions() const
UINT getNumSamples() const
virtual ~FiniteStateMachine(void)
virtual bool deepCopyFrom(const Classifier *classifier)
bool copyBaseVariables(const Classifier *classifier)
Vector< Vector< IndexedDouble > > pt
This stores the stateTransitions matrix in a format more efficient for the particle filter...
bool loadBaseSettingsFromFile(std::fstream &file)
unsigned int getNumRows() const
UINT getNumDimensions() const
unsigned int getNumCols() const
bool addSample(const UINT classLabel, const VectorFloat &sample)
bool setMinNumEpochs(const UINT minNumEpochs)
virtual bool train_(ClassificationData &trainingData)
virtual bool saveModelToFile(std::fstream &file) const
UINT getNumDimensions() const
UINT getNumClasses() const
bool setNumDimensions(const UINT numDimensions)
int getRandomNumberInt(int minRange, int maxRange)
virtual bool predict_(VectorFloat &inputVector)
virtual bool resize(const unsigned int r, const unsigned int c)
Vector< MinMax > getRanges() const
UINT getNumSamples() const
Vector< Vector< VectorFloat > > pe
This stores the stateEmissions model in a format more efficient for the particle filter.
virtual bool init(const unsigned int numParticles, const Vector< VectorFloat > &initModel, const VectorFloat &processNoise, const VectorFloat &measurementNoise)
bool setMaxNumEpochs(const UINT maxNumEpochs)
bool push_back(const Vector< T > &sample)
virtual bool loadModelFromFile(std::fstream &file)
FiniteStateMachine & operator=(const FiniteStateMachine &rhs)
bool setNumClusters(const UINT numClusters)