/** * @file seriesClassification.cpp * RapidLib * * @author Michael Zbyszynski * @date 08 Jun 2017 * @copyright Copyright © 2017 Goldsmiths. All rights reserved. */ #include #include #include #include #include "seriesClassification.h" #ifdef EMSCRIPTEN #include "emscripten/seriesClassificationEmbindings.h" #endif #define SEARCH_RADIUS 1 template seriesClassificationTemplate::seriesClassificationTemplate() : hopSize(1), counter(0) {}; template seriesClassificationTemplate::~seriesClassificationTemplate() {}; template bool seriesClassificationTemplate::train(const std::vector > &seriesSet) { assert(seriesSet.size() > 0); reset(); vectorLength = int(seriesSet[0].input[0].size()); //TODO: check that all vectors are the same size bool trained = true; allTrainingSeries = seriesSet; minLength = maxLength = int(allTrainingSeries[0].input.size()); for (int i = 0; i < allTrainingSeries.size(); ++i) { //for (auto trainingSeries : allTrainingSeries) //Global int newLength = int(allTrainingSeries[i].input.size()); if (newLength < minLength) { minLength = newLength; } if (newLength > maxLength) { maxLength = newLength; } //Per Label typename std::map >::iterator it = lengthsPerLabel.find(allTrainingSeries[i].label); if (it != lengthsPerLabel.end()) { int newLength = int(allTrainingSeries[i].input.size()); if (newLength < it->second.min) { it->second.min = newLength; } if (newLength > it->second.max) { it->second.max = newLength; } } else { minMax tempLengths; tempLengths.min = tempLengths.max = int(allTrainingSeries[i].input.size()); lengthsPerLabel[allTrainingSeries[i].label] = tempLengths; } } //TODO: make this size smarter? std::vector zeroVector; for (int i = 0; i < vectorLength; ++i) { zeroVector.push_back(0.0); } for (int i = 0; i < minLength; ++i ) { seriesBuffer.push_back(zeroVector); //set size of continuous buffer } return trained; }; template void seriesClassificationTemplate::reset() { allCosts.clear(); allTrainingSeries.clear(); lengthsPerLabel.clear(); minLength = -1; maxLength = -1; } template std::string seriesClassificationTemplate::run(const std::vector> &inputSeries) { //TODO: Check to see if trained int closestSeries = 0; allCosts.clear(); T lowestCost = fastDTW::getCost(inputSeries, allTrainingSeries[0].input, SEARCH_RADIUS); allCosts.push_back(lowestCost); for (int i = 1; i < allTrainingSeries.size(); ++i) { T currentCost = fastDTW::getCost(inputSeries, allTrainingSeries[i].input, SEARCH_RADIUS); allCosts.push_back(currentCost); if (currentCost < lowestCost) { lowestCost = currentCost; closestSeries = i; } } return allTrainingSeries[closestSeries].label; }; template T seriesClassificationTemplate::run(const std::vector> &inputSeries, std::string label) { //TODO: Check to see if trained int closestSeries = 0; allCosts.clear(); T lowestCost = std::numeric_limits::max(); for (int i = 0; i < allTrainingSeries.size(); ++i) { if (allTrainingSeries[i].label == label) { T currentCost = fastDTW::getCost(inputSeries, allTrainingSeries[i].input, SEARCH_RADIUS); allCosts.push_back(currentCost); if (currentCost < lowestCost) { lowestCost = currentCost; closestSeries = i; } } } return lowestCost; }; template std::string seriesClassificationTemplate::runContinuous(const std::vector &inputVector) { seriesBuffer.erase(seriesBuffer.begin()); seriesBuffer.push_back(inputVector); std::string returnString = "none"; if ((counter % hopSize) == 0 ) { returnString = run(seriesBuffer); counter = 0; } ++counter; return returnString; } template std::vector seriesClassificationTemplate::getCosts() const{ return allCosts; } template int seriesClassificationTemplate::getMinLength() const{ return minLength; } template int seriesClassificationTemplate::getMinLength(std::string label) const { int labelMinLength = -1; typename std::map >::const_iterator it = lengthsPerLabel.find(label); if (it != lengthsPerLabel.end()) { labelMinLength = it->second.min; } return labelMinLength; } template int seriesClassificationTemplate::getMaxLength() const { return maxLength; } template int seriesClassificationTemplate::getMaxLength(std::string label) const { int labelMaxLength = -1; typename std::map >::const_iterator it = lengthsPerLabel.find(label); if (it != lengthsPerLabel.end()) { labelMaxLength = it->second.max; } return labelMaxLength; } template typename seriesClassificationTemplate::template minMax seriesClassificationTemplate::calculateCosts(std::string label) const { minMax calculatedMinMax; bool foundSeries = false; std::vector labelCosts; for (int i = 0; i < (allTrainingSeries.size() - 1); ++i) { //these loops are a little different than the two-label case if (allTrainingSeries[i].label == label) { foundSeries = true; for (int j = (i + 1); j < allTrainingSeries.size(); ++j) { if (allTrainingSeries[j].label == label) { labelCosts.push_back(fastDTW::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS)); } } } } if (foundSeries) { auto minmax_result = std::minmax_element(std::begin(labelCosts), std::end(labelCosts)); calculatedMinMax.min = *minmax_result.first; calculatedMinMax.max = *minmax_result.second; } else { calculatedMinMax.min = calculatedMinMax.max = 0; } return calculatedMinMax; } template typename seriesClassificationTemplate::template minMax seriesClassificationTemplate::calculateCosts(std::string label1, std::string label2) const { minMax calculatedMinMax; bool foundSeries = false; std::vector labelCosts; for (int i = 0; i < (allTrainingSeries.size()); ++i) { if (allTrainingSeries[i].label == label1) { for (int j = 0; j < allTrainingSeries.size(); ++j) { if (allTrainingSeries[j].label == label2) { foundSeries = true; labelCosts.push_back(fastDTW::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS)); } } } } if (foundSeries) { auto minmax_result = std::minmax_element(std::begin(labelCosts), std::end(labelCosts)); calculatedMinMax.min = *minmax_result.first; calculatedMinMax.max = *minmax_result.second; } else { calculatedMinMax.min = calculatedMinMax.max = 0; } return calculatedMinMax; } //explicit instantiation template class seriesClassificationTemplate; template class seriesClassificationTemplate; // //std::vector seriesClassification::getCosts(const std::vector &trainingSet) { // run(trainingSet); // return allCosts; //}