21 #define GRT_DLL_EXPORTS 27 const std::string DTW::id =
"DTW";
33 DTW::DTW(
bool useScaling,
bool useNullRejection,Float nullRejectionCoeff,UINT rejectionMode,
bool constrainWarpingPath,Float radius,
bool offsetUsingFirstSample,
bool useSmoothing,UINT smoothingFactor,Float nullRejectionLikelihoodThreshold) :
Classifier(
DTW::
getId() )
36 this->useScaling=useScaling;
37 this->useNullRejection = useNullRejection;
38 this->nullRejectionCoeff = nullRejectionCoeff;
39 this->nullRejectionLikelihoodThreshold = nullRejectionLikelihoodThreshold;
40 this->rejectionMode = rejectionMode;
41 this->constrainWarpingPath = constrainWarpingPath;
42 this->radius = radius;
43 this->offsetUsingFirstSample = offsetUsingFirstSample;
44 this->useSmoothing = useSmoothing;
45 this->smoothingFactor = smoothingFactor;
47 supportsNullRejection =
true;
49 useZNormalisation=
false;
51 trimTrainingData =
false;
53 zNormConstrainThreshold=0.2;
55 maximumTrimPercentage = 90;
58 distanceMethod=EUCLIDEAN_DIST;
60 averageTemplateLength =0;
62 classifierMode = TIMESERIES_CLASSIFIER_MODE;
77 this->templatesBuffer = rhs.templatesBuffer;
78 this->distanceMatrices = rhs.distanceMatrices;
79 this->warpPaths = rhs.warpPaths;
80 this->continuousInputDataBuffer = rhs.continuousInputDataBuffer;
81 this->numTemplates = rhs.numTemplates;
82 this->useSmoothing = rhs.useSmoothing;
83 this->useZNormalisation = rhs.useZNormalisation;
84 this->constrainZNorm = rhs.constrainZNorm;
85 this->constrainWarpingPath = rhs.constrainWarpingPath;
86 this->trimTrainingData = rhs.trimTrainingData;
87 this->zNormConstrainThreshold = rhs.zNormConstrainThreshold;
88 this->radius = rhs.radius;
89 this->offsetUsingFirstSample = rhs.offsetUsingFirstSample;
90 this->trimThreshold = rhs.trimThreshold;
91 this->maximumTrimPercentage = rhs.maximumTrimPercentage;
92 this->smoothingFactor = rhs.smoothingFactor;
93 this->distanceMethod = rhs.distanceMethod;
94 this->rejectionMode = rhs.rejectionMode;
95 this->nullRejectionLikelihoodThreshold = rhs.nullRejectionLikelihoodThreshold;
96 this->averageTemplateLength = rhs.averageTemplateLength;
107 if( classifier == NULL )
return false;
111 DTW *ptr = (
DTW*)classifier;
112 this->templatesBuffer = ptr->templatesBuffer;
113 this->distanceMatrices = ptr->distanceMatrices;
114 this->warpPaths = ptr->warpPaths;
115 this->continuousInputDataBuffer = ptr->continuousInputDataBuffer;
116 this->numTemplates = ptr->numTemplates;
117 this->useSmoothing = ptr->useSmoothing;
118 this->useZNormalisation = ptr->useZNormalisation;
119 this->constrainZNorm = ptr->constrainZNorm;
120 this->constrainWarpingPath = ptr->constrainWarpingPath;
121 this->trimTrainingData = ptr->trimTrainingData;
122 this->zNormConstrainThreshold = ptr->zNormConstrainThreshold;
123 this->radius = ptr->radius;
124 this->offsetUsingFirstSample = ptr->offsetUsingFirstSample;
125 this->trimThreshold = ptr->trimThreshold;
126 this->maximumTrimPercentage = ptr->maximumTrimPercentage;
127 this->smoothingFactor = ptr->smoothingFactor;
128 this->distanceMethod = ptr->distanceMethod;
129 this->rejectionMode = ptr->rejectionMode;
130 this->nullRejectionLikelihoodThreshold = ptr->nullRejectionLikelihoodThreshold;
131 this->averageTemplateLength = ptr->averageTemplateLength;
146 templatesBuffer.clear();
149 continuousInputDataBuffer.
clear();
151 if( trimTrainingData ){
158 tempData.
addSample(data[i].getClassLabel(), data[i].getData());
160 trainingLog <<
"Removing training sample " << i <<
" from the dataset as it could not be trimmed!" << std::endl;
168 errorLog << __GRT_LOG__ <<
" Can't train model as there are no samples in training data!" << std::endl;
176 templatesBuffer.
resize( numClasses );
177 classLabels.
resize( numClasses );
178 nullRejectionThresholds.
resize( numClasses );
179 averageTemplateLength = 0;
186 if( useScaling ) scaleData( trainingData );
187 if( useZNormalisation ) znormData( trainingData );
190 for(UINT k=0; k<numTemplates; k++){
198 templatesBuffer[k].classLabel = classLabel;
201 classLabels[k] = classLabel;
203 trainingLog <<
"Training Template: " << k <<
" Class: " << classLabel << std::endl;
206 if( numExamples < 1 ){
207 errorLog << __GRT_LOG__ <<
" Can not train model: Num of Example is < 1! Class: " << classLabel <<
". Turn off null rejection if you want to use DTW with only 1 training sample per class." << std::endl;
211 if( numExamples == 1 && useNullRejection ){
212 errorLog << __GRT_LOG__ <<
" Can not train model as there is only 1 example in class: " << classLabel <<
". Turn off null rejection if you want to use DTW with only 1 training sample per class." << std::endl;
216 if( numExamples == 1 ){
218 nullRejectionThresholds[k] = 0.0;
221 if( !train_NDDTW(classData,templatesBuffer[k],bestIndex) ){
222 errorLog << __GRT_LOG__ <<
" Failed to train template for class with label: " << classLabel << std::endl;
228 int trainingMethod = 0;
229 if(useSmoothing) trainingMethod = 1;
231 switch (trainingMethod) {
233 templatesBuffer[k].timeSeries = classData[bestIndex].getData();
237 smoothData(classData[ bestIndex ].getData(),smoothingFactor,templatesBuffer[k].timeSeries);
240 errorLog << __GRT_LOG__ <<
" Can not train model: Unknown training method " << std::endl;
245 if( offsetUsingFirstSample ){
246 offsetTimeseries( templatesBuffer[k].timeSeries );
250 averageTemplateLength += templatesBuffer[k].averageTemplateLength;
256 averageTemplateLength = averageTemplateLength/numTemplates;
262 continuousInputDataBuffer.
clear();
263 continuousInputDataBuffer.
resize(averageTemplateLength,
VectorFloat(numInputDimensions,0));
265 classDistances.
resize(numTemplates,0);
266 predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
277 MatrixFloat distanceResults(numExamples,numExamples);
278 dtwTemplate.averageTemplateLength = 0;
280 for(UINT m=0; m<numExamples; m++){
284 dtwTemplate.averageTemplateLength += trainingData[m].getLength();
287 if( useSmoothing ) smoothData(trainingData[m].getData(),smoothingFactor,templateA);
288 else templateA = trainingData[m].getData();
290 if( offsetUsingFirstSample ){
291 offsetTimeseries(templateA);
294 for(UINT n=0; n<numExamples; n++){
297 if( useSmoothing ) smoothData(trainingData[n].getData(),smoothingFactor,templateB);
298 else templateB = trainingData[n].getData();
300 if( offsetUsingFirstSample ){
301 offsetTimeseries(templateB);
307 Float dist = computeDistance(templateA,templateB,distanceMatrix,warpPath);
309 trainingLog <<
"Template: " << m <<
" Timeseries: " << n <<
" Dist: " << dist << std::endl;
312 distanceResults[m][n] = dist;
314 }
else distanceResults[m][n] = 0;
318 for(UINT m=0; m<numExamples; m++) results[m]/=(numExamples-1);
321 Float bestAverage = results[0];
322 for(UINT m=1; m<numExamples; m++){
323 if( results[m] < bestAverage ){
324 bestAverage = results[m];
329 if( numExamples > 2 ){
331 dtwTemplate.trainingMu = results[bestIndex];
332 dtwTemplate.trainingSigma = 0.0;
334 for(UINT n=0; n<numExamples; n++){
336 dtwTemplate.trainingSigma += SQR( distanceResults[ bestIndex ][n] - dtwTemplate.trainingMu );
339 dtwTemplate.trainingSigma = sqrt( dtwTemplate.trainingSigma / Float(numExamples-2) );
341 warningLog << __GRT_LOG__ <<
" There are not enough examples to compute the trainingMu and trainingSigma for the template for class " << dtwTemplate.classLabel << std::endl;
342 dtwTemplate.trainingMu = 0.0;
343 dtwTemplate.trainingSigma = 0.0;
347 dtwTemplate.averageTemplateLength = (UINT) (dtwTemplate.averageTemplateLength/Float(numExamples));
349 trainingLog <<
"AverageTemplateLength: " << dtwTemplate.averageTemplateLength << std::endl;
359 errorLog << __GRT_LOG__ <<
" The DTW templates have not been trained!" << std::endl;
363 if( classLikelihoods.size() != numTemplates ) classLikelihoods.
resize(numTemplates);
364 if( classDistances.size() != numTemplates ) classDistances.
resize(numTemplates);
366 predictedClassLabel = 0;
368 for(UINT k=0; k<classLikelihoods.size(); k++){
369 classLikelihoods[k] = 0;
373 if( numInputDimensions != inputTimeSeries.
getNumCols() ){
374 errorLog << __GRT_LOG__ <<
" The number of features in the model (" << numInputDimensions <<
") do not match that of the input time series (" << inputTimeSeries.
getNumCols() <<
")" << std::endl;
383 scaleData(*timeSeriesPtr,processedTimeSeries);
384 timeSeriesPtr = &processedTimeSeries;
388 if( useZNormalisation ){
389 znormData(*timeSeriesPtr,processedTimeSeries);
390 timeSeriesPtr = &processedTimeSeries;
395 smoothData(*timeSeriesPtr,smoothingFactor,tempMatrix);
396 timeSeriesPtr = &tempMatrix;
400 if( offsetUsingFirstSample ){
401 offsetTimeseries( *timeSeriesPtr );
406 if( distanceMatrices.size() != numTemplates ) distanceMatrices.
resize( numTemplates );
407 if( warpPaths.size() != numTemplates ) warpPaths.
resize( numTemplates );
410 for(UINT k=0; k<numTemplates; k++){
412 classDistances[k] = computeDistance(templatesBuffer[k].timeSeries,*timeSeriesPtr,distanceMatrices[k],warpPaths[k]);
414 if(classDistances[k] > 1e-8)
416 classLikelihoods[k] = 1.0 / classDistances[k];
420 classLikelihoods[k] = 1e8;
423 sum += classLikelihoods[k];
427 UINT closestTemplateIndex = 0;
428 bestDistance = classDistances[0];
429 for(UINT k=1; k<numTemplates; k++){
430 if( classDistances[k] < bestDistance ){
431 bestDistance = classDistances[k];
432 closestTemplateIndex = k;
437 UINT maxLikelihoodIndex = 0;
440 for(UINT k=0; k<numTemplates; k++){
441 classLikelihoods[k] /= sum;
442 if( classLikelihoods[k] > maxLikelihood ){
443 maxLikelihood = classLikelihoods[k];
444 maxLikelihoodIndex = k;
449 if( useNullRejection ){
451 switch( rejectionMode ){
452 case TEMPLATE_THRESHOLDS:
453 if( bestDistance <= nullRejectionThresholds[ closestTemplateIndex ] ) predictedClassLabel = templatesBuffer[ closestTemplateIndex ].classLabel;
454 else predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
456 case CLASS_LIKELIHOODS:
457 if( maxLikelihood >= nullRejectionLikelihoodThreshold) predictedClassLabel = templatesBuffer[ maxLikelihoodIndex ].classLabel;
458 else predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
460 case THRESHOLDS_AND_LIKELIHOODS:
461 if( bestDistance <= nullRejectionThresholds[ closestTemplateIndex ] && maxLikelihood >= nullRejectionLikelihoodThreshold)
462 predictedClassLabel = templatesBuffer[ closestTemplateIndex ].classLabel;
463 else predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
466 errorLog << __GRT_LOG__ <<
" Unknown RejectionMode!" << std::endl;
471 }
else predictedClassLabel = templatesBuffer[ closestTemplateIndex ].classLabel;
479 errorLog << __GRT_LOG__ <<
" The model has not been trained!" << std::endl;
482 predictedClassLabel = 0;
485 std::fill(classDistances.begin(),classDistances.end(),0);
487 if( numInputDimensions != inputVector.
getSize() ){
488 errorLog << __GRT_LOG__ <<
" The number of features in the model " << numInputDimensions <<
" does not match that of the input Vector " << inputVector.size() << std::endl;
493 continuousInputDataBuffer.
push_back( inputVector );
501 const UINT M = continuousInputDataBuffer.
getSize();
502 const UINT N = numInputDimensions;
504 for(UINT i=0; i<M; i++){
505 for(UINT j=0; j<N; j++){
506 predictionTimeSeries[i][j] = continuousInputDataBuffer[i][j];
511 return predict( predictionTimeSeries );
516 continuousInputDataBuffer.
clear();
518 continuousInputDataBuffer.
resize(averageTemplateLength,
VectorFloat(numInputDimensions,0));
530 templatesBuffer.clear();
531 distanceMatrices.clear();
533 continuousInputDataBuffer.
clear();
540 if(!trained)
return false;
543 nullRejectionThresholds.
resize(numTemplates);
545 for(UINT k=0; k<numTemplates; k++){
547 nullRejectionThresholds[k] = templatesBuffer[k].trainingMu + (templatesBuffer[k].trainingSigma * nullRejectionCoeff);
555 if( newTemplates.size() == templatesBuffer.size() ){
556 templatesBuffer = newTemplates;
558 classLabels.
resize( templatesBuffer.size() );
559 for(UINT i=0; i<templatesBuffer.size(); i++){
560 classLabels[i] = templatesBuffer[i].classLabel;
575 Float totalDist,v,normFactor = 0.;
579 distanceMatrix.
resize(M, N);
582 switch (distanceMethod) {
583 case (ABSOLUTE_DIST):
586 distanceMatrix[i][j] = 0.0;
588 distanceMatrix[i][j] += fabs(timeSeriesA[i][k]-timeSeriesB[j][k]);
593 case (EUCLIDEAN_DIST):
597 distanceMatrix[i][j] = 0.0;
599 distanceMatrix[i][j] += SQR( timeSeriesA[i][k]-timeSeriesB[j][k] );
601 distanceMatrix[i][j] = sqrt( distanceMatrix[i][j] );
605 case (NORM_ABSOLUTE_DIST):
608 distanceMatrix[i][j] = 0.0;
610 distanceMatrix[i][j] += fabs(timeSeriesA[i][k]-timeSeriesB[j][k]);
612 distanceMatrix[i][j]/=N;
617 errorLog<< __GRT_LOG__ <<
" Unknown distance method: "<<distanceMethod<< std::endl;
623 Float distance = sqrt( d(M-1,N-1,distanceMatrix,M,N) );
625 if( grt_isinf(distance) || grt_isnan(distance) ){
626 warningLog << __GRT_LOG__ <<
" Distance Matrix Values are INF!" << std::endl;
635 distanceMatrix[i][j] = fabs( distanceMatrix[i][j] );
642 totalDist = distanceMatrix[i][j];
643 warpPath.push_back(
IndexDist(i,j,distanceMatrix[i][j]) );
648 if( i==0 && j==0 )
break;
656 if( distanceMatrix[i-1][j] < v ){ v = distanceMatrix[i-1][j]; index = 1; }
657 if( distanceMatrix[i][j-1] < v ){ v = distanceMatrix[i][j-1]; index = 2; }
658 if( distanceMatrix[i-1][j-1] <= v ){ index = 3; }
671 warningLog << __GRT_LOG__ <<
" Could not compute a warping path for the input matrix! Dist: " << distanceMatrix[i-1][j] <<
" i: " << i <<
" j: " << j << std::endl;
678 totalDist += distanceMatrix[i][j];
679 warpPath.push_back(
IndexDist(i,j,distanceMatrix[i][j]) );
682 return totalDist/normFactor;
685 Float DTW::d(
int m,
int n,
MatrixFloat &distanceMatrix,
const int M,
const int N){
691 if( grt_isnan( distanceMatrix[m][n] ) ){
695 if( constrainWarpingPath ){
696 Float r = ceil( grt_min(M,N)*radius );
698 if( fabs( n-((N-1)/((M-1)/Float(m))) ) > r ){
699 if( n-((N-1)/((M-1)/Float(m))) > 0 ){
700 for(
int i=0; i<m; i++){
701 for(
int j=n; j<N; j++){
702 distanceMatrix[i][j] = NAN;
706 for(
int i=m; i<M; i++){
707 for(
int j=0; j<n; j++){
708 distanceMatrix[i][j] = NAN;
718 if( distanceMatrix[m][n] < 0 ){
719 dist = fabs( distanceMatrix[m][n] );
727 if( m == 0 && n == 0 ){
728 dist = distanceMatrix[0][0];
729 distanceMatrix[0][0] = -distanceMatrix[0][0];
736 Float contribDist = d(m,n-1,distanceMatrix,M,N);
738 dist = distanceMatrix[m][n] + contribDist;
740 distanceMatrix[m][n] = -dist;
746 Float contribDist = d(m-1,n,distanceMatrix,M,N);
748 dist = distanceMatrix[m][n] + contribDist;
750 distanceMatrix[m][n] = -dist;
754 Float contribDist1 = d(m-1,n-1,distanceMatrix,M,N);
755 Float contribDist2 = d(m-1,n,distanceMatrix,M,N);
756 Float contribDist3 = d(m,n-1,distanceMatrix,M,N);
759 if( contribDist1 < minValue ){ minValue = contribDist1; index = 1; }
760 if( contribDist2 < minValue ){ minValue = contribDist2; index = 2; }
761 if( contribDist3 < minValue ){ minValue = contribDist3; index = 3; }
765 dist = distanceMatrix[m][n] + minValue;
768 dist = distanceMatrix[m][n] + minValue;
771 dist = distanceMatrix[m][n] + minValue;
778 distanceMatrix[m][n] = -dist;
787 inline Float DTW::MIN_(Float a,Float b, Float c){
801 scaleData( trainingData[i].getData(), trainingData[i].getData() );
816 for(UINT i=0; i<R; i++)
817 for(UINT j=0; j<C; j++)
818 scaledData[i][j] = grt_scale(data[i][j],ranges[j].minValue,ranges[j].maxValue,0.0,1.0);
825 znormData( trainingData[i].getData(), trainingData[i].getData() );
839 for(UINT j=0; j<C; j++){
844 for(UINT i=0; i<R; i++) mean += data[i][j];
848 for(UINT i=0; i<R; i++)
849 stdDev += grt_sqr(data[i][j]-mean);
850 stdDev = grt_sqrt( stdDev / (R - 1.0) );
852 if(constrainZNorm && stdDev < 0.01){
854 for(UINT i=0; i<R; i++)
855 normData[i][j] = (data[i][j] - mean);
858 for(UINT i=0; i<R; i++)
859 normData[i][j] = (data[i][j] - mean) / stdDev;
866 const UINT M = (UINT)data.size();
867 const UINT N = (UINT) floor(Float(M)/Float(smoothFactor));
869 for(UINT i=0; i<N; i++) resultsData[i]=0.0;
871 if(smoothFactor==1 || M<smoothFactor){
876 for(UINT i=0; i<N; i++){
878 UINT index = i*smoothFactor;
879 for(UINT x=0; x<smoothFactor; x++){
880 mean += data[index+x];
882 resultsData[i] = mean/smoothFactor;
885 if(M%smoothFactor!=0.0){
887 for(UINT i=N*smoothFactor; i<M; i++) mean += data[i];
888 mean/=M-(N*smoothFactor);
891 for(UINT i=0; i<N; i++) tempVector[i] = resultsData[i];
892 tempVector[N] = mean;
893 resultsData = tempVector;
902 const UINT N = (UINT) floor(Float(M)/Float(smoothFactor));
905 if(smoothFactor==1 || M<smoothFactor){
910 for(UINT i=0; i<N; i++){
911 for(UINT j=0; j<C; j++){
913 int index = i*smoothFactor;
914 for(UINT x=0; x<smoothFactor; x++){
915 mean += data[index+x][j];
917 resultsData[i][j] = mean/smoothFactor;
922 if(M%smoothFactor!=0.0){
924 for(UINT j=0; j<C; j++){
925 for(UINT i=N*smoothFactor; i<M; i++) mean[j] += data[i][j];
926 mean[j]/=M-(N*smoothFactor);
932 for(UINT i=0; i<N; i++)
933 for(UINT j=0; j<C; j++)
934 tempMatrix[i][j] = resultsData[i][j];
936 for(UINT j=0; j<C; j++) tempMatrix[N][j] = mean[j];
937 resultsData = tempMatrix;
947 errorLog << __GRT_LOG__ <<
" Could not open file to save data" << std::endl;
951 file <<
"GRT_DTW_Model_File_V2.0" << std::endl;
955 errorLog << __GRT_LOG__ <<
" Failed to save classifier base settings to file!" << std::endl;
959 file <<
"DistanceMethod: ";
960 switch(distanceMethod){
962 file <<ABSOLUTE_DIST<< std::endl;
964 case(EUCLIDEAN_DIST):
965 file <<EUCLIDEAN_DIST<< std::endl;
968 file <<ABSOLUTE_DIST<< std::endl;
971 file <<
"UseSmoothing: "<<useSmoothing<< std::endl;
972 file <<
"SmoothingFactor: "<<smoothingFactor<< std::endl;
973 file <<
"UseZNormalisation: "<<useZNormalisation<< std::endl;
974 file <<
"OffsetUsingFirstSample: " << offsetUsingFirstSample << std::endl;
975 file <<
"ConstrainWarpingPath: " << constrainWarpingPath << std::endl;
976 file <<
"Radius: " << radius << std::endl;
977 file <<
"RejectionMode: " << rejectionMode<< std::endl;
980 file <<
"NumberOfTemplates: " << numTemplates << std::endl;
981 file <<
"OverallAverageTemplateLength: " << averageTemplateLength << std::endl;
983 for(UINT i=0; i<numTemplates; i++){
984 file <<
"***************TEMPLATE***************" << std::endl;
985 file <<
"Template: " << i+1 << std::endl;
986 file <<
"ClassLabel: " << templatesBuffer[i].classLabel << std::endl;
987 file <<
"TimeSeriesLength: " << templatesBuffer[i].timeSeries.getNumRows() << std::endl;
988 file <<
"TemplateThreshold: " << nullRejectionThresholds[i] << std::endl;
989 file <<
"TrainingMu: " << templatesBuffer[i].trainingMu << std::endl;
990 file <<
"TrainingSigma: " << templatesBuffer[i].trainingSigma << std::endl;
991 file <<
"AverageTemplateLength: " << templatesBuffer[i].averageTemplateLength << std::endl;
992 file <<
"TimeSeries: " << std::endl;
993 for(UINT k=0; k<templatesBuffer[i].timeSeries.getNumRows(); k++){
994 for(UINT j=0; j<templatesBuffer[i].timeSeries.getNumCols(); j++){
995 file << templatesBuffer[i].timeSeries[k][j] <<
"\t";
1008 UINT timeSeriesLength;
1013 errorLog << __GRT_LOG__ <<
" Failed to open file!" << std::endl;
1020 if( word ==
"GRT_DTW_Model_File_V1.0" ){
1021 return loadLegacyModelFromFile( file );
1025 if(word !=
"GRT_DTW_Model_File_V2.0"){
1026 errorLog << __GRT_LOG__ <<
" Unknown file header!" << std::endl;
1032 errorLog << __GRT_LOG__ <<
" Failed to load base settings from file!" << std::endl;
1038 if(word !=
"DistanceMethod:"){
1039 errorLog << __GRT_LOG__ <<
" Failed to find DistanceMethod!" << std::endl;
1042 file >> distanceMethod;
1046 if(word !=
"UseSmoothing:"){
1047 errorLog << __GRT_LOG__ <<
" Failed to find UseSmoothing!" << std::endl;
1050 file >> useSmoothing;
1054 if(word !=
"SmoothingFactor:"){
1055 errorLog << __GRT_LOG__ <<
" Failed to find SmoothingFactor!" << std::endl;
1058 file >> smoothingFactor;
1062 if(word !=
"UseZNormalisation:"){
1063 errorLog << __GRT_LOG__ <<
" Failed to find UseZNormalisation!" << std::endl;
1066 file >> useZNormalisation;
1070 if(word !=
"OffsetUsingFirstSample:"){
1071 errorLog << __GRT_LOG__ <<
" Failed to find OffsetUsingFirstSample!" << std::endl;
1074 file >> offsetUsingFirstSample;
1078 if(word !=
"ConstrainWarpingPath:"){
1079 errorLog << __GRT_LOG__ <<
" Failed to find ConstrainWarpingPath!" << std::endl;
1082 file >> constrainWarpingPath;
1086 if(word !=
"Radius:"){
1087 errorLog << __GRT_LOG__ <<
" Failed to find Radius!" << std::endl;
1094 if(word !=
"RejectionMode:"){
1095 errorLog << __GRT_LOG__ <<
" Failed to find RejectionMode!" << std::endl;
1098 file >> rejectionMode;
1104 if(word !=
"NumberOfTemplates:"){
1105 errorLog << __GRT_LOG__ <<
" Failed to find NumberOfTemplates!" << std::endl;
1108 file >> numTemplates;
1112 if(word !=
"OverallAverageTemplateLength:"){
1113 errorLog << __GRT_LOG__ <<
" Failed to find OverallAverageTemplateLength!" << std::endl;
1116 file >> averageTemplateLength;
1119 templatesBuffer.
resize(numTemplates);
1120 classLabels.
resize(numTemplates);
1121 nullRejectionThresholds.
resize(numTemplates);
1124 for(UINT i=0; i<numTemplates; i++){
1127 if( word !=
"***************TEMPLATE***************" ){
1129 errorLog << __GRT_LOG__ <<
" Failed to find template header!" << std::endl;
1135 if(word !=
"Template:"){
1137 errorLog << __GRT_LOG__ <<
" ailed to find Template Number!" << std::endl;
1145 errorLog << __GRT_LOG__ <<
" Invalid Template Number: " << ts << std::endl;
1151 if(word !=
"ClassLabel:"){
1153 errorLog << __GRT_LOG__ <<
" Failed to find ClassLabel!" << std::endl;
1156 file >> templatesBuffer[i].classLabel;
1157 classLabels[i] = templatesBuffer[i].classLabel;
1161 if(word !=
"TimeSeriesLength:"){
1163 errorLog << __GRT_LOG__ <<
" Failed to find TimeSeriesLength!" << std::endl;
1166 file >> timeSeriesLength;
1169 templatesBuffer[i].timeSeries.
resize(timeSeriesLength,numInputDimensions);
1173 if(word !=
"TemplateThreshold:"){
1175 errorLog << __GRT_LOG__ <<
" Failed to find TemplateThreshold!" << std::endl;
1178 file >> nullRejectionThresholds[i];
1182 if(word !=
"TrainingMu:"){
1184 errorLog << __GRT_LOG__ <<
" Failed to find TrainingMu!" << std::endl;
1187 file >> templatesBuffer[i].trainingMu;
1191 if(word !=
"TrainingSigma:"){
1193 errorLog << __GRT_LOG__ <<
" Failed to find TrainingSigma!" << std::endl;
1196 file >> templatesBuffer[i].trainingSigma;
1200 if(word !=
"AverageTemplateLength:"){
1202 errorLog << __GRT_LOG__ <<
" Failed to find AverageTemplateLength!" << std::endl;
1205 file >> templatesBuffer[i].averageTemplateLength;
1209 if(word !=
"TimeSeries:"){
1211 errorLog << __GRT_LOG__ <<
" Failed to find template timeseries!" << std::endl;
1214 for(UINT k=0; k<timeSeriesLength; k++)
1215 for(UINT j=0; j<numInputDimensions; j++)
1216 file >> templatesBuffer[i].timeSeries[k][j];
1220 continuousInputDataBuffer.
clear();
1221 continuousInputDataBuffer.
resize(averageTemplateLength,
VectorFloat(numInputDimensions,0));
1223 bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
1225 classDistances.
resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
1231 if( rejectionMode == TEMPLATE_THRESHOLDS || rejectionMode == CLASS_LIKELIHOODS || rejectionMode == THRESHOLDS_AND_LIKELIHOODS ){
1232 this->rejectionMode = rejectionMode;
1240 this->nullRejectionLikelihoodThreshold = nullRejectionLikelihoodThreshold;
1245 this->offsetUsingFirstSample = offsetUsingFirstSample;
1250 this->constrainWarpingPath = constrain;
1255 this->radius = radius;
1260 this->useZNormalisation = useZNormalisation;
1261 this->constrainZNorm = constrainZNorm;
1267 if( trimThreshold < 0 || trimThreshold > 1 ){
1268 warningLog << __GRT_LOG__ <<
" Failed to set trimTrainingData. The trimThreshold must be in the range of [0 1]" << std::endl;
1271 if( maximumTrimPercentage < 0 || maximumTrimPercentage > 100 ){
1272 warningLog << __GRT_LOG__ <<
" Failed to set trimTrainingData. The maximumTrimPercentage must be a valid percentage in the range of [0 100]" << std::endl;
1276 this->trimTrainingData = trimTrainingData;
1277 this->trimThreshold = trimThreshold;
1278 this->maximumTrimPercentage = maximumTrimPercentage;
1282 void DTW::offsetTimeseries(
MatrixFloat ×eries){
1284 for(UINT i=0; i<timeseries.
getNumRows(); i++){
1285 for(UINT j=0; j<timeseries.
getNumCols(); j++){
1286 timeseries[i][j] -= firstRow[j];
1291 bool DTW::loadLegacyModelFromFile( std::fstream &file ){
1294 UINT timeSeriesLength;
1299 if(word !=
"NumberOfDimensions:"){
1300 errorLog << __GRT_LOG__ <<
" Failed to find NumberOfDimensions!" << std::endl;
1303 file >> numInputDimensions;
1307 if(word !=
"NumberOfClasses:"){
1308 errorLog << __GRT_LOG__ <<
" Failed to find NumberOfClasses!" << std::endl;
1315 if(word !=
"NumberOfTemplates:"){
1316 errorLog << __GRT_LOG__ <<
" Failed to find NumberOfTemplates!" << std::endl;
1319 file >> numTemplates;
1323 if(word !=
"DistanceMethod:"){
1324 errorLog << __GRT_LOG__ <<
" Failed to find DistanceMethod!" << std::endl;
1327 file >> distanceMethod;
1331 if(word !=
"UseNullRejection:"){
1332 errorLog << __GRT_LOG__ <<
" Failed to find UseNullRejection!" << std::endl;
1335 file >> useNullRejection;
1339 if(word !=
"UseSmoothing:"){
1340 errorLog << __GRT_LOG__ <<
" Failed to find UseSmoothing!" << std::endl;
1343 file >> useSmoothing;
1347 if(word !=
"SmoothingFactor:"){
1348 errorLog << __GRT_LOG__ <<
" Failed to find SmoothingFactor!" << std::endl;
1351 file >> smoothingFactor;
1355 if(word !=
"UseScaling:"){
1356 errorLog << __GRT_LOG__ <<
" Failed to find UseScaling!" << std::endl;
1363 if(word !=
"UseZNormalisation:"){
1364 errorLog << __GRT_LOG__ <<
" Failed to find UseZNormalisation!" << std::endl;
1367 file >> useZNormalisation;
1371 if(word !=
"OffsetUsingFirstSample:"){
1372 errorLog << __GRT_LOG__ <<
" Failed to find OffsetUsingFirstSample!" << std::endl;
1375 file >> offsetUsingFirstSample;
1379 if(word !=
"ConstrainWarpingPath:"){
1380 errorLog << __GRT_LOG__ <<
" Failed to find ConstrainWarpingPath!" << std::endl;
1383 file >> constrainWarpingPath;
1387 if(word !=
"Radius:"){
1388 errorLog << __GRT_LOG__ <<
" Failed to find Radius!" << std::endl;
1395 if(word !=
"RejectionMode:"){
1396 errorLog << __GRT_LOG__ <<
" Failed to find RejectionMode!" << std::endl;
1399 file >> rejectionMode;
1403 if(word !=
"NullRejectionCoeff:"){
1404 errorLog << __GRT_LOG__ <<
" Failed to find NullRejectionCoeff!" << std::endl;
1407 file >> nullRejectionCoeff;
1411 if(word !=
"OverallAverageTemplateLength:"){
1412 errorLog << __GRT_LOG__ <<
" Failed to find OverallAverageTemplateLength!" << std::endl;
1415 file >> averageTemplateLength;
1418 templatesBuffer.
resize(numTemplates);
1419 classLabels.
resize(numTemplates);
1420 nullRejectionThresholds.
resize(numTemplates);
1423 for(UINT i=0; i<numTemplates; i++){
1426 while(word !=
"Template:"){
1435 errorLog << __GRT_LOG__ <<
" Failed to find Invalid Template Number!" << std::endl;
1441 if(word !=
"ClassLabel:"){
1444 errorLog << __GRT_LOG__ <<
" Failed to find ClassLabel!" << std::endl;
1447 file >> templatesBuffer[i].classLabel;
1448 classLabels[i] = templatesBuffer[i].classLabel;
1452 if(word !=
"TimeSeriesLength:"){
1455 errorLog << __GRT_LOG__ <<
" Failed to find TimeSeriesLength!" << std::endl;
1458 file >> timeSeriesLength;
1461 templatesBuffer[i].timeSeries.
resize(timeSeriesLength,numInputDimensions);
1465 if(word !=
"TemplateThreshold:"){
1468 errorLog << __GRT_LOG__ <<
" Failed to find TemplateThreshold!" << std::endl;
1471 file >> nullRejectionThresholds[i];
1475 if(word !=
"TrainingMu:"){
1478 errorLog << __GRT_LOG__ <<
" Failed to find TrainingMu!" << std::endl;
1481 file >> templatesBuffer[i].trainingMu;
1485 if(word !=
"TrainingSigma:"){
1488 errorLog << __GRT_LOG__ <<
" Failed to find TrainingSigma!" << std::endl;
1491 file >> templatesBuffer[i].trainingSigma;
1495 if(word !=
"AverageTemplateLength:"){
1498 errorLog << __GRT_LOG__ <<
" Failed to find AverageTemplateLength!" << std::endl;
1501 file >> templatesBuffer[i].averageTemplateLength;
1505 if(word !=
"TimeSeries:"){
1508 errorLog << __GRT_LOG__ <<
" Failed to find template timeseries!" << std::endl;
1511 for(UINT k=0; k<timeSeriesLength; k++)
1512 for(UINT j=0; j<numInputDimensions; j++)
1513 file >> templatesBuffer[i].timeSeries[k][j];
1517 if(word !=
"***************************"){
1520 numInputDimensions=0;
1522 errorLog << __GRT_LOG__ <<
" Failed to find template footer!" << std::endl;
1528 continuousInputDataBuffer.
clear();
1529 continuousInputDataBuffer.
resize(averageTemplateLength,
VectorFloat(numInputDimensions,0));
1531 bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
1533 classDistances.
resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
virtual bool predict_(VectorFloat &inputVector)
bool saveBaseSettingsToFile(std::fstream &file) const
bool push_back(const T &value)
virtual bool predict(VectorFloat inputVector)
#define DEFAULT_NULL_LIKELIHOOD_VALUE
virtual bool save(std::fstream &file) const
std::string getClassifierType() const
bool setRejectionMode(UINT rejectionMode)
bool setNumDimensions(const UINT numDimensions)
virtual bool train_(TimeSeriesClassificationData &trainingData)
virtual bool resize(const unsigned int size)
bool enableTrimTrainingData(bool trimTrainingData, Float trimThreshold, Float maximumTrimPercentage)
bool setContrainWarpingPath(bool constrain)
bool enableZNormalization(bool useZNormalization, bool constrainZNorm=true)
bool setWarpingRadius(Float radius)
DTW & operator=(const DTW &rhs)
Vector< MinMax > getRanges() const
bool setModels(Vector< DTWTemplate > newTemplates)
Vector< ClassTracker > getClassTracker() const
static std::string getId()
unsigned int getNumValuesInBuffer() const
bool copyBaseVariables(const Classifier *classifier)
bool loadBaseSettingsFromFile(std::fstream &file)
bool setNullRejectionThreshold(Float nullRejectionLikelihoodThreshold)
unsigned int getNumRows() const
unsigned int getNumCols() const
bool addSample(const UINT classLabel, const MatrixFloat &trainingSample)
virtual bool recomputeNullRejectionThresholds()
VectorFloat getRow(const unsigned int r) const
TimeSeriesClassificationData getClassData(const UINT classLabel) const
UINT getNumDimensions() const
DTW(bool useScaling=false, bool useNullRejection=false, Float nullRejectionCoeff=3.0, UINT rejectionMode=DTW::TEMPLATE_THRESHOLDS, bool dtwConstrain=true, Float radius=0.2, bool offsetUsingFirstSample=false, bool useSmoothing=false, UINT smoothingFactor=5, Float nullRejectionLikelihoodThreshold=0.99)
virtual bool deepCopyFrom(const Classifier *classifier)
virtual bool resize(const unsigned int r, const unsigned int c)
UINT getNumClasses() const
bool trimTimeSeries(TimeSeriesClassificationSample &timeSeries)
bool setOffsetTimeseriesUsingFirstSample(bool offsetUsingFirstSample)
UINT getNumSamples() const
virtual bool load(std::fstream &file)
This is the main base class that all GRT Classification algorithms should inherit from...
unsigned int getSize() const
bool resize(const unsigned int newBufferSize)