#ifndef USINGPCA_H #define USINGPCA_H #include "pca/TrainPCA.h" #include "pca/KNN.h" #include "pca/aKNN.h" std::vector COLORS = {"#000000", "#0000ff", "#00ff00", "#ff0000", "#00ffff"}; struct Plot { K::Gnuplot gp; K::GnuplotSplot splot; K::GnuplotSplotElementLines lines[5]; public: Plot() { for (int i = 0; i < 5; ++i) {lines[i].setColorHex(COLORS[i]);} for (int i = 0; i < 5; ++i) {splot.add(&lines[i]);} } void add(int idx, std::vector& vec) { K::GnuplotPoint3 p3(vec[0], vec[1], vec[2]); lines[idx].add(p3); } void clear() { for (int i = 0; i < 5; ++i) {lines[i].clear();} } void show() { gp.setDebugOutput(false); gp.draw(splot); gp.flush(); } }; std::string getClass(const std::vector& nns) { std::unordered_map map; for(const ClassifiedFeature& nn : nns) { map[nn.className] += 1; } for (auto& it : map) { if (it.second > nns.size() * 0.75) {return it.first;} } return ""; } struct ClassStats { int counts[6] = {}; }; struct Stats{ int match; int error; int unknown; Stats() : match(0), error(0), unknown(0) {;} float getSum() {return match+error+unknown;} }; std::vector removePatterns(const std::vector& patAll, const std::string& fileName) { std::vector res; for (const ClassifiedPattern& pat : patAll) { if (pat.belongsToFile(fileName)) { continue; } else { res.push_back(pat); } } return res; } template struct PCA { aKNN knn; TrainPCA::Matrices m; }; void runPCA() { const int numFeatures = 10; TrainPCA::Settings setTrain; TrainPCA::Settings setClass; setClass.regionStart_ms += 25; Plot p; // convert all provided datasets into patterns std::vector srcTrain = TrainPCA::getAllData(setTrain); std::vector srcClass = TrainPCA::getAllData(setClass); std::cout << "windows: " << srcTrain.size() << std::endl; // error calculation std::unordered_map stats; std::unordered_map classStats; int xx = 0; std::unordered_map*> pcas; // try to classify each pattern for (const ClassifiedPattern& patClassify : srcClass) { // construct knn search for this leave-one-out ONLY ONCE if (pcas.find(patClassify.fileName) == pcas.end()) { std::cout << "constructing PCA for all files but " << patClassify.fileName << std::endl; // remove all training patterns belonging to the same source file as the to be classifed pattern std::vector srcTrainLOO = removePatterns(srcTrain, patClassify.fileName); // sanity check (have we removed all patterns?) int diff = srcTrain.size() - srcTrainLOO.size(); if (diff < 200) {throw 1;} p.clear(); PCA* pca = new PCA(); pcas[patClassify.fileName] = pca; // train PCA using all pattern without those belonging to the same source file as the to-be-classified one pca->m = TrainPCA::getMatrices(srcTrainLOO, numFeatures); // calculate features and add them to the KNN for (const ClassifiedPattern& pat : srcTrainLOO) { K::DynColVector vec = pca->m.A1 * K::PCAHelper::toVector(pat.pattern); std::vector arr; for (int i = 0; i < numFeatures; ++i) {arr.push_back(vec(i));} pca->knn.add(ClassifiedFeature(pat.className, arr)); const int idx = Settings::classToInt(pat.className); p.add(idx, arr); } pca->knn.build(); if (xx == 0) { ++xx; std::ofstream out("/tmp/pca.gp"); p.gp.draw(p.splot); out << p.gp.getBuffer(); out.close(); } //p.show(); //sleep(100); } { PCA* pca = pcas[patClassify.fileName]; // calculate features for the to-be-classified pattern //const int idx = Settings::classToInt(pat.className); K::DynColVector vec = pca->m.A1 * K::PCAHelper::toVector(patClassify.pattern); // get KNN's answer std::vector arr; for (int i = 0; i < numFeatures; ++i) {arr.push_back(vec(i));} std::vector neighbors = pca->knn.get(arr.data(), 5); std::string gotClass = getClass(neighbors); if (patClassify.className == gotClass) {stats["all"].match++; stats[patClassify.fileName].match++; stats[patClassify.className].match++;} else if (gotClass == "") {stats["all"].unknown++; stats[patClassify.fileName].unknown++; stats[patClassify.className].unknown++;} else {stats["all"].error++; stats[patClassify.fileName].error++; stats[patClassify.className].error++;} int gotIdx = (gotClass == "") ? (5) : Settings::classToInt(gotClass); ++classStats[patClassify.className].counts[gotIdx]; } } for (auto& it : stats) { Stats& stats = it.second; std::cout << "'" < #include "sensors/SensorReader.h" #include "Interpolator.h" #include enum class PracticeType { //REST, JUMPING_JACK, SITUPS, PUSHUPS, KNEEBEND, FORWARDBEND, }; struct Practice { PracticeType type; Recording rec; std::vector keyGyro; //Practice(const PracticeType p, const Recording& rec, const std::vector& keyGyro) : p(p), rec(rec), keyGyro(keyGyro) {;} K::Interpolator getInterpol() const { K::Interpolator interpol; for (auto it : rec.gyro.values) {interpol.add(it.ts, it.val);} interpol.makeRelative(); return interpol; } }; class UsingPCA { public: static Eigen::VectorXf getWindow(Practice& p, uint64_t pos) { K::Interpolator interpol = p.getInterpol(); Eigen::VectorXf vec(600/50*3, 1); int idx = 0; for (int offset = -300; offset < 300; offset += 50) { SensorGyro gyro = interpol.get(pos + offset); vec(idx++,0) = (gyro.x); vec(idx++,0) = (gyro.y); vec(idx++,0) = (gyro.z); } std::cout << vec << std::endl; return vec; } static std::vector getClassWindows(Practice& p) { std::vector windows; for (uint64_t pos = 1000; pos < 5000; pos += 500) { Eigen::VectorXf window = getWindow(p, pos); windows.push_back(window); } return windows; } static Eigen::MatrixXf getR(std::vector& vecs) { Eigen::MatrixXf mat = Eigen::MatrixXf::Zero(vecs[0].rows(), vecs[0].rows()); for (const Eigen::VectorXf& vec : vecs) { mat += vec * vec.transpose(); } mat /= vecs.size(); return mat; } static Eigen::VectorXf getM(std::vector& vecs) { Eigen::MatrixXf mat = Eigen::MatrixXf::Zero(vecs[0].rows(), vecs[0].cols()); for (const Eigen::VectorXf& vec : vecs) { mat += vec; } mat /= vecs.size(); return mat; } static void run() { std::vector practices; practices.push_back( Practice { PracticeType::JUMPING_JACK, SensorReader::read("/mnt/firma/kunden/HandyGames/daten/jumpingjack/jumpingjack_gl_5_subject_3_left.txt"), {1950, 2900, 3850, 4850, 5850, 6850, 7850, 8850, 9800, 10800, 11850} } ); std::vector windows = getClassWindows(practices.back()); Eigen::MatrixXf R = getR(windows); Eigen::MatrixXf m = getM(windows); Eigen::MatrixXf Q = R - (m * m.transpose()); Eigen::SelfAdjointEigenSolver es; es.compute(Q); int i = 0; } }; */ #endif // USINGPCA_H