From cac764534e886a01707d6fe13a8f31a042ac0ff1 Mon Sep 17 00:00:00 2001 From: lewardo Date: Wed, 9 Aug 2023 14:57:26 +0100 Subject: [PATCH 01/30] base PolynomialRegressor object --- .../algorithms/public/PolynomialRegressor.hpp | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 include/algorithms/public/PolynomialRegressor.hpp diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp new file mode 100644 index 000000000..0f9f09b24 --- /dev/null +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -0,0 +1,66 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#pragma once + +#include "../util/AlgorithmUtils.hpp" +#include "../util/FluidEigenMappings.hpp" +#include "../../data/FluidIndex.hpp" +#include "../../data/FluidMemory.hpp" +#include "../../data/TensorTypes.hpp" +#include +#include +#include + +namespace fluid { +namespace algorithm { + +template +class PolynomialRegressor +{ + using ArrayXd = Eigen::ArrayXd; + using ArrayXXd = Eigen::ArrayXXd; + + using MatrixXd = Eigen::MatrixXd; + using VectorXd = Eigen::VectorXd; + +public: + PolynomialRegressor() = default; + ~PolynomialRegressor() = default; + + void init(index degree) + { + mDegree = degree; + mInitialised = true; + }; + + index getDegree() const { return mDegree; }; + bool initialised() const { return mInitialised; }; + bool regressed() const { return mRegressed; }; + + RealVectorView getCoefficients() const + { + + }; + +private: + index mDegree {2}; + bool mInitialised {false}; + bool mRegressed {false}; + + VectorXd mCoefficients; + + mutable VectorXd mIn; + mutable VectorXd mOut; + +} + +} +} \ No newline at end of file From 430ac9c14b56e21308b368f736cb89efccb68218 Mon Sep 17 00:00:00 2001 From: lewardo Date: Wed, 9 Aug 2023 15:57:22 +0100 Subject: [PATCH 02/30] method call structure --- .../algorithms/public/PolynomialRegressor.hpp | 74 +++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 0f9f09b24..8a1368a7e 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -35,7 +35,7 @@ class PolynomialRegressor PolynomialRegressor() = default; ~PolynomialRegressor() = default; - void init(index degree) + void init(index degree = 2) { mDegree = degree; mInitialised = true; @@ -45,22 +45,86 @@ class PolynomialRegressor bool initialised() const { return mInitialised; }; bool regressed() const { return mRegressed; }; - RealVectorView getCoefficients() const + void setDegree(index degree) { + if(mDegree == degree) return; + + mDegree = degree; + resetMappingSpace(); + } + + void process(RealVectorView in, RealVectorView out) { + setMappingSpace(in, out); + process(); + }; + + void process() { + assert(mInSet && mOutSet && "input and output mapping must be set"); + + }; + void getCoefficients(RealVectorView coefficients) const + { + VectorXd output; + }; + void setMappingSpace(RealVectorView in, RealVectorView out) const + { + VectorXd input = asEigen(in); + VectorXd output = asEigen(out); + + setInputSpace(input); + setOutputSpace(output); + } + + void setMappingSpace(RealVectorView in, + RealVectorView out, + Allocator& alloc = FluidDefaultAllocator()) const + { + ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); + input = asEigen(in); + output = asEigen(in); + + setInputSpace(input); + setInputSpace(output); + }; + + void resetMappingSpace() const { mInSet = mOutSet = false; }; + private: + + void setInputSpace(Eigen::Ref in) const + { + mIn = in; + mInSet = true; + }; + + void setOutputSpace(Eigen::Ref out) const + { + mOut = out; + mOutSet = true; + }; + + void getRegressionCoefficients(Eigen::Ref coefficientsOut) + { + + }; + index mDegree {2}; bool mInitialised {false}; bool mRegressed {false}; - VectorXd mCoefficients; + bool mInSet {false}; + bool mOutSet {false}; mutable VectorXd mIn; mutable VectorXd mOut; + MatrixXd mDesignMatrix; + VectorXd mCoefficients; + } -} -} \ No newline at end of file +} // namespace algorithm +} // namespace fluid \ No newline at end of file From 3883e5c0b25d500e81b8cfb226bf470459952425 Mon Sep 17 00:00:00 2001 From: lewardo Date: Wed, 9 Aug 2023 16:34:14 +0100 Subject: [PATCH 03/30] design matrix construction --- include/algorithms/public/PolynomialRegressor.hpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 8a1368a7e..c058e2a8c 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -96,6 +96,15 @@ class PolynomialRegressor void setInputSpace(Eigen::Ref in) const { + VectorXd designColumn = VectorXd::Ones(in.size()); + ArrayXd inArray = in.array(); + mDesignMatrix.conservativeResize(in.size(), mDegree + 1); + + for(index i = 0; i < mDegree + 1; ++i) { + mDesignMatrix.col(i) = designColumn; + designColumn = designColumn.array() * inArray; + } + mIn = in; mInSet = true; }; @@ -108,7 +117,7 @@ class PolynomialRegressor void getRegressionCoefficients(Eigen::Ref coefficientsOut) { - + }; index mDegree {2}; From c633e494d390daf7f7c612b607fa37580f3145aa Mon Sep 17 00:00:00 2001 From: lewardo Date: Wed, 9 Aug 2023 16:50:19 +0100 Subject: [PATCH 04/30] linear algebra algorithm implementation --- .../algorithms/public/PolynomialRegressor.hpp | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index c058e2a8c..49dc37cd2 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -52,21 +52,22 @@ class PolynomialRegressor resetMappingSpace(); } - void process(RealVectorView in, RealVectorView out) { + void process(RealVectorView in, RealVectorView out) + { setMappingSpace(in, out); process(); }; void process() { - assert(mInSet && mOutSet && "input and output mapping must be set"); - + assert(mInSet && mOutSet); + calculateRegressionCoefficients(); }; void getCoefficients(RealVectorView coefficients) const { - VectorXd output; - + assert(mRegressed); + asEigen(coefficients) = mCoefficients; }; void setMappingSpace(RealVectorView in, RealVectorView out) const @@ -90,7 +91,7 @@ class PolynomialRegressor setInputSpace(output); }; - void resetMappingSpace() const { mInSet = mOutSet = false; }; + void resetMappingSpace() const { mInSet = mOutSet = mRegressed = false; }; private: @@ -107,17 +108,22 @@ class PolynomialRegressor mIn = in; mInSet = true; + mRegressed = false; }; void setOutputSpace(Eigen::Ref out) const { mOut = out; mOutSet = true; + mRegressed = false; }; - void getRegressionCoefficients(Eigen::Ref coefficientsOut) + void calculateRegressionCoefficients() { - + MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; + mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * mOut; + + mRegressed = true; }; index mDegree {2}; From 96f715c2b911245cdab6fbfc6497654b7f2d0c37 Mon Sep 17 00:00:00 2001 From: lewardo Date: Wed, 9 Aug 2023 17:05:51 +0100 Subject: [PATCH 05/30] copy constructor and assignment operator optimisations --- .../algorithms/public/PolynomialRegressor.hpp | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 49dc37cd2..b020aa702 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -32,9 +32,32 @@ class PolynomialRegressor using VectorXd = Eigen::VectorXd; public: - PolynomialRegressor() = default; + explicit PolynomialRegressor() = default; ~PolynomialRegressor() = default; + PolynomialRegressor(const PolynomialRegressor& other) + : mDegree {other.mDegree} + , mInitialised {true} + , mRegressed {true} + , mCoefficients {other.mCoefficients} + { + setInputSpace(other.mIn); + setOutputSpace(other.mOut); + }; + + PolynomialRegressor& operator=(const PolynomialRegressor& other) + { + mDegree = other.mDegree; + mInitialised = true; + mRegressed = true; + mCoefficients = other.mCoefficients; + + setInputSpace(other.mIn); + setOutputSpace(other.mOut); + + return *this; + } + void init(index degree = 2) { mDegree = degree; @@ -135,8 +158,8 @@ class PolynomialRegressor mutable VectorXd mIn; mutable VectorXd mOut; + mutable MatrixXd mDesignMatrix; - MatrixXd mDesignMatrix; VectorXd mCoefficients; } From 1719d8f7e6237087a7b0ebd2337971fb39c23e5b Mon Sep 17 00:00:00 2001 From: lewardo Date: Tue, 15 Aug 2023 10:02:52 +0100 Subject: [PATCH 06/30] getting obejct to show up in max (with lewardo/flucoma-max@02d3b22) --- FlucomaClients.cmake | 1 + .../algorithms/public/PolynomialRegressor.hpp | 206 +++++++++--------- .../clients/nrt/PolynomialRegressorClient.hpp | 148 +++++++++++++ 3 files changed, 257 insertions(+), 98 deletions(-) create mode 100644 include/clients/nrt/PolynomialRegressorClient.hpp diff --git a/FlucomaClients.cmake b/FlucomaClients.cmake index 2208b82b1..03ef5b659 100644 --- a/FlucomaClients.cmake +++ b/FlucomaClients.cmake @@ -156,5 +156,6 @@ add_client(PCA clients/nrt/PCAClient.hpp CLASS NRTThreadedPCAClient GROUP MANIPU add_client(MDS clients/nrt/MDSClient.hpp CLASS NRTThreadedMDSClient GROUP MANIPULATION) add_client(UMAP clients/nrt/UMAPClient.hpp CLASS NRTThreadedUMAPClient GROUP MANIPULATION) add_client(MLPRegressor clients/nrt/MLPRegressorClient.hpp CLASS NRTThreadedMLPRegressorClient GROUP MANIPULATION) +add_client(PolynomialRegressor clients/nrt/PolynomialRegressorClient.hpp CLASS NRTThreadedPolynomialRegressorClient GROUP MANIPULATION) add_client(MLPClassifier clients/nrt/MLPClassifierClient.hpp CLASS NRTThreadedMLPClassifierClient GROUP MANIPULATION) add_client(Grid clients/nrt/GridClient.hpp CLASS NRTThreadedGridClient GROUP MANIPULATION) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index b020aa702..e735cf7b4 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -22,50 +22,39 @@ under the European Union’s Horizon 2020 research and innovation programme namespace fluid { namespace algorithm { -template class PolynomialRegressor { - using ArrayXd = Eigen::ArrayXd; - using ArrayXXd = Eigen::ArrayXXd; - - using MatrixXd = Eigen::MatrixXd; - using VectorXd = Eigen::VectorXd; - public: explicit PolynomialRegressor() = default; ~PolynomialRegressor() = default; - PolynomialRegressor(const PolynomialRegressor& other) - : mDegree {other.mDegree} - , mInitialised {true} - , mRegressed {true} - , mCoefficients {other.mCoefficients} - { - setInputSpace(other.mIn); - setOutputSpace(other.mOut); - }; - - PolynomialRegressor& operator=(const PolynomialRegressor& other) - { - mDegree = other.mDegree; - mInitialised = true; - mRegressed = true; - mCoefficients = other.mCoefficients; + // PolynomialRegressor(const PolynomialRegressor& other) + // : mDegree {other.mDegree} + // , mRegressed {true} + // , mCoefficients {other.mCoefficients} + // { + // setInputSpace(other.mIn); + // setOutputSpace(other.mOut); + // }; + + // PolynomialRegressor& operator=(const PolynomialRegressor& other) + // { + // mDegree = other.mDegree; + // mRegressed = true; + // mCoefficients = other.mCoefficients; - setInputSpace(other.mIn); - setOutputSpace(other.mOut); + // setInputSpace(other.mIn); + // setOutputSpace(other.mOut); - return *this; - } + // return *this; + // } void init(index degree = 2) { mDegree = degree; - mInitialised = true; }; index getDegree() const { return mDegree; }; - bool initialised() const { return mInitialised; }; bool regressed() const { return mRegressed; }; void setDegree(index degree) { @@ -75,94 +64,115 @@ class PolynomialRegressor resetMappingSpace(); } - void process(RealVectorView in, RealVectorView out) - { - setMappingSpace(in, out); - process(); - }; + // void process(RealVectorView in, RealVectorView out) + // { + // setMappingSpace(in, out); + // process(); + // }; - void process() - { - assert(mInSet && mOutSet); - calculateRegressionCoefficients(); - }; + // void process() + // { + // assert(mInSet && mOutSet); + // calculateRegressionCoefficients(); + // }; - void getCoefficients(RealVectorView coefficients) const - { - assert(mRegressed); - asEigen(coefficients) = mCoefficients; - }; + // void getCoefficients(RealVectorView coefficients) const + // { + // using namespace _impl; - void setMappingSpace(RealVectorView in, RealVectorView out) const - { - VectorXd input = asEigen(in); - VectorXd output = asEigen(out); + // assert(mRegressed); - setInputSpace(input); - setOutputSpace(output); - } + // asEigen(coefficients) = mCoefficients; + // }; - void setMappingSpace(RealVectorView in, - RealVectorView out, - Allocator& alloc = FluidDefaultAllocator()) const - { - ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); - input = asEigen(in); - output = asEigen(in); + // void getMappedSpace(InputRealVectorView in, + // RealVectorView out, + // Allocator& alloc = FluidDefaultAllocator()) const + // { + // using namespace _impl; - setInputSpace(input); - setInputSpace(output); - }; + // assert(mRegressed); - void resetMappingSpace() const { mInSet = mOutSet = mRegressed = false; }; + // ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); + // input = asEigen(in); + // output = asEigen(in); -private: + // calculateMappings(input, output); - void setInputSpace(Eigen::Ref in) const - { - VectorXd designColumn = VectorXd::Ones(in.size()); - ArrayXd inArray = in.array(); - mDesignMatrix.conservativeResize(in.size(), mDegree + 1); - - for(index i = 0; i < mDegree + 1; ++i) { - mDesignMatrix.col(i) = designColumn; - designColumn = designColumn.array() * inArray; - } - - mIn = in; - mInSet = true; - mRegressed = false; - }; + // asEigen(out) = output; + // } - void setOutputSpace(Eigen::Ref out) const - { - mOut = out; - mOutSet = true; - mRegressed = false; - }; + // void setMappingSpace(InputRealVectorView in, + // InputRealVectorView out, + // Allocator& alloc = FluidDefaultAllocator()) const + // { + // using namespace _impl; - void calculateRegressionCoefficients() - { - MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; - mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * mOut; + // ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); + // input = asEigen(in); + // output = asEigen(in); - mRegressed = true; - }; + // setInputSpace(input); + // setInputSpace(output); + // }; + + void resetMappingSpace() { mInSet = mOutSet = mRegressed = false; }; + +private: + + // void setInputSpace(Eigen::Ref in) + // { + // mIn = in; + // mInSet = true; + // mRegressed = false; + // }; + + // void setOutputSpace(Eigen::Ref out) + // { + // mOut = out; + // mOutSet = true; + // mRegressed = false; + // }; + + // void calculateRegressionCoefficients() + // { + // generateDesignMatrix(mIn); + + // Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; + // mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * mOut; + + // mRegressed = true; + // }; + + // void calculateMappings(Eigen::Ref in, Eigen::Ref out) const + // { + // generateDesignMatrix(in); + // out = mDesignMatrix * mCoefficients; + // } + + // void generateDesignMatrix(Eigen::Ref in) const + // { + // Eigen::VectorXd designColumn = Eigen::VectorXd::Ones(in.size()); + // Eigen::ArrayXd inArray = in.array(); + // mDesignMatrix.conservativeResize(in.size(), mDegree + 1); + + // for(index i = 0; i < mDegree + 1; ++i, designColumn = designColumn.array() * inArray) + // mDesignMatrix.col(i) = designColumn; + // } index mDegree {2}; - bool mInitialised {false}; bool mRegressed {false}; - bool mInSet {false}; - bool mOutSet {false}; + bool mInSet {false}; + bool mOutSet{false}; - mutable VectorXd mIn; - mutable VectorXd mOut; - mutable MatrixXd mDesignMatrix; + Eigen::VectorXd mIn; + Eigen::VectorXd mOut; + mutable Eigen::MatrixXd mDesignMatrix; - VectorXd mCoefficients; + Eigen::VectorXd mCoefficients; -} +}; } // namespace algorithm } // namespace fluid \ No newline at end of file diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp new file mode 100644 index 000000000..40369fe20 --- /dev/null +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -0,0 +1,148 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#pragma once + +#include "DataSetClient.hpp" +#include "NRTClient.hpp" + +#include "../../algorithms/public/PolynomialRegressor.hpp" + +namespace fluid { +namespace client { +namespace polynomialregressor { + +constexpr auto PolynomialRegressorParams = defineParameters( + StringParam>("name", "Name"), + LongParam("degree", "Degree of fit polynomial", 2, Min(0)) +); + +class PolynomialRegressorClient : public FluidBaseClient, + OfflineIn, + OfflineOut, + ModelObject, + public DataClient +{ + enum { + kName, + kDegree + }; + +public: + using string = std::string; + using BufferPtr = std::shared_ptr; + using InputBufferPtr = std::shared_ptr; + using DataSet = FluidDataSet; + using StringVector = FluidTensor; + + using ParamDescType = decltype(PolynomialRegressorParams); + + using ParamSetViewType = ParameterSetView; + using ParamValues = typename ParamSetViewType::ValueTuple; + + std::reference_wrapper mParams; + + void setParams(ParamSetViewType& p) { mParams = p; } + + template + auto& get() const + { + return mParams.get().template get(); + } + + static constexpr auto& getParameterDescriptors() + { + return PolynomialRegressorParams; + } + + PolynomialRegressorClient(ParamSetViewType& p, FluidContext&) : mParams(p) {} + + template + Result process(FluidContext&) + { + return {}; + } + + MessageResult fit() + { + return OK(); + } + + static auto getMessageDescriptors() + { + return defineMessages( + makeMessage("fit", &PolynomialRegressorClient::fit)); + } + +private: + MessageResult updateParameters() + { + return ParamValues {mParams.get().toTuple()}; + } + +}; + +using PolynomialRegressorRef = SharedClientRef; + +constexpr auto PolynomialRegressorQueryParams = + defineParameters(PolynomialRegressorRef::makeParam("model", "Source Model"), + LongParam("degree", "Prediction Polynomial Degree", 2, Min(0) ), + InputBufferParam("inputPointBuffer", "Input Point Buffer"), + BufferParam("predictionBuffer", "Prediction Buffer")); + +class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut +{ + enum { kModel, kDegree, kInputBuffer, kOutputBuffer }; + +public: + using ParamDescType = decltype(PolynomialRegressorQueryParams); + + using ParamSetViewType = ParameterSetView; + std::reference_wrapper mParams; + + void setParams(ParamSetViewType& p) { mParams = p; } + + template + auto& get() const + { + return mParams.get().template get(); + } + + static constexpr auto& getParameterDescriptors() + { + return PolynomialRegressorQueryParams; + } + + PolynomialRegressorQuery(ParamSetViewType& p, FluidContext&) : mParams(p) + { + controlChannelsIn(1); + controlChannelsOut({1, 1}); + } + + template + void process(std::vector>& input, + std::vector>& output, FluidContext&) + { + + } + + index latency() { return 0; } +}; + +} // namespace polynomialregressor + +using NRTThreadedPolynomialRegressorClient = + NRTThreadingAdaptor; + +using RTPolynomialRegressorQueryClient = + ClientWrapper; + +} // namespace client +} // namespace fluid \ No newline at end of file From c3fa23acbf9735d90670edfaade16794568ccaf6 Mon Sep 17 00:00:00 2001 From: lewardo Date: Thu, 17 Aug 2023 16:02:20 +0100 Subject: [PATCH 07/30] temporary commit --- FlucomaClients.cmake | 3 +- .../algorithms/public/PolynomialRegressor.hpp | 198 ++++++++---------- .../clients/nrt/PolynomialRegressorClient.hpp | 86 +++++--- 3 files changed, 155 insertions(+), 132 deletions(-) diff --git a/FlucomaClients.cmake b/FlucomaClients.cmake index 03ef5b659..78bcd3678 100644 --- a/FlucomaClients.cmake +++ b/FlucomaClients.cmake @@ -140,6 +140,8 @@ add_kr_in_client(Stats clients/rt/RunningStatsClient.hpp CLASS RunningStatsClien add_client(TransientSlice clients/rt/TransientSliceClient.hpp CLASS RTTransientSliceClient ) add_client(Transients clients/rt/TransientClient.hpp CLASS RTTransientClient ) +add_client(PolynomialRegressor clients/nrt/PolynomialRegressorClient.hpp CLASS NRTThreadedPolynomialRegressorClient ) + #lib manipulation client group add_client(DataSet clients/nrt/DataSetClient.hpp CLASS NRTThreadedDataSetClient GROUP MANIPULATION) add_client(DataSetQuery clients/nrt/DataSetQueryClient.hpp CLASS NRTThreadedDataSetQueryClient GROUP MANIPULATION) @@ -156,6 +158,5 @@ add_client(PCA clients/nrt/PCAClient.hpp CLASS NRTThreadedPCAClient GROUP MANIPU add_client(MDS clients/nrt/MDSClient.hpp CLASS NRTThreadedMDSClient GROUP MANIPULATION) add_client(UMAP clients/nrt/UMAPClient.hpp CLASS NRTThreadedUMAPClient GROUP MANIPULATION) add_client(MLPRegressor clients/nrt/MLPRegressorClient.hpp CLASS NRTThreadedMLPRegressorClient GROUP MANIPULATION) -add_client(PolynomialRegressor clients/nrt/PolynomialRegressorClient.hpp CLASS NRTThreadedPolynomialRegressorClient GROUP MANIPULATION) add_client(MLPClassifier clients/nrt/MLPClassifierClient.hpp CLASS NRTThreadedMLPClassifierClient GROUP MANIPULATION) add_client(Grid clients/nrt/GridClient.hpp CLASS NRTThreadedGridClient GROUP MANIPULATION) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index e735cf7b4..01536fb46 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -28,140 +28,128 @@ class PolynomialRegressor explicit PolynomialRegressor() = default; ~PolynomialRegressor() = default; - // PolynomialRegressor(const PolynomialRegressor& other) - // : mDegree {other.mDegree} - // , mRegressed {true} - // , mCoefficients {other.mCoefficients} - // { - // setInputSpace(other.mIn); - // setOutputSpace(other.mOut); - // }; - - // PolynomialRegressor& operator=(const PolynomialRegressor& other) - // { - // mDegree = other.mDegree; - // mRegressed = true; - // mCoefficients = other.mCoefficients; - - // setInputSpace(other.mIn); - // setOutputSpace(other.mOut); - - // return *this; - // } - void init(index degree = 2) { + mInitialized = true; mDegree = degree; }; - index getDegree() const { return mDegree; }; - bool regressed() const { return mRegressed; }; + index size() const { return asSigned(mInSet ? mIn.size() : 0); }; + index dims() const { return size(); }; + + void clear() + { + mInSet = mOutSet = mRegressed = false; + } + + index getDegree() const { return asSigned(mDegree); }; + bool regressed() const { return mRegressed; }; + bool initialized() const { return mInitialized; }; void setDegree(index degree) { - if(mDegree == degree) return; + if (mDegree == degree) + return; mDegree = degree; - resetMappingSpace(); + resetMappingSpace(); } - // void process(RealVectorView in, RealVectorView out) - // { - // setMappingSpace(in, out); - // process(); - // }; - - // void process() - // { - // assert(mInSet && mOutSet); - // calculateRegressionCoefficients(); - // }; - - // void getCoefficients(RealVectorView coefficients) const - // { - // using namespace _impl; + void process(RealVectorView in, RealVectorView out) + { + setMappingSpace(in, out); + process(); + }; - // assert(mRegressed); + void process() + { + assert(mInSet && mOutSet); + calculateRegressionCoefficients(); + }; - // asEigen(coefficients) = mCoefficients; - // }; + void getCoefficients(RealVectorView coefficients) const + { + assert(mRegressed); + _impl::asEigen(coefficients) = mCoefficients; + }; - // void getMappedSpace(InputRealVectorView in, - // RealVectorView out, - // Allocator& alloc = FluidDefaultAllocator()) const - // { - // using namespace _impl; + void getMappedSpace(InputRealVectorView in, + RealVectorView out, + Allocator& alloc = FluidDefaultAllocator()) const + { + using namespace _impl; - // assert(mRegressed); + assert(mRegressed); - // ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); - // input = asEigen(in); - // output = asEigen(in); + ScopedEigenMap input(in.size(), alloc), + output(out.size(), alloc); + input = asEigen(in); + output = asEigen(in); - // calculateMappings(input, output); + calculateMappings(input, output); - // asEigen(out) = output; - // } + asEigen(out) = output; + } - // void setMappingSpace(InputRealVectorView in, - // InputRealVectorView out, - // Allocator& alloc = FluidDefaultAllocator()) const - // { - // using namespace _impl; + void setMappingSpace(InputRealVectorView in, + InputRealVectorView out, + Allocator& alloc = FluidDefaultAllocator()) + { + using namespace _impl; - // ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); - // input = asEigen(in); - // output = asEigen(in); + ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); + input = asEigen(in); + output = asEigen(in); - // setInputSpace(input); - // setInputSpace(output); - // }; + setInputSpace(input); + setOutputSpace(output); + }; void resetMappingSpace() { mInSet = mOutSet = mRegressed = false; }; private: + void setInputSpace(Eigen::Ref in) + { + mIn = in; + mInSet = true; + mRegressed = false; + }; + + void setOutputSpace(Eigen::Ref out) + { + mOut = out; + mOutSet = true; + mRegressed = false; + }; + + void calculateRegressionCoefficients() + { + generateDesignMatrix(mIn); + + Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; + mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * mOut; - // void setInputSpace(Eigen::Ref in) - // { - // mIn = in; - // mInSet = true; - // mRegressed = false; - // }; - - // void setOutputSpace(Eigen::Ref out) - // { - // mOut = out; - // mOutSet = true; - // mRegressed = false; - // }; - - // void calculateRegressionCoefficients() - // { - // generateDesignMatrix(mIn); - - // Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; - // mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * mOut; - - // mRegressed = true; - // }; - - // void calculateMappings(Eigen::Ref in, Eigen::Ref out) const - // { - // generateDesignMatrix(in); - // out = mDesignMatrix * mCoefficients; - // } - - // void generateDesignMatrix(Eigen::Ref in) const - // { - // Eigen::VectorXd designColumn = Eigen::VectorXd::Ones(in.size()); - // Eigen::ArrayXd inArray = in.array(); - // mDesignMatrix.conservativeResize(in.size(), mDegree + 1); - - // for(index i = 0; i < mDegree + 1; ++i, designColumn = designColumn.array() * inArray) - // mDesignMatrix.col(i) = designColumn; - // } + mRegressed = true; + }; + + void calculateMappings(Eigen::Ref in, Eigen::Ref out) const + { + generateDesignMatrix(in); + out = mDesignMatrix * mCoefficients; + } + + void generateDesignMatrix(Eigen::Ref in) const + { + Eigen::VectorXd designColumn = Eigen::VectorXd::Ones(in.size()); + Eigen::ArrayXd inArray = in.array(); + mDesignMatrix.conservativeResize(in.size(), mDegree + 1); + + for(index i = 0; i < mDegree + 1; ++i, designColumn = designColumn.array() * inArray) + mDesignMatrix.col(i) = designColumn; + } index mDegree {2}; bool mRegressed {false}; + bool mInitialized {false}; bool mInSet {false}; bool mOutSet{false}; diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 40369fe20..1af68f33f 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -25,10 +25,10 @@ constexpr auto PolynomialRegressorParams = defineParameters( ); class PolynomialRegressorClient : public FluidBaseClient, - OfflineIn, - OfflineOut, - ModelObject, - public DataClient + OfflineIn, + OfflineOut, + ModelObject, + public DataClient { enum { kName, @@ -43,9 +43,7 @@ class PolynomialRegressorClient : public FluidBaseClient, using StringVector = FluidTensor; using ParamDescType = decltype(PolynomialRegressorParams); - using ParamSetViewType = ParameterSetView; - using ParamValues = typename ParamSetViewType::ValueTuple; std::reference_wrapper mParams; @@ -61,8 +59,13 @@ class PolynomialRegressorClient : public FluidBaseClient, { return PolynomialRegressorParams; } - - PolynomialRegressorClient(ParamSetViewType& p, FluidContext&) : mParams(p) {} + +// c.allocator(); + PolynomialRegressorClient(ParamSetViewType& p, FluidContext& c) : mParams(p) + { + audioChannelsIn(1); + controlChannelsOut({1, 1}); + } template Result process(FluidContext&) @@ -70,32 +73,58 @@ class PolynomialRegressorClient : public FluidBaseClient, return {}; } - MessageResult fit() + MessageResult fit(InputDataSetClientRef source, + InputDataSetClientRef target) { - return OK(); + auto sourceClientPtr = source.get().lock(); + if (!sourceClientPtr) return Error(NoDataSet); + + auto sourceDataSet = sourceClientPtr->getDataSet(); + if (sourceDataSet.size() == 0) return Error(EmptyDataSet); + + if (sourceDataSet.dims() != 1) + return Error(DimensionsDontMatch); + + auto targetClientPtr = target.get().lock(); + if (!targetClientPtr) return Error(NoDataSet); + auto targetDataSet = targetClientPtr->getDataSet(); + if (targetDataSet.size() == 0) return Error(EmptyDataSet); + if (sourceDataSet.size() != targetDataSet.size()) + return Error(SizesDontMatch); + + if (!mAlgorithm.initialized()) + mAlgorithm.init(); + + auto data = sourceDataSet.getData(); + auto tgt = targetDataSet.getData().col(0); + + string res = " "; + + for (auto& x : data) { + res += std::to_string(x); + } + + return res.c_str(); } static auto getMessageDescriptors() { return defineMessages( - makeMessage("fit", &PolynomialRegressorClient::fit)); + makeMessage("fit", &PolynomialRegressorClient::fit), + makeMessage("cols", &PolynomialRegressorClient::dims), + makeMessage("clear", &PolynomialRegressorClient::clear), + makeMessage("size", &PolynomialRegressorClient::size)); } - -private: - MessageResult updateParameters() - { - return ParamValues {mParams.get().toTuple()}; - } - }; using PolynomialRegressorRef = SharedClientRef; -constexpr auto PolynomialRegressorQueryParams = - defineParameters(PolynomialRegressorRef::makeParam("model", "Source Model"), - LongParam("degree", "Prediction Polynomial Degree", 2, Min(0) ), - InputBufferParam("inputPointBuffer", "Input Point Buffer"), - BufferParam("predictionBuffer", "Prediction Buffer")); +constexpr auto PolynomialRegressorQueryParams = defineParameters( + PolynomialRegressorRef::makeParam("model", "Source Model"), + LongParam("degree", "Prediction Polynomial Degree", 2, Min(0) ), + InputDataSetClientRef::makeParam("dataSet", "DataSet Name"), + InputBufferParam("inputPointBuffer", "Input Point Buffer"), + BufferParam("predictionBuffer", "Prediction Buffer")); class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut { @@ -103,8 +132,8 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut public: using ParamDescType = decltype(PolynomialRegressorQueryParams); - using ParamSetViewType = ParameterSetView; + std::reference_wrapper mParams; void setParams(ParamSetViewType& p) { mParams = p; } @@ -120,7 +149,8 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut return PolynomialRegressorQueryParams; } - PolynomialRegressorQuery(ParamSetViewType& p, FluidContext&) : mParams(p) + PolynomialRegressorQuery(ParamSetViewType& p, FluidContext& c) + : mParams(p), mRTBuffer(c.allocator()) { controlChannelsIn(1); controlChannelsOut({1, 1}); @@ -128,12 +158,16 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut template void process(std::vector>& input, - std::vector>& output, FluidContext&) + std::vector>& output, FluidContext& c) { } index latency() { return 0; } + +private: + RealVector mRTBuffer; + InputDataSetClientRef mDataSetClient; }; } // namespace polynomialregressor From 3997c5bbeca29368d89173e498b591f90ae1d789 Mon Sep 17 00:00:00 2001 From: lewardo Date: Thu, 17 Aug 2023 16:06:29 +0100 Subject: [PATCH 08/30] client update test --- FlucomaClients.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FlucomaClients.cmake b/FlucomaClients.cmake index 78bcd3678..2958a825f 100644 --- a/FlucomaClients.cmake +++ b/FlucomaClients.cmake @@ -140,7 +140,6 @@ add_kr_in_client(Stats clients/rt/RunningStatsClient.hpp CLASS RunningStatsClien add_client(TransientSlice clients/rt/TransientSliceClient.hpp CLASS RTTransientSliceClient ) add_client(Transients clients/rt/TransientClient.hpp CLASS RTTransientClient ) -add_client(PolynomialRegressor clients/nrt/PolynomialRegressorClient.hpp CLASS NRTThreadedPolynomialRegressorClient ) #lib manipulation client group add_client(DataSet clients/nrt/DataSetClient.hpp CLASS NRTThreadedDataSetClient GROUP MANIPULATION) @@ -160,3 +159,4 @@ add_client(UMAP clients/nrt/UMAPClient.hpp CLASS NRTThreadedUMAPClient GROUP MAN add_client(MLPRegressor clients/nrt/MLPRegressorClient.hpp CLASS NRTThreadedMLPRegressorClient GROUP MANIPULATION) add_client(MLPClassifier clients/nrt/MLPClassifierClient.hpp CLASS NRTThreadedMLPClassifierClient GROUP MANIPULATION) add_client(Grid clients/nrt/GridClient.hpp CLASS NRTThreadedGridClient GROUP MANIPULATION) +add_client(PolynomialRegressor clients/nrt/PolynomialRegressorClient.hpp CLASS NRTThreadedPolynomialRegressorClient GROUP MANIPULATION) From 971dce87903a798e8c6c679a20a0eeb49ff24af5 Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 11:47:36 +0100 Subject: [PATCH 09/30] json functions now configured --- .../algorithms/public/PolynomialRegressor.hpp | 22 +++++----- .../clients/nrt/PolynomialRegressorClient.hpp | 44 ++++++++++++------- include/data/FluidJSON.hpp | 25 +++++++++++ 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 01536fb46..e59d46caa 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -34,13 +34,10 @@ class PolynomialRegressor mDegree = degree; }; - index size() const { return asSigned(mInSet ? mIn.size() : 0); }; - index dims() const { return size(); }; + index size() const { return asSigned(mInSet ? mIn.size() : 1); }; + index dims() const { return asSigned(mInSet ? mIn.size() : 0); }; - void clear() - { - mInSet = mOutSet = mRegressed = false; - } + void clear() { mInSet = mOutSet = mRegressed = false; } index getDegree() const { return asSigned(mDegree); }; bool regressed() const { return mRegressed; }; @@ -51,7 +48,7 @@ class PolynomialRegressor return; mDegree = degree; - resetMappingSpace(); + clear(); } void process(RealVectorView in, RealVectorView out) @@ -72,6 +69,13 @@ class PolynomialRegressor _impl::asEigen(coefficients) = mCoefficients; }; + void setCoefficients(InputRealVectorView coefficients) + { + mCoefficients = _impl::asEigen(coefficients); + setDegree(coefficients.size() - 1); + mRegressed = true; + } + void getMappedSpace(InputRealVectorView in, RealVectorView out, Allocator& alloc = FluidDefaultAllocator()) const @@ -104,8 +108,6 @@ class PolynomialRegressor setOutputSpace(output); }; - void resetMappingSpace() { mInSet = mOutSet = mRegressed = false; }; - private: void setInputSpace(Eigen::Ref in) { @@ -160,7 +162,7 @@ class PolynomialRegressor Eigen::VectorXd mCoefficients; -}; +}; } // namespace algorithm } // namespace fluid \ No newline at end of file diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 1af68f33f..ed80b27df 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -73,47 +73,63 @@ class PolynomialRegressorClient : public FluidBaseClient, return {}; } - MessageResult fit(InputDataSetClientRef source, + MessageResult fit(InputDataSetClientRef source, InputDataSetClientRef target) { auto sourceClientPtr = source.get().lock(); if (!sourceClientPtr) return Error(NoDataSet); - auto sourceDataSet = sourceClientPtr->getDataSet(); if (sourceDataSet.size() == 0) return Error(EmptyDataSet); - if (sourceDataSet.dims() != 1) return Error(DimensionsDontMatch); - auto targetClientPtr = target.get().lock(); if (!targetClientPtr) return Error(NoDataSet); auto targetDataSet = targetClientPtr->getDataSet(); if (targetDataSet.size() == 0) return Error(EmptyDataSet); if (sourceDataSet.size() != targetDataSet.size()) return Error(SizesDontMatch); - if (!mAlgorithm.initialized()) mAlgorithm.init(); - auto data = sourceDataSet.getData(); + auto data = sourceDataSet.getData().col(0); auto tgt = targetDataSet.getData().col(0); + // mAlgorithm.setMappingSpace(data, tgt); + string res = " "; for (auto& x : data) { res += std::to_string(x); + res += "\t"; } - return res.c_str(); + return res; + } + + MessageResult map(InputBufferPtr in, BufferPtr out) + { + return OK(); + } + + + MessageResult print() + { + return "deez nuts"; } static auto getMessageDescriptors() { return defineMessages( - makeMessage("fit", &PolynomialRegressorClient::fit), - makeMessage("cols", &PolynomialRegressorClient::dims), - makeMessage("clear", &PolynomialRegressorClient::clear), - makeMessage("size", &PolynomialRegressorClient::size)); + makeMessage("fit", &PolynomialRegressorClient::fit), + makeMessage("dims", &PolynomialRegressorClient::dims), + makeMessage("clear", &PolynomialRegressorClient::clear), + makeMessage("size", &PolynomialRegressorClient::size), + makeMessage("print", &PolynomialRegressorClient::print), + makeMessage("map", &PolynomialRegressorClient::map), + makeMessage("load", &PolynomialRegressorClient::load), + makeMessage("dump", &PolynomialRegressorClient::dump), + makeMessage("write", &PolynomialRegressorClient::write), + makeMessage("read", &PolynomialRegressorClient::read)); } }; @@ -150,7 +166,7 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut } PolynomialRegressorQuery(ParamSetViewType& p, FluidContext& c) - : mParams(p), mRTBuffer(c.allocator()) + : mParams(p) { controlChannelsIn(1); controlChannelsOut({1, 1}); @@ -164,10 +180,6 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut } index latency() { return 0; } - -private: - RealVector mRTBuffer; - InputDataSetClientRef mDataSetClient; }; } // namespace polynomialregressor diff --git a/include/data/FluidJSON.hpp b/include/data/FluidJSON.hpp index 0cdd5ede4..205f3dba2 100644 --- a/include/data/FluidJSON.hpp +++ b/include/data/FluidJSON.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -473,6 +474,30 @@ void from_json(const nlohmann::json &j, UMAP &umap) { umap.init(embedding, tree, k, a, b); } +// PolynomialRegressor +void to_json(nlohmann::json &j, const PolynomialRegressor ®) { + RealVector coefficients(reg.getDegree()); + + reg.getCoefficients(coefficients); + + j["degree"] = reg.getDegree(); + j["coefficients"] = RealVectorView(coefficients); +} + +bool check_json(const nlohmann::json &j, const PolynomialRegressor &) { + return fluid::check_json(j, + {"degree", "coefficients"}, + {JSONTypes::NUMBER, JSONTypes::OBJECT} + ); +} + +void from_json(const nlohmann::json &j, PolynomialRegressor ®) { + reg.setDegree(j.at("degree").get()); + + RealVector embedding(reg.getDegree() + 1); + j.at("coefficients").get_to(embedding); +} + } // namespace algorithm class JSONFile { From b6a3701d1a6e8bcc41875995e2f5241308554ece Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 13:50:23 +0100 Subject: [PATCH 10/30] init method for setting initial value on load --- include/data/FluidJSON.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/data/FluidJSON.hpp b/include/data/FluidJSON.hpp index 205f3dba2..95b3c6ba8 100644 --- a/include/data/FluidJSON.hpp +++ b/include/data/FluidJSON.hpp @@ -492,7 +492,7 @@ bool check_json(const nlohmann::json &j, const PolynomialRegressor &) { } void from_json(const nlohmann::json &j, PolynomialRegressor ®) { - reg.setDegree(j.at("degree").get()); + reg.init(j.at("degree").get()); RealVector embedding(reg.getDegree() + 1); j.at("coefficients").get_to(embedding); From b591674d9a2bbdd38b791b8cd020261265d1abaf Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 13:50:56 +0100 Subject: [PATCH 11/30] removed superfluous mIn/mOut members --- .../algorithms/public/PolynomialRegressor.hpp | 81 +++++-------------- 1 file changed, 21 insertions(+), 60 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index e59d46caa..8c1f09f6e 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -16,6 +16,7 @@ under the European Union’s Horizon 2020 research and innovation programme #include "../../data/FluidMemory.hpp" #include "../../data/TensorTypes.hpp" #include +#include #include #include @@ -34,10 +35,10 @@ class PolynomialRegressor mDegree = degree; }; - index size() const { return asSigned(mInSet ? mIn.size() : 1); }; - index dims() const { return asSigned(mInSet ? mIn.size() : 0); }; + index size() const { return asSigned(mDegree); }; + index dims() const { return asSigned(mDegree); }; - void clear() { mInSet = mOutSet = mRegressed = false; } + void clear() { mRegressed = false; } index getDegree() const { return asSigned(mDegree); }; bool regressed() const { return mRegressed; }; @@ -48,31 +49,37 @@ class PolynomialRegressor return; mDegree = degree; - clear(); + mRegressed = false; } - void process(RealVectorView in, RealVectorView out) + void calculateRegressionCoefficients(InputRealVectorView in, + InputRealVectorView out, + Allocator& alloc = FluidDefaultAllocator()) { - setMappingSpace(in, out); - process(); - }; + using namespace _impl; - void process() - { - assert(mInSet && mOutSet); - calculateRegressionCoefficients(); + ScopedEigenMap input(in.size(), alloc), + output(out.size(), alloc); + input = asEigen(in); + output = asEigen(out); + + generateDesignMatrix(input); + + Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; + mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * output; + + mRegressed = true; }; void getCoefficients(RealVectorView coefficients) const { - assert(mRegressed); _impl::asEigen(coefficients) = mCoefficients; }; void setCoefficients(InputRealVectorView coefficients) { - mCoefficients = _impl::asEigen(coefficients); setDegree(coefficients.size() - 1); + mCoefficients = _impl::asEigen(coefficients); mRegressed = true; } @@ -82,8 +89,6 @@ class PolynomialRegressor { using namespace _impl; - assert(mRegressed); - ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); input = asEigen(in); @@ -94,45 +99,7 @@ class PolynomialRegressor asEigen(out) = output; } - void setMappingSpace(InputRealVectorView in, - InputRealVectorView out, - Allocator& alloc = FluidDefaultAllocator()) - { - using namespace _impl; - - ScopedEigenMap input(in.size(), alloc), output(out.size(), alloc); - input = asEigen(in); - output = asEigen(in); - - setInputSpace(input); - setOutputSpace(output); - }; - private: - void setInputSpace(Eigen::Ref in) - { - mIn = in; - mInSet = true; - mRegressed = false; - }; - - void setOutputSpace(Eigen::Ref out) - { - mOut = out; - mOutSet = true; - mRegressed = false; - }; - - void calculateRegressionCoefficients() - { - generateDesignMatrix(mIn); - - Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; - mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * mOut; - - mRegressed = true; - }; - void calculateMappings(Eigen::Ref in, Eigen::Ref out) const { generateDesignMatrix(in); @@ -153,13 +120,7 @@ class PolynomialRegressor bool mRegressed {false}; bool mInitialized {false}; - bool mInSet {false}; - bool mOutSet{false}; - - Eigen::VectorXd mIn; - Eigen::VectorXd mOut; mutable Eigen::MatrixXd mDesignMatrix; - Eigen::VectorXd mCoefficients; }; From d880081d696999849067632eb07bbda864fc1744 Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 13:51:21 +0100 Subject: [PATCH 12/30] predictpoint message now working and regressing --- .../clients/nrt/PolynomialRegressorClient.hpp | 71 +++++++++++++------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index ed80b27df..89e0a3b3b 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -47,7 +47,10 @@ class PolynomialRegressorClient : public FluidBaseClient, std::reference_wrapper mParams; - void setParams(ParamSetViewType& p) { mParams = p; } + void setParams(ParamSetViewType& p) { + mParams = p; + mAlgorithm.setDegree(get()); + } template auto& get() const @@ -73,48 +76,73 @@ class PolynomialRegressorClient : public FluidBaseClient, return {}; } - MessageResult fit(InputDataSetClientRef source, + MessageResult fit(InputDataSetClientRef source, InputDataSetClientRef target) { auto sourceClientPtr = source.get().lock(); - if (!sourceClientPtr) return Error(NoDataSet); + if (!sourceClientPtr) return Error(NoDataSet); auto sourceDataSet = sourceClientPtr->getDataSet(); - if (sourceDataSet.size() == 0) return Error(EmptyDataSet); + if (sourceDataSet.size() == 0) return Error(EmptyDataSet); if (sourceDataSet.dims() != 1) - return Error(DimensionsDontMatch); + return Error(DimensionsDontMatch); auto targetClientPtr = target.get().lock(); - if (!targetClientPtr) return Error(NoDataSet); + if (!targetClientPtr) return Error(NoDataSet); auto targetDataSet = targetClientPtr->getDataSet(); - if (targetDataSet.size() == 0) return Error(EmptyDataSet); + if (targetDataSet.size() == 0) return Error(EmptyDataSet); if (sourceDataSet.size() != targetDataSet.size()) - return Error(SizesDontMatch); + return Error(SizesDontMatch); if (!mAlgorithm.initialized()) - mAlgorithm.init(); + mAlgorithm.init(get()); auto data = sourceDataSet.getData().col(0); auto tgt = targetDataSet.getData().col(0); - // mAlgorithm.setMappingSpace(data, tgt); - - string res = " "; - - for (auto& x : data) { - res += std::to_string(x); - res += "\t"; - } + mAlgorithm.calculateRegressionCoefficients(data, tgt); - return res; + return OK(); } - MessageResult map(InputBufferPtr in, BufferPtr out) + MessageResult predict(InputDataSetClientRef src, + DataSetClientRef dest) { return OK(); } + MessageResult predictPoint(InputBufferPtr in, BufferPtr out) const + { + if (!in || !out) return Error(NoBuffer); + + BufferAdaptor::ReadAccess inBuf(in.get()); + BufferAdaptor::Access outBuf(out.get()); + + if (!inBuf.exists()) return Error(InvalidBuffer); + if (!outBuf.exists()) return Error(InvalidBuffer); + if (inBuf.numFrames() != 1) return Error(WrongPointSize); + + if (!mAlgorithm.regressed()) return Error(NoDataFitted); + + Result resizeResult = outBuf.resize(1, 1, inBuf.sampleRate()); + if (!resizeResult.ok()) return Error(BufferAlloc); + + RealVector src(1); + RealVector dest(1); + + src <<= inBuf.samps(0, 1, 0); + mAlgorithm.getMappedSpace(src, dest); + outBuf.samps(0, 1, 0) <<= dest; + + return dest[0]; + } + MessageResult print() { - return "deez nuts"; + return "PolynomialRegressor " + + std::string(get()) + + "\ndegree: " + + std::to_string(mAlgorithm.getDegree()) + + "\n regressed: " + + (mAlgorithm.regressed() ? "true" : "false"); } static auto getMessageDescriptors() @@ -125,7 +153,8 @@ class PolynomialRegressorClient : public FluidBaseClient, makeMessage("clear", &PolynomialRegressorClient::clear), makeMessage("size", &PolynomialRegressorClient::size), makeMessage("print", &PolynomialRegressorClient::print), - makeMessage("map", &PolynomialRegressorClient::map), + makeMessage("predict",&PolynomialRegressorClient::predict), + makeMessage("predictPoint", &PolynomialRegressorClient::predictPoint), makeMessage("load", &PolynomialRegressorClient::load), makeMessage("dump", &PolynomialRegressorClient::dump), makeMessage("write", &PolynomialRegressorClient::write), From eb940deb039264541e9b03269759eb8e5de01f7c Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 14:28:01 +0100 Subject: [PATCH 13/30] predict message now working with datasets --- .../clients/nrt/PolynomialRegressorClient.hpp | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 89e0a3b3b..e688c9555 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -105,24 +105,43 @@ class PolynomialRegressorClient : public FluidBaseClient, MessageResult predict(InputDataSetClientRef src, DataSetClientRef dest) { + auto srcPtr = src.get().lock(); + auto destPtr = dest.get().lock(); + + if (!srcPtr || !destPtr) return Error(NoDataSet); + + auto srcDataSet = srcPtr->getDataSet(); + if (srcDataSet.size() == 0) return Error(EmptyDataSet); + + if (!mAlgorithm.regressed()) return Error(NoDataFitted); + if (srcDataSet.dims() != 1) return Error(WrongPointSize); + + StringVector ids{srcDataSet.getIds()}; + RealMatrix output(srcDataSet.size(), 1); + + mAlgorithm.getMappedSpace(srcDataSet.getData().col(0), output.col(0)); + + DataSet result(ids, output); + destPtr->setDataSet(result); + return OK(); } - MessageResult predictPoint(InputBufferPtr in, BufferPtr out) const + MessageResult predictPoint(InputBufferPtr in, BufferPtr out) const { - if (!in || !out) return Error(NoBuffer); + if (!in || !out) return Error(NoBuffer); BufferAdaptor::ReadAccess inBuf(in.get()); BufferAdaptor::Access outBuf(out.get()); - if (!inBuf.exists()) return Error(InvalidBuffer); - if (!outBuf.exists()) return Error(InvalidBuffer); - if (inBuf.numFrames() != 1) return Error(WrongPointSize); + if (!inBuf.exists()) return Error(InvalidBuffer); + if (!outBuf.exists()) return Error(InvalidBuffer); + if (inBuf.numFrames() != 1) return Error(WrongPointSize); - if (!mAlgorithm.regressed()) return Error(NoDataFitted); + if (!mAlgorithm.regressed()) return Error(NoDataFitted); Result resizeResult = outBuf.resize(1, 1, inBuf.sampleRate()); - if (!resizeResult.ok()) return Error(BufferAlloc); + if (!resizeResult.ok()) return Error(BufferAlloc); RealVector src(1); RealVector dest(1); From 8792d2067987c6fe657e1dfc8422a3cd6cecab23 Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 15:36:35 +0100 Subject: [PATCH 14/30] multi-regressor interface --- .../algorithms/public/PolynomialRegressor.hpp | 67 ++++++++++++------- .../clients/nrt/PolynomialRegressorClient.hpp | 65 +++++++++++------- include/data/FluidJSON.hpp | 15 +++-- 3 files changed, 91 insertions(+), 56 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 8c1f09f6e..39f3e4c8d 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -29,70 +29,84 @@ class PolynomialRegressor explicit PolynomialRegressor() = default; ~PolynomialRegressor() = default; - void init(index degree = 2) + void init(index degree, index dim) { mInitialized = true; mDegree = degree; + mSize = dim; }; - index size() const { return asSigned(mDegree); }; index dims() const { return asSigned(mDegree); }; + index size() const { return asSigned(mSize); }; void clear() { mRegressed = false; } - index getDegree() const { return asSigned(mDegree); }; bool regressed() const { return mRegressed; }; bool initialized() const { return mInitialized; }; void setDegree(index degree) { - if (mDegree == degree) - return; + if (mDegree == degree) return; mDegree = degree; + mCoefficients.conservativeResize(mDegree + 1, mSize); mRegressed = false; } - void calculateRegressionCoefficients(InputRealVectorView in, - InputRealVectorView out, + void setSize(index dim) { + if (mSize == dim) return; + + mSize = dim; + mCoefficients.conservativeResize(mDegree + 1, mSize); + mRegressed = false; + } + + void calculateRegressionCoefficients(InputRealMatrixView in, + InputRealMatrixView out, Allocator& alloc = FluidDefaultAllocator()) { using namespace _impl; - ScopedEigenMap input(in.size(), alloc), - output(out.size(), alloc); + ScopedEigenMap input(in.rows(), in.cols(), alloc), + output(out.rows(), out.cols(), alloc); input = asEigen(in); output = asEigen(out); - generateDesignMatrix(input); + for(index i = 0; i < mSize; ++i) + { + generateDesignMatrix(input.col(i)); - Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; - mCoefficients = transposeProduct.inverse() * mDesignMatrix.transpose() * output; + Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; + mCoefficients.col(i) = transposeProduct.inverse() * mDesignMatrix.transpose() * output.col(i); + } + mRegressed = true; }; - void getCoefficients(RealVectorView coefficients) const + void getCoefficients(RealMatrixView coefficients) const { _impl::asEigen(coefficients) = mCoefficients; }; - void setCoefficients(InputRealVectorView coefficients) + void setCoefficients(InputRealMatrixView coefficients) { - setDegree(coefficients.size() - 1); + setDegree(coefficients.rows() - 1); + setSize(coefficients.cols()); + mCoefficients = _impl::asEigen(coefficients); mRegressed = true; } - void getMappedSpace(InputRealVectorView in, - RealVectorView out, + void getMappedSpace(InputRealMatrixView in, + RealMatrixView out, Allocator& alloc = FluidDefaultAllocator()) const { using namespace _impl; - ScopedEigenMap input(in.size(), alloc), - output(out.size(), alloc); + ScopedEigenMap input(in.rows(), in.cols(), alloc), + output(out.rows(), out.cols(), alloc); input = asEigen(in); - output = asEigen(in); + output = asEigen(out); calculateMappings(input, output); @@ -100,16 +114,20 @@ class PolynomialRegressor } private: - void calculateMappings(Eigen::Ref in, Eigen::Ref out) const + void calculateMappings(Eigen::Ref in, Eigen::Ref out) const { - generateDesignMatrix(in); - out = mDesignMatrix * mCoefficients; + for(index i = 0; i < mSize; ++i) + { + generateDesignMatrix(in.col(i)); + out.col(i) = mDesignMatrix * mCoefficients.col(i); + } } void generateDesignMatrix(Eigen::Ref in) const { Eigen::VectorXd designColumn = Eigen::VectorXd::Ones(in.size()); Eigen::ArrayXd inArray = in.array(); + mDesignMatrix.conservativeResize(in.size(), mDegree + 1); for(index i = 0; i < mDegree + 1; ++i, designColumn = designColumn.array() * inArray) @@ -117,11 +135,12 @@ class PolynomialRegressor } index mDegree {2}; + index mSize {2}; bool mRegressed {false}; bool mInitialized {false}; mutable Eigen::MatrixXd mDesignMatrix; - Eigen::VectorXd mCoefficients; + Eigen::MatrixXd mCoefficients; }; diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index e688c9555..a5b18f583 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -21,7 +21,8 @@ namespace polynomialregressor { constexpr auto PolynomialRegressorParams = defineParameters( StringParam>("name", "Name"), - LongParam("degree", "Degree of fit polynomial", 2, Min(0)) + LongParam("degree", "Degree of polynomial", 2, Min(0)), + LongParam("regressors", "Number of regrssors", 1, Min(1)) ); class PolynomialRegressorClient : public FluidBaseClient, @@ -32,7 +33,8 @@ class PolynomialRegressorClient : public FluidBaseClient, { enum { kName, - kDegree + kDegree, + kRegressors }; public: @@ -49,7 +51,9 @@ class PolynomialRegressorClient : public FluidBaseClient, void setParams(ParamSetViewType& p) { mParams = p; + mAlgorithm.setDegree(get()); + mAlgorithm.setSize(get()); } template @@ -77,25 +81,31 @@ class PolynomialRegressorClient : public FluidBaseClient, } MessageResult fit(InputDataSetClientRef source, - InputDataSetClientRef target) + InputDataSetClientRef target) { auto sourceClientPtr = source.get().lock(); if (!sourceClientPtr) return Error(NoDataSet); + auto sourceDataSet = sourceClientPtr->getDataSet(); if (sourceDataSet.size() == 0) return Error(EmptyDataSet); - if (sourceDataSet.dims() != 1) + if (sourceDataSet.dims() != mAlgorithm.size()) return Error(DimensionsDontMatch); + auto targetClientPtr = target.get().lock(); if (!targetClientPtr) return Error(NoDataSet); + auto targetDataSet = targetClientPtr->getDataSet(); if (targetDataSet.size() == 0) return Error(EmptyDataSet); if (sourceDataSet.size() != targetDataSet.size()) return Error(SizesDontMatch); + if (sourceDataSet.dims() != targetDataSet.dims()) + return Error(SizesDontMatch); + if (!mAlgorithm.initialized()) - mAlgorithm.init(get()); + mAlgorithm.init(get(), get()); - auto data = sourceDataSet.getData().col(0); - auto tgt = targetDataSet.getData().col(0); + auto data = sourceDataSet.getData(); + auto tgt = targetDataSet.getData(); mAlgorithm.calculateRegressionCoefficients(data, tgt); @@ -105,6 +115,8 @@ class PolynomialRegressorClient : public FluidBaseClient, MessageResult predict(InputDataSetClientRef src, DataSetClientRef dest) { + index inputSize = mAlgorithm.size(); + index outputSize = mAlgorithm.size(); auto srcPtr = src.get().lock(); auto destPtr = dest.get().lock(); @@ -114,12 +126,12 @@ class PolynomialRegressorClient : public FluidBaseClient, if (srcDataSet.size() == 0) return Error(EmptyDataSet); if (!mAlgorithm.regressed()) return Error(NoDataFitted); - if (srcDataSet.dims() != 1) return Error(WrongPointSize); + if (srcDataSet.dims() != inputSize) return Error(WrongPointSize); StringVector ids{srcDataSet.getIds()}; - RealMatrix output(srcDataSet.size(), 1); + RealMatrix output(srcDataSet.size(), outputSize); - mAlgorithm.getMappedSpace(srcDataSet.getData().col(0), output.col(0)); + mAlgorithm.getMappedSpace(srcDataSet.getData(), output); DataSet result(ids, output); destPtr->setDataSet(result); @@ -127,30 +139,33 @@ class PolynomialRegressorClient : public FluidBaseClient, return OK(); } - MessageResult predictPoint(InputBufferPtr in, BufferPtr out) const + MessageResult predictPoint(InputBufferPtr in, BufferPtr out) const { - if (!in || !out) return Error(NoBuffer); + index inputSize = mAlgorithm.size(); + index outputSize = mAlgorithm.size(); + + if (!in || !out) return Error(NoBuffer); BufferAdaptor::ReadAccess inBuf(in.get()); BufferAdaptor::Access outBuf(out.get()); - if (!inBuf.exists()) return Error(InvalidBuffer); - if (!outBuf.exists()) return Error(InvalidBuffer); - if (inBuf.numFrames() != 1) return Error(WrongPointSize); + if (!inBuf.exists()) return Error(InvalidBuffer); + if (!outBuf.exists()) return Error(InvalidBuffer); + if (inBuf.numFrames() != inputSize) return Error(WrongPointSize); - if (!mAlgorithm.regressed()) return Error(NoDataFitted); + if (!mAlgorithm.regressed()) return Error(NoDataFitted); - Result resizeResult = outBuf.resize(1, 1, inBuf.sampleRate()); - if (!resizeResult.ok()) return Error(BufferAlloc); + Result resizeResult = outBuf.resize(outputSize, 1, inBuf.sampleRate()); + if (!resizeResult.ok()) return Error(BufferAlloc); - RealVector src(1); - RealVector dest(1); + RealMatrix src(inputSize, 1); + RealMatrix dest(outputSize, 1); - src <<= inBuf.samps(0, 1, 0); + src.col(0) <<= inBuf.samps(0, inputSize, 0); mAlgorithm.getMappedSpace(src, dest); - outBuf.samps(0, 1, 0) <<= dest; + outBuf.samps(0, outputSize, 0) <<= dest.col(0); - return dest[0]; + return OK(); } @@ -158,8 +173,8 @@ class PolynomialRegressorClient : public FluidBaseClient, { return "PolynomialRegressor " + std::string(get()) - + "\ndegree: " - + std::to_string(mAlgorithm.getDegree()) + + "\ndegree: " + + std::to_string(mAlgorithm.dims()) + "\n regressed: " + (mAlgorithm.regressed() ? "true" : "false"); } diff --git a/include/data/FluidJSON.hpp b/include/data/FluidJSON.hpp index 95b3c6ba8..88c8ad507 100644 --- a/include/data/FluidJSON.hpp +++ b/include/data/FluidJSON.hpp @@ -476,25 +476,26 @@ void from_json(const nlohmann::json &j, UMAP &umap) { // PolynomialRegressor void to_json(nlohmann::json &j, const PolynomialRegressor ®) { - RealVector coefficients(reg.getDegree()); + RealMatrix coefficients(reg.dims(), reg.size()); reg.getCoefficients(coefficients); - j["degree"] = reg.getDegree(); - j["coefficients"] = RealVectorView(coefficients); + j["degree"] = reg.dims(); + j["size"] = reg.dims(); + j["coefficients"] = RealMatrixView(coefficients); } bool check_json(const nlohmann::json &j, const PolynomialRegressor &) { return fluid::check_json(j, - {"degree", "coefficients"}, - {JSONTypes::NUMBER, JSONTypes::OBJECT} + {"degree", "size", "coefficients"}, + {JSONTypes::NUMBER, JSONTypes::NUMBER, JSONTypes::OBJECT} ); } void from_json(const nlohmann::json &j, PolynomialRegressor ®) { - reg.init(j.at("degree").get()); + reg.init(j.at("degree").get(), j.at("size").get()); - RealVector embedding(reg.getDegree() + 1); + RealMatrix embedding(reg.dims() + 1, reg.size()); j.at("coefficients").get_to(embedding); } From 53aff44abeefdbe63615c486b804001bd6c2264b Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 17:30:36 +0100 Subject: [PATCH 15/30] ranme mDims for consistency --- .../algorithms/public/PolynomialRegressor.hpp | 31 ++++++++++--------- .../clients/nrt/PolynomialRegressorClient.hpp | 27 ++++++++-------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 39f3e4c8d..472ba75ec 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -29,15 +29,16 @@ class PolynomialRegressor explicit PolynomialRegressor() = default; ~PolynomialRegressor() = default; - void init(index degree, index dim) + void init(index degree, index dims) { mInitialized = true; - mDegree = degree; - mSize = dim; + setDegree(degree); + setDims(dims); }; - index dims() const { return asSigned(mDegree); }; - index size() const { return asSigned(mSize); }; + index degree() const { return mInitialized ? asSigned(mDegree) : 0; }; + index dims() const { return mInitialized ? asSigned(mDims) : 0; }; + index size() const { return mInitialized ? asSigned(mDegree) : 0; }; void clear() { mRegressed = false; } @@ -48,15 +49,15 @@ class PolynomialRegressor if (mDegree == degree) return; mDegree = degree; - mCoefficients.conservativeResize(mDegree + 1, mSize); + mCoefficients.conservativeResize(mDegree + 1, mDims); mRegressed = false; } - void setSize(index dim) { - if (mSize == dim) return; + void setDims(index dims) { + if (mDims == dims) return; - mSize = dim; - mCoefficients.conservativeResize(mDegree + 1, mSize); + mDims = dims; + mCoefficients.conservativeResize(mDegree + 1, mDims); mRegressed = false; } @@ -71,7 +72,7 @@ class PolynomialRegressor input = asEigen(in); output = asEigen(out); - for(index i = 0; i < mSize; ++i) + for(index i = 0; i < mDims; ++i) { generateDesignMatrix(input.col(i)); @@ -85,13 +86,13 @@ class PolynomialRegressor void getCoefficients(RealMatrixView coefficients) const { - _impl::asEigen(coefficients) = mCoefficients; + if (mInitialized) _impl::asEigen(coefficients) = mCoefficients; }; void setCoefficients(InputRealMatrixView coefficients) { setDegree(coefficients.rows() - 1); - setSize(coefficients.cols()); + setDims(coefficients.cols()); mCoefficients = _impl::asEigen(coefficients); mRegressed = true; @@ -116,7 +117,7 @@ class PolynomialRegressor private: void calculateMappings(Eigen::Ref in, Eigen::Ref out) const { - for(index i = 0; i < mSize; ++i) + for(index i = 0; i < mDims; ++i) { generateDesignMatrix(in.col(i)); out.col(i) = mDesignMatrix * mCoefficients.col(i); @@ -135,7 +136,7 @@ class PolynomialRegressor } index mDegree {2}; - index mSize {2}; + index mDims {1}; bool mRegressed {false}; bool mInitialized {false}; diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index a5b18f583..53f6d0b0b 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -53,7 +53,7 @@ class PolynomialRegressorClient : public FluidBaseClient, mParams = p; mAlgorithm.setDegree(get()); - mAlgorithm.setSize(get()); + mAlgorithm.setDims(get()); } template @@ -85,21 +85,20 @@ class PolynomialRegressorClient : public FluidBaseClient, { auto sourceClientPtr = source.get().lock(); if (!sourceClientPtr) return Error(NoDataSet); - auto sourceDataSet = sourceClientPtr->getDataSet(); if (sourceDataSet.size() == 0) return Error(EmptyDataSet); - if (sourceDataSet.dims() != mAlgorithm.size()) + if (sourceDataSet.dims() != mAlgorithm.dims()) return Error(DimensionsDontMatch); auto targetClientPtr = target.get().lock(); if (!targetClientPtr) return Error(NoDataSet); - auto targetDataSet = targetClientPtr->getDataSet(); if (targetDataSet.size() == 0) return Error(EmptyDataSet); + if (sourceDataSet.dims() != mAlgorithm.dims()) + return Error(DimensionsDontMatch); + if (sourceDataSet.size() != targetDataSet.size()) return Error(SizesDontMatch); - if (sourceDataSet.dims() != targetDataSet.dims()) - return Error(SizesDontMatch); if (!mAlgorithm.initialized()) mAlgorithm.init(get(), get()); @@ -115,8 +114,8 @@ class PolynomialRegressorClient : public FluidBaseClient, MessageResult predict(InputDataSetClientRef src, DataSetClientRef dest) { - index inputSize = mAlgorithm.size(); - index outputSize = mAlgorithm.size(); + index inputSize = mAlgorithm.dims(); + index outputSize = mAlgorithm.dims(); auto srcPtr = src.get().lock(); auto destPtr = dest.get().lock(); @@ -141,8 +140,8 @@ class PolynomialRegressorClient : public FluidBaseClient, MessageResult predictPoint(InputBufferPtr in, BufferPtr out) const { - index inputSize = mAlgorithm.size(); - index outputSize = mAlgorithm.size(); + index inputSize = mAlgorithm.dims(); + index outputSize = mAlgorithm.dims(); if (!in || !out) return Error(NoBuffer); @@ -173,9 +172,11 @@ class PolynomialRegressorClient : public FluidBaseClient, { return "PolynomialRegressor " + std::string(get()) - + "\ndegree: " - + std::to_string(mAlgorithm.dims()) - + "\n regressed: " + + "\npolynimal degree: " + + std::to_string(mAlgorithm.degree()) + + "\nparallel regressors: " + + std::to_string(mAlgorithm.dims()) + + "\nregressed: " + (mAlgorithm.regressed() ? "true" : "false"); } From cd15ed246926577ca3e4659c73a52ea8ae11337f Mon Sep 17 00:00:00 2001 From: lewardo Date: Fri, 18 Aug 2023 17:31:05 +0100 Subject: [PATCH 16/30] actually initialise algorithm from read --- include/data/FluidJSON.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/data/FluidJSON.hpp b/include/data/FluidJSON.hpp index 88c8ad507..be7548a14 100644 --- a/include/data/FluidJSON.hpp +++ b/include/data/FluidJSON.hpp @@ -476,27 +476,29 @@ void from_json(const nlohmann::json &j, UMAP &umap) { // PolynomialRegressor void to_json(nlohmann::json &j, const PolynomialRegressor ®) { - RealMatrix coefficients(reg.dims(), reg.size()); + RealMatrix coefficients(reg.dims() + 1, reg.size()); reg.getCoefficients(coefficients); - j["degree"] = reg.dims(); - j["size"] = reg.dims(); j["coefficients"] = RealMatrixView(coefficients); + j["degree"] = reg.degree(); + j["dims"] = reg.dims(); } bool check_json(const nlohmann::json &j, const PolynomialRegressor &) { return fluid::check_json(j, - {"degree", "size", "coefficients"}, - {JSONTypes::NUMBER, JSONTypes::NUMBER, JSONTypes::OBJECT} + {"degree", "dims", "coefficients"}, + {JSONTypes::NUMBER, JSONTypes::NUMBER, JSONTypes::ARRAY} ); } void from_json(const nlohmann::json &j, PolynomialRegressor ®) { - reg.init(j.at("degree").get(), j.at("size").get()); + reg.init(j.at("degree").get(), j.at("dims").get()); RealMatrix embedding(reg.dims() + 1, reg.size()); j.at("coefficients").get_to(embedding); + + reg.setCoefficients(embedding); } } // namespace algorithm From be581ff880137eaedd74693c27c1712d3fe3aa0e Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 09:02:04 +0100 Subject: [PATCH 17/30] fix parameter read/load updating --- .../clients/nrt/PolynomialRegressorClient.hpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 53f6d0b0b..e7cc9b049 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -46,6 +46,7 @@ class PolynomialRegressorClient : public FluidBaseClient, using ParamDescType = decltype(PolynomialRegressorParams); using ParamSetViewType = ParameterSetView; + using ParamValues = typename ParamSetViewType::ValueTuple; std::reference_wrapper mParams; @@ -180,6 +181,21 @@ class PolynomialRegressorClient : public FluidBaseClient, + (mAlgorithm.regressed() ? "true" : "false"); } + MessageResult read(string fileName) + { + auto result = DataClient::read(fileName); + if (result.ok()) return updateParameters(); + return {result.status(), result.message()}; + } + + MessageResult load(string fileName) + { + auto result = DataClient::load(fileName); + if (result.ok()) return updateParameters(); + return {result.status(), result.message()}; + } + + static auto getMessageDescriptors() { return defineMessages( @@ -195,6 +211,15 @@ class PolynomialRegressorClient : public FluidBaseClient, makeMessage("write", &PolynomialRegressorClient::write), makeMessage("read", &PolynomialRegressorClient::read)); } + +private: + MessageResult updateParameters() + { + get() = mAlgorithm.dims(); + get() = mAlgorithm.degree(); + + return mParams.get().toTuple(); + } }; using PolynomialRegressorRef = SharedClientRef; From 6cf06aad454470ec515d8dfaa85a488e48cc0cdd Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 09:37:36 +0100 Subject: [PATCH 18/30] automatic dimensioin setting from training mapping --- .../clients/nrt/PolynomialRegressorClient.hpp | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index e7cc9b049..d97506bfd 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -21,8 +21,7 @@ namespace polynomialregressor { constexpr auto PolynomialRegressorParams = defineParameters( StringParam>("name", "Name"), - LongParam("degree", "Degree of polynomial", 2, Min(0)), - LongParam("regressors", "Number of regrssors", 1, Min(1)) + LongParam("degree", "Degree of polynomial", 2, Min(0)) ); class PolynomialRegressorClient : public FluidBaseClient, @@ -33,8 +32,7 @@ class PolynomialRegressorClient : public FluidBaseClient, { enum { kName, - kDegree, - kRegressors + kDegree }; public: @@ -52,9 +50,7 @@ class PolynomialRegressorClient : public FluidBaseClient, void setParams(ParamSetViewType& p) { mParams = p; - mAlgorithm.setDegree(get()); - mAlgorithm.setDims(get()); } template @@ -71,7 +67,7 @@ class PolynomialRegressorClient : public FluidBaseClient, // c.allocator(); PolynomialRegressorClient(ParamSetViewType& p, FluidContext& c) : mParams(p) { - audioChannelsIn(1); + controlChannelsIn(1); controlChannelsOut({1, 1}); } @@ -84,25 +80,23 @@ class PolynomialRegressorClient : public FluidBaseClient, MessageResult fit(InputDataSetClientRef source, InputDataSetClientRef target) { - auto sourceClientPtr = source.get().lock(); - if (!sourceClientPtr) return Error(NoDataSet); - auto sourceDataSet = sourceClientPtr->getDataSet(); - if (sourceDataSet.size() == 0) return Error(EmptyDataSet); - if (sourceDataSet.dims() != mAlgorithm.dims()) - return Error(DimensionsDontMatch); - auto targetClientPtr = target.get().lock(); if (!targetClientPtr) return Error(NoDataSet); auto targetDataSet = targetClientPtr->getDataSet(); if (targetDataSet.size() == 0) return Error(EmptyDataSet); - if (sourceDataSet.dims() != mAlgorithm.dims()) - return Error(DimensionsDontMatch); + + auto sourceClientPtr = source.get().lock(); + if (!sourceClientPtr) return Error(NoDataSet); + auto sourceDataSet = sourceClientPtr->getDataSet(); + if (sourceDataSet.size() == 0) return Error(EmptyDataSet); if (sourceDataSet.size() != targetDataSet.size()) return Error(SizesDontMatch); - if (!mAlgorithm.initialized()) - mAlgorithm.init(get(), get()); + if (sourceDataSet.dims() != targetDataSet.dims()) + return Error(WrongPointSize); + + mAlgorithm.init(get(), sourceDataSet.dims()); auto data = sourceDataSet.getData(); auto tgt = targetDataSet.getData(); @@ -174,7 +168,7 @@ class PolynomialRegressorClient : public FluidBaseClient, return "PolynomialRegressor " + std::string(get()) + "\npolynimal degree: " - + std::to_string(mAlgorithm.degree()) + + std::to_string(get()) + "\nparallel regressors: " + std::to_string(mAlgorithm.dims()) + "\nregressed: " @@ -215,9 +209,7 @@ class PolynomialRegressorClient : public FluidBaseClient, private: MessageResult updateParameters() { - get() = mAlgorithm.dims(); get() = mAlgorithm.degree(); - return mParams.get().toTuple(); } }; From ee63aaeb9100e6180b00b9cbd81450799fec12ba Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 09:39:17 +0100 Subject: [PATCH 19/30] bugfix saving in wrong dimensionality --- include/data/FluidJSON.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/data/FluidJSON.hpp b/include/data/FluidJSON.hpp index be7548a14..da95454a3 100644 --- a/include/data/FluidJSON.hpp +++ b/include/data/FluidJSON.hpp @@ -476,7 +476,7 @@ void from_json(const nlohmann::json &j, UMAP &umap) { // PolynomialRegressor void to_json(nlohmann::json &j, const PolynomialRegressor ®) { - RealMatrix coefficients(reg.dims() + 1, reg.size()); + RealMatrix coefficients(reg.degree() + 1, reg.dims()); reg.getCoefficients(coefficients); @@ -495,7 +495,7 @@ bool check_json(const nlohmann::json &j, const PolynomialRegressor &) { void from_json(const nlohmann::json &j, PolynomialRegressor ®) { reg.init(j.at("degree").get(), j.at("dims").get()); - RealMatrix embedding(reg.dims() + 1, reg.size()); + RealMatrix embedding(reg.degree() + 1, reg.dims()); j.at("coefficients").get_to(embedding); reg.setCoefficients(embedding); From 7b92c534fcfb43ebd96047a0bf3084e53aedb15f Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 09:42:42 +0100 Subject: [PATCH 20/30] rename algo methods for consistency --- include/algorithms/public/PolynomialRegressor.hpp | 12 ++++++------ include/clients/nrt/PolynomialRegressorClient.hpp | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 472ba75ec..6270a816e 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -61,9 +61,9 @@ class PolynomialRegressor mRegressed = false; } - void calculateRegressionCoefficients(InputRealMatrixView in, - InputRealMatrixView out, - Allocator& alloc = FluidDefaultAllocator()) + void regress(InputRealMatrixView in, + InputRealMatrixView out, + Allocator& alloc = FluidDefaultAllocator()) { using namespace _impl; @@ -98,9 +98,9 @@ class PolynomialRegressor mRegressed = true; } - void getMappedSpace(InputRealMatrixView in, - RealMatrixView out, - Allocator& alloc = FluidDefaultAllocator()) const + void process(InputRealMatrixView in, + RealMatrixView out, + Allocator& alloc = FluidDefaultAllocator()) const { using namespace _impl; diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index d97506bfd..2254cd1ca 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -101,7 +101,7 @@ class PolynomialRegressorClient : public FluidBaseClient, auto data = sourceDataSet.getData(); auto tgt = targetDataSet.getData(); - mAlgorithm.calculateRegressionCoefficients(data, tgt); + mAlgorithm.regress(data, tgt); return OK(); } @@ -125,7 +125,7 @@ class PolynomialRegressorClient : public FluidBaseClient, StringVector ids{srcDataSet.getIds()}; RealMatrix output(srcDataSet.size(), outputSize); - mAlgorithm.getMappedSpace(srcDataSet.getData(), output); + mAlgorithm.process(srcDataSet.getData(), output); DataSet result(ids, output); destPtr->setDataSet(result); @@ -156,7 +156,7 @@ class PolynomialRegressorClient : public FluidBaseClient, RealMatrix dest(outputSize, 1); src.col(0) <<= inBuf.samps(0, inputSize, 0); - mAlgorithm.getMappedSpace(src, dest); + mAlgorithm.process(src, dest); outBuf.samps(0, outputSize, 0) <<= dest.col(0); return OK(); From 983560a2059cd551186a955b9157f4d4e377b7d5 Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 11:15:05 +0100 Subject: [PATCH 21/30] added tikhonov regularisation, currently only ridge normalisation --- .../algorithms/public/PolynomialRegressor.hpp | 40 +++++++++++++++---- .../clients/nrt/PolynomialRegressorClient.hpp | 23 +++++++---- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 6270a816e..7c5213346 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -29,16 +29,18 @@ class PolynomialRegressor explicit PolynomialRegressor() = default; ~PolynomialRegressor() = default; - void init(index degree, index dims) + void init(index degree, index dims, double tikhonov = 0.0) { mInitialized = true; setDegree(degree); setDims(dims); + setTikhonov(tikhonov); }; - index degree() const { return mInitialized ? asSigned(mDegree) : 0; }; - index dims() const { return mInitialized ? asSigned(mDims) : 0; }; - index size() const { return mInitialized ? asSigned(mDegree) : 0; }; + index degree() const { return mInitialized ? asSigned(mDegree) : 0; }; + double tihkonov() const { return mInitialized ? mTikhonovFactor : 0.0; }; + index dims() const { return mInitialized ? asSigned(mDims) : 0; }; + index size() const { return mInitialized ? asSigned(mDegree) : 0; }; void clear() { mRegressed = false; } @@ -61,6 +63,14 @@ class PolynomialRegressor mRegressed = false; } + void setTikhonov(double tikhonov) { + if (mTikhonovFactor == tikhonov) return; + + mTikhonovFactor = tikhonov; + mRegressed = false; + } + + void regress(InputRealMatrixView in, InputRealMatrixView out, Allocator& alloc = FluidDefaultAllocator()) @@ -72,12 +82,17 @@ class PolynomialRegressor input = asEigen(in); output = asEigen(out); + generateTikhonovFilter(mDegree + 1); + for(index i = 0; i < mDims; ++i) { generateDesignMatrix(input.col(i)); - - Eigen::MatrixXd transposeProduct = mDesignMatrix.transpose() * mDesignMatrix; - mCoefficients.col(i) = transposeProduct.inverse() * mDesignMatrix.transpose() * output.col(i); + + // tikhonov/ridge regularisation, given Ax = y where x could be noisy + // optimise the value _x = (A^T . A + R^T . R)^-1 . A^T . y + // where R is a tikhonov filter matrix, in case of ridge regression of the form a.I + Eigen::MatrixXd transposeDesignTikhonovProduct = mDesignMatrix.transpose() * mDesignMatrix + mTikhonovMatrix.transpose() * mTikhonovMatrix; + mCoefficients.col(i) = transposeDesignTikhonovProduct.inverse() * mDesignMatrix.transpose() * output.col(i); } @@ -135,14 +150,23 @@ class PolynomialRegressor mDesignMatrix.col(i) = designColumn; } + // currently only ridge normalisation with scaled identity matrix as tikhonov filter + void generateTikhonovFilter(index size) + { + mTikhonovMatrix = mTikhonovFactor * Eigen::MatrixXd::Identity(size, size); + }; + index mDegree {2}; index mDims {1}; bool mRegressed {false}; bool mInitialized {false}; - mutable Eigen::MatrixXd mDesignMatrix; + double mTikhonovFactor {0}; + Eigen::MatrixXd mCoefficients; + mutable Eigen::MatrixXd mDesignMatrix; + mutable Eigen::MatrixXd mTikhonovMatrix; }; } // namespace algorithm diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 2254cd1ca..6ff011376 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -21,7 +21,8 @@ namespace polynomialregressor { constexpr auto PolynomialRegressorParams = defineParameters( StringParam>("name", "Name"), - LongParam("degree", "Degree of polynomial", 2, Min(0)) + LongParam("degree", "Degree of polynomial", 2, Min(0)), + FloatParam("tikhonov", "Tihkonov factor for regression", 0.0, Min(0.0)) ); class PolynomialRegressorClient : public FluidBaseClient, @@ -32,7 +33,8 @@ class PolynomialRegressorClient : public FluidBaseClient, { enum { kName, - kDegree + kDegree, + kTikhonov }; public: @@ -51,6 +53,7 @@ class PolynomialRegressorClient : public FluidBaseClient, void setParams(ParamSetViewType& p) { mParams = p; mAlgorithm.setDegree(get()); + mAlgorithm.setTikhonov(get()); } template @@ -64,8 +67,7 @@ class PolynomialRegressorClient : public FluidBaseClient, return PolynomialRegressorParams; } -// c.allocator(); - PolynomialRegressorClient(ParamSetViewType& p, FluidContext& c) : mParams(p) + PolynomialRegressorClient(ParamSetViewType& p, FluidContext&) : mParams(p) { controlChannelsIn(1); controlChannelsOut({1, 1}); @@ -96,7 +98,9 @@ class PolynomialRegressorClient : public FluidBaseClient, if (sourceDataSet.dims() != targetDataSet.dims()) return Error(WrongPointSize); - mAlgorithm.init(get(), sourceDataSet.dims()); + updateParameters(); + + mAlgorithm.init(get(), sourceDataSet.dims(), get()); auto data = sourceDataSet.getData(); auto tgt = targetDataSet.getData(); @@ -168,9 +172,11 @@ class PolynomialRegressorClient : public FluidBaseClient, return "PolynomialRegressor " + std::string(get()) + "\npolynimal degree: " - + std::to_string(get()) + + std::to_string(mAlgorithm.degree()) + "\nparallel regressors: " + std::to_string(mAlgorithm.dims()) + + "\nTikhonov regularisation factor: " + + std::to_string(mAlgorithm.tihkonov()) + "\nregressed: " + (mAlgorithm.regressed() ? "true" : "false"); } @@ -199,7 +205,8 @@ class PolynomialRegressorClient : public FluidBaseClient, makeMessage("size", &PolynomialRegressorClient::size), makeMessage("print", &PolynomialRegressorClient::print), makeMessage("predict",&PolynomialRegressorClient::predict), - makeMessage("predictPoint", &PolynomialRegressorClient::predictPoint), + makeMessage("predictPoint", + &PolynomialRegressorClient::predictPoint), makeMessage("load", &PolynomialRegressorClient::load), makeMessage("dump", &PolynomialRegressorClient::dump), makeMessage("write", &PolynomialRegressorClient::write), @@ -210,6 +217,8 @@ class PolynomialRegressorClient : public FluidBaseClient, MessageResult updateParameters() { get() = mAlgorithm.degree(); + get() = mAlgorithm.tihkonov(); + return mParams.get().toTuple(); } }; From ab42687c0ddd680f09b78a4bc24666ee7f168baa Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 11:23:11 +0100 Subject: [PATCH 22/30] slimmed json saving by removing redundant data --- include/algorithms/public/PolynomialRegressor.hpp | 2 ++ include/data/FluidJSON.hpp | 8 ++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 7c5213346..b9d262cf9 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -106,6 +106,8 @@ class PolynomialRegressor void setCoefficients(InputRealMatrixView coefficients) { + if(!mInitialized) mInitialized = true; + setDegree(coefficients.rows() - 1); setDims(coefficients.cols()); diff --git a/include/data/FluidJSON.hpp b/include/data/FluidJSON.hpp index da95454a3..2ace9aacd 100644 --- a/include/data/FluidJSON.hpp +++ b/include/data/FluidJSON.hpp @@ -481,20 +481,16 @@ void to_json(nlohmann::json &j, const PolynomialRegressor ®) { reg.getCoefficients(coefficients); j["coefficients"] = RealMatrixView(coefficients); - j["degree"] = reg.degree(); - j["dims"] = reg.dims(); } bool check_json(const nlohmann::json &j, const PolynomialRegressor &) { return fluid::check_json(j, - {"degree", "dims", "coefficients"}, - {JSONTypes::NUMBER, JSONTypes::NUMBER, JSONTypes::ARRAY} + {"coefficients"}, + {JSONTypes::ARRAY} ); } void from_json(const nlohmann::json &j, PolynomialRegressor ®) { - reg.init(j.at("degree").get(), j.at("dims").get()); - RealMatrix embedding(reg.degree() + 1, reg.dims()); j.at("coefficients").get_to(embedding); From b6151173ed2c54e195aadc1d5254c1a5dbdc15c3 Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 11:31:11 +0100 Subject: [PATCH 23/30] saving of tikhonov factor --- include/data/FluidJSON.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/include/data/FluidJSON.hpp b/include/data/FluidJSON.hpp index 2ace9aacd..9d459148c 100644 --- a/include/data/FluidJSON.hpp +++ b/include/data/FluidJSON.hpp @@ -480,21 +480,26 @@ void to_json(nlohmann::json &j, const PolynomialRegressor ®) { reg.getCoefficients(coefficients); + j["tikhonov"] = reg.tihkonov(); j["coefficients"] = RealMatrixView(coefficients); } bool check_json(const nlohmann::json &j, const PolynomialRegressor &) { return fluid::check_json(j, - {"coefficients"}, - {JSONTypes::ARRAY} + {"tikhonov", "coefficients"}, + {JSONTypes::NUMBER, JSONTypes::ARRAY} ); } void from_json(const nlohmann::json &j, PolynomialRegressor ®) { RealMatrix embedding(reg.degree() + 1, reg.dims()); + double tikhonov; + + j.at("tikhonov").get_to(tikhonov); j.at("coefficients").get_to(embedding); - reg.setCoefficients(embedding); + reg.setTikhonov(tikhonov); + reg.setCoefficients(embedding); } } // namespace algorithm From fa0dbfb7bbd8d87094287440d2e89b01cf4a98ea Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 21 Aug 2023 12:19:11 +0100 Subject: [PATCH 24/30] added write regression state catch --- include/clients/nrt/PolynomialRegressorClient.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 6ff011376..110301def 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -181,6 +181,12 @@ class PolynomialRegressorClient : public FluidBaseClient, + (mAlgorithm.regressed() ? "true" : "false"); } + MessageResult write(string fileName) + { + if(!mAlgorithm.regressed()) return Error(NoDataFitted); + return DataClient::write(fileName); + } + MessageResult read(string fileName) { auto result = DataClient::read(fileName); From 5b0bc48109471ec50682a2ed1aab5c64406de755 Mon Sep 17 00:00:00 2001 From: lewardo Date: Tue, 22 Aug 2023 09:34:53 +0100 Subject: [PATCH 25/30] remove parameter update bug on first `fit` --- include/clients/nrt/PolynomialRegressorClient.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 110301def..983d71c5e 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -98,8 +98,6 @@ class PolynomialRegressorClient : public FluidBaseClient, if (sourceDataSet.dims() != targetDataSet.dims()) return Error(WrongPointSize); - updateParameters(); - mAlgorithm.init(get(), sourceDataSet.dims(), get()); auto data = sourceDataSet.getData(); From cd16032a4a0dcb341db0d2470893fab755f82f99 Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 28 Aug 2023 08:59:19 +0100 Subject: [PATCH 26/30] fix get<>() definition location --- include/clients/nrt/PolynomialRegressorClient.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 983d71c5e..77057c217 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -50,18 +50,18 @@ class PolynomialRegressorClient : public FluidBaseClient, std::reference_wrapper mParams; - void setParams(ParamSetViewType& p) { - mParams = p; - mAlgorithm.setDegree(get()); - mAlgorithm.setTikhonov(get()); - } - template auto& get() const { return mParams.get().template get(); } + void setParams(ParamSetViewType& p) { + mParams = p; + mAlgorithm.setDegree(get()); + mAlgorithm.setTikhonov(get()); + } + static constexpr auto& getParameterDescriptors() { return PolynomialRegressorParams; From c0023d2b98788ddfb41a51eb294631cc98c04ab0 Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 28 Aug 2023 10:10:36 +0100 Subject: [PATCH 27/30] increase assignment clarity --- include/clients/nrt/PolynomialRegressorClient.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index 77057c217..f48b326ef 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -100,8 +100,8 @@ class PolynomialRegressorClient : public FluidBaseClient, mAlgorithm.init(get(), sourceDataSet.dims(), get()); - auto data = sourceDataSet.getData(); - auto tgt = targetDataSet.getData(); + RealMatrixView data = sourceDataSet.getData(); + RealMatrixView tgt = targetDataSet.getData(); mAlgorithm.regress(data, tgt); From dea9281dd78dde9fe62df327bbe0a59ff8478f41 Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 28 Aug 2023 10:34:43 +0100 Subject: [PATCH 28/30] run clang-format --- .../algorithms/public/PolynomialRegressor.hpp | 233 +++++++++--------- .../clients/nrt/PolynomialRegressorClient.hpp | 107 ++++---- 2 files changed, 168 insertions(+), 172 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index b9d262cf9..868975049 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -26,149 +26,158 @@ namespace algorithm { class PolynomialRegressor { public: - explicit PolynomialRegressor() = default; - ~PolynomialRegressor() = default; + explicit PolynomialRegressor() = default; + ~PolynomialRegressor() = default; - void init(index degree, index dims, double tikhonov = 0.0) - { - mInitialized = true; - setDegree(degree); - setDims(dims); - setTikhonov(tikhonov); - }; + void init(index degree, index dims, double tikhonov = 0.0) + { + mInitialized = true; + setDegree(degree); + setDims(dims); + setTikhonov(tikhonov); + }; - index degree() const { return mInitialized ? asSigned(mDegree) : 0; }; - double tihkonov() const { return mInitialized ? mTikhonovFactor : 0.0; }; - index dims() const { return mInitialized ? asSigned(mDims) : 0; }; - index size() const { return mInitialized ? asSigned(mDegree) : 0; }; + index degree() const { return mInitialized ? asSigned(mDegree) : 0; }; + double tihkonov() const { return mInitialized ? mTikhonovFactor : 0.0; }; + index dims() const { return mInitialized ? asSigned(mDims) : 0; }; + index size() const { return mInitialized ? asSigned(mDegree) : 0; }; - void clear() { mRegressed = false; } + void clear() { mRegressed = false; } - bool regressed() const { return mRegressed; }; - bool initialized() const { return mInitialized; }; + bool regressed() const { return mRegressed; }; + bool initialized() const { return mInitialized; }; - void setDegree(index degree) { - if (mDegree == degree) return; + void setDegree(index degree) + { + if (mDegree == degree) return; - mDegree = degree; - mCoefficients.conservativeResize(mDegree + 1, mDims); - mRegressed = false; - } + mDegree = degree; + mCoefficients.conservativeResize(mDegree + 1, mDims); + mRegressed = false; + } - void setDims(index dims) { - if (mDims == dims) return; + void setDims(index dims) + { + if (mDims == dims) return; - mDims = dims; - mCoefficients.conservativeResize(mDegree + 1, mDims); - mRegressed = false; - } + mDims = dims; + mCoefficients.conservativeResize(mDegree + 1, mDims); + mRegressed = false; + } - void setTikhonov(double tikhonov) { - if (mTikhonovFactor == tikhonov) return; + void setTikhonov(double tikhonov) + { + if (mTikhonovFactor == tikhonov) return; - mTikhonovFactor = tikhonov; - mRegressed = false; - } + mTikhonovFactor = tikhonov; + mRegressed = false; + } - void regress(InputRealMatrixView in, - InputRealMatrixView out, - Allocator& alloc = FluidDefaultAllocator()) - { - using namespace _impl; - - ScopedEigenMap input(in.rows(), in.cols(), alloc), - output(out.rows(), out.cols(), alloc); - input = asEigen(in); - output = asEigen(out); - - generateTikhonovFilter(mDegree + 1); - - for(index i = 0; i < mDims; ++i) - { - generateDesignMatrix(input.col(i)); - - // tikhonov/ridge regularisation, given Ax = y where x could be noisy - // optimise the value _x = (A^T . A + R^T . R)^-1 . A^T . y - // where R is a tikhonov filter matrix, in case of ridge regression of the form a.I - Eigen::MatrixXd transposeDesignTikhonovProduct = mDesignMatrix.transpose() * mDesignMatrix + mTikhonovMatrix.transpose() * mTikhonovMatrix; - mCoefficients.col(i) = transposeDesignTikhonovProduct.inverse() * mDesignMatrix.transpose() * output.col(i); - } - - - mRegressed = true; - }; - - void getCoefficients(RealMatrixView coefficients) const - { - if (mInitialized) _impl::asEigen(coefficients) = mCoefficients; - }; + void regress(InputRealMatrixView in, InputRealMatrixView out, + Allocator& alloc = FluidDefaultAllocator()) + { + using namespace _impl; - void setCoefficients(InputRealMatrixView coefficients) - { - if(!mInitialized) mInitialized = true; - - setDegree(coefficients.rows() - 1); - setDims(coefficients.cols()); + ScopedEigenMap input(in.rows(), in.cols(), alloc), + output(out.rows(), out.cols(), alloc); + input = asEigen(in); + output = asEigen(out); - mCoefficients = _impl::asEigen(coefficients); - mRegressed = true; - } + generateTikhonovFilter(mDegree + 1); - void process(InputRealMatrixView in, - RealMatrixView out, - Allocator& alloc = FluidDefaultAllocator()) const + for (index i = 0; i < mDims; ++i) { - using namespace _impl; + generateDesignMatrix(input.col(i)); + + // tikhonov/ridge regularisation, given Ax = y where x could be noisy + // optimise the value _x = (A^T . A + R^T . R)^-1 . A^T . y + // where R is a tikhonov filter matrix, in case of ridge regression of the + // form a.I + Eigen::MatrixXd transposeDesignTikhonovProduct = + mDesignMatrix.transpose() * mDesignMatrix + + mTikhonovMatrix.transpose() * mTikhonovMatrix; + mCoefficients.col(i) = transposeDesignTikhonovProduct.inverse() * + mDesignMatrix.transpose() * output.col(i); + } - ScopedEigenMap input(in.rows(), in.cols(), alloc), - output(out.rows(), out.cols(), alloc); - input = asEigen(in); - output = asEigen(out); - calculateMappings(input, output); + mRegressed = true; + }; - asEigen(out) = output; - } + void getCoefficients(RealMatrixView coefficients) const + { + if (mInitialized) + _impl::asEigen(coefficients) = mCoefficients; + }; + + void setCoefficients(InputRealMatrixView coefficients) + { + if (!mInitialized) mInitialized = true; + + setDegree(coefficients.rows() - 1); + setDims(coefficients.cols()); + + mCoefficients = _impl::asEigen(coefficients); + mRegressed = true; + } + + void process(InputRealMatrixView in, RealMatrixView out, + Allocator& alloc = FluidDefaultAllocator()) const + { + using namespace _impl; + + ScopedEigenMap input(in.rows(), in.cols(), alloc), + output(out.rows(), out.cols(), alloc); + input = asEigen(in); + output = asEigen(out); + + calculateMappings(input, output); + + asEigen(out) = output; + } private: - void calculateMappings(Eigen::Ref in, Eigen::Ref out) const + void calculateMappings(Eigen::Ref in, + Eigen::Ref out) const + { + for (index i = 0; i < mDims; ++i) { - for(index i = 0; i < mDims; ++i) - { - generateDesignMatrix(in.col(i)); - out.col(i) = mDesignMatrix * mCoefficients.col(i); - } + generateDesignMatrix(in.col(i)); + out.col(i) = mDesignMatrix * mCoefficients.col(i); } + } - void generateDesignMatrix(Eigen::Ref in) const - { - Eigen::VectorXd designColumn = Eigen::VectorXd::Ones(in.size()); - Eigen::ArrayXd inArray = in.array(); + void generateDesignMatrix(Eigen::Ref in) const + { + Eigen::VectorXd designColumn = Eigen::VectorXd::Ones(in.size()); + Eigen::ArrayXd inArray = in.array(); - mDesignMatrix.conservativeResize(in.size(), mDegree + 1); + mDesignMatrix.conservativeResize(in.size(), mDegree + 1); - for(index i = 0; i < mDegree + 1; ++i, designColumn = designColumn.array() * inArray) - mDesignMatrix.col(i) = designColumn; - } + for (index i = 0; i < mDegree + 1; + ++i, designColumn = designColumn.array() * inArray) + mDesignMatrix.col(i) = designColumn; + } - // currently only ridge normalisation with scaled identity matrix as tikhonov filter - void generateTikhonovFilter(index size) - { - mTikhonovMatrix = mTikhonovFactor * Eigen::MatrixXd::Identity(size, size); - }; + // currently only ridge normalisation with scaled identity matrix as tikhonov + // filter + void generateTikhonovFilter(index size) + { + mTikhonovMatrix = mTikhonovFactor * Eigen::MatrixXd::Identity(size, size); + }; - index mDegree {2}; - index mDims {1}; - bool mRegressed {false}; - bool mInitialized {false}; + index mDegree{2}; + index mDims{1}; + bool mRegressed{false}; + bool mInitialized{false}; - double mTikhonovFactor {0}; + double mTikhonovFactor{0}; - Eigen::MatrixXd mCoefficients; + Eigen::MatrixXd mCoefficients; - mutable Eigen::MatrixXd mDesignMatrix; - mutable Eigen::MatrixXd mTikhonovMatrix; + mutable Eigen::MatrixXd mDesignMatrix; + mutable Eigen::MatrixXd mTikhonovMatrix; }; } // namespace algorithm diff --git a/include/clients/nrt/PolynomialRegressorClient.hpp b/include/clients/nrt/PolynomialRegressorClient.hpp index f48b326ef..23b7c6dda 100644 --- a/include/clients/nrt/PolynomialRegressorClient.hpp +++ b/include/clients/nrt/PolynomialRegressorClient.hpp @@ -12,7 +12,6 @@ under the European Union’s Horizon 2020 research and innovation programme #include "DataSetClient.hpp" #include "NRTClient.hpp" - #include "../../algorithms/public/PolynomialRegressor.hpp" namespace fluid { @@ -22,23 +21,19 @@ namespace polynomialregressor { constexpr auto PolynomialRegressorParams = defineParameters( StringParam>("name", "Name"), LongParam("degree", "Degree of polynomial", 2, Min(0)), - FloatParam("tikhonov", "Tihkonov factor for regression", 0.0, Min(0.0)) -); - -class PolynomialRegressorClient : public FluidBaseClient, - OfflineIn, - OfflineOut, - ModelObject, - public DataClient + FloatParam("tikhonov", "Tihkonov factor for regression", 0.0, Min(0.0))); + +class PolynomialRegressorClient + : public FluidBaseClient, + OfflineIn, + OfflineOut, + ModelObject, + public DataClient { - enum { - kName, - kDegree, - kTikhonov - }; + enum { kName, kDegree, kTikhonov }; public: - using string = std::string; + using string = std::string; using BufferPtr = std::shared_ptr; using InputBufferPtr = std::shared_ptr; using DataSet = FluidDataSet; @@ -47,7 +42,7 @@ class PolynomialRegressorClient : public FluidBaseClient, using ParamDescType = decltype(PolynomialRegressorParams); using ParamSetViewType = ParameterSetView; using ParamValues = typename ParamSetViewType::ValueTuple; - + std::reference_wrapper mParams; template @@ -56,7 +51,8 @@ class PolynomialRegressorClient : public FluidBaseClient, return mParams.get().template get(); } - void setParams(ParamSetViewType& p) { + void setParams(ParamSetViewType& p) + { mParams = p; mAlgorithm.setDegree(get()); mAlgorithm.setTikhonov(get()); @@ -66,8 +62,8 @@ class PolynomialRegressorClient : public FluidBaseClient, { return PolynomialRegressorParams; } - - PolynomialRegressorClient(ParamSetViewType& p, FluidContext&) : mParams(p) + + PolynomialRegressorClient(ParamSetViewType& p, FluidContext&) : mParams(p) { controlChannelsIn(1); controlChannelsOut({1, 1}); @@ -86,7 +82,7 @@ class PolynomialRegressorClient : public FluidBaseClient, if (!targetClientPtr) return Error(NoDataSet); auto targetDataSet = targetClientPtr->getDataSet(); if (targetDataSet.size() == 0) return Error(EmptyDataSet); - + auto sourceClientPtr = source.get().lock(); if (!sourceClientPtr) return Error(NoDataSet); auto sourceDataSet = sourceClientPtr->getDataSet(); @@ -99,7 +95,7 @@ class PolynomialRegressorClient : public FluidBaseClient, return Error(WrongPointSize); mAlgorithm.init(get(), sourceDataSet.dims(), get()); - + RealMatrixView data = sourceDataSet.getData(); RealMatrixView tgt = targetDataSet.getData(); @@ -108,8 +104,7 @@ class PolynomialRegressorClient : public FluidBaseClient, return OK(); } - MessageResult predict(InputDataSetClientRef src, - DataSetClientRef dest) + MessageResult predict(InputDataSetClientRef src, DataSetClientRef dest) { index inputSize = mAlgorithm.dims(); index outputSize = mAlgorithm.dims(); @@ -125,7 +120,7 @@ class PolynomialRegressorClient : public FluidBaseClient, if (srcDataSet.dims() != inputSize) return Error(WrongPointSize); StringVector ids{srcDataSet.getIds()}; - RealMatrix output(srcDataSet.size(), outputSize); + RealMatrix output(srcDataSet.size(), outputSize); mAlgorithm.process(srcDataSet.getData(), output); @@ -143,7 +138,7 @@ class PolynomialRegressorClient : public FluidBaseClient, if (!in || !out) return Error(NoBuffer); BufferAdaptor::ReadAccess inBuf(in.get()); - BufferAdaptor::Access outBuf(out.get()); + BufferAdaptor::Access outBuf(out.get()); if (!inBuf.exists()) return Error(InvalidBuffer); if (!outBuf.exists()) return Error(InvalidBuffer); @@ -156,7 +151,7 @@ class PolynomialRegressorClient : public FluidBaseClient, RealMatrix src(inputSize, 1); RealMatrix dest(outputSize, 1); - + src.col(0) <<= inBuf.samps(0, inputSize, 0); mAlgorithm.process(src, dest); outBuf.samps(0, outputSize, 0) <<= dest.col(0); @@ -164,24 +159,20 @@ class PolynomialRegressorClient : public FluidBaseClient, return OK(); } - + MessageResult print() { - return "PolynomialRegressor " - + std::string(get()) - + "\npolynimal degree: " - + std::to_string(mAlgorithm.degree()) - + "\nparallel regressors: " - + std::to_string(mAlgorithm.dims()) - + "\nTikhonov regularisation factor: " - + std::to_string(mAlgorithm.tihkonov()) - + "\nregressed: " - + (mAlgorithm.regressed() ? "true" : "false"); + return "PolynomialRegressor " + std::string(get()) + + "\npolynimal degree: " + std::to_string(mAlgorithm.degree()) + + "\nparallel regressors: " + std::to_string(mAlgorithm.dims()) + + "\nTikhonov regularisation factor: " + + std::to_string(mAlgorithm.tihkonov()) + + "\nregressed: " + (mAlgorithm.regressed() ? "true" : "false"); } MessageResult write(string fileName) { - if(!mAlgorithm.regressed()) return Error(NoDataFitted); + if (!mAlgorithm.regressed()) return Error(NoDataFitted); return DataClient::write(fileName); } @@ -203,18 +194,17 @@ class PolynomialRegressorClient : public FluidBaseClient, static auto getMessageDescriptors() { return defineMessages( - makeMessage("fit", &PolynomialRegressorClient::fit), - makeMessage("dims", &PolynomialRegressorClient::dims), - makeMessage("clear", &PolynomialRegressorClient::clear), - makeMessage("size", &PolynomialRegressorClient::size), - makeMessage("print", &PolynomialRegressorClient::print), - makeMessage("predict",&PolynomialRegressorClient::predict), - makeMessage("predictPoint", - &PolynomialRegressorClient::predictPoint), - makeMessage("load", &PolynomialRegressorClient::load), - makeMessage("dump", &PolynomialRegressorClient::dump), - makeMessage("write", &PolynomialRegressorClient::write), - makeMessage("read", &PolynomialRegressorClient::read)); + makeMessage("fit", &PolynomialRegressorClient::fit), + makeMessage("dims", &PolynomialRegressorClient::dims), + makeMessage("clear", &PolynomialRegressorClient::clear), + makeMessage("size", &PolynomialRegressorClient::size), + makeMessage("print", &PolynomialRegressorClient::print), + makeMessage("predict", &PolynomialRegressorClient::predict), + makeMessage("predictPoint", &PolynomialRegressorClient::predictPoint), + makeMessage("load", &PolynomialRegressorClient::load), + makeMessage("dump", &PolynomialRegressorClient::dump), + makeMessage("write", &PolynomialRegressorClient::write), + makeMessage("read", &PolynomialRegressorClient::read)); } private: @@ -231,7 +221,7 @@ using PolynomialRegressorRef = SharedClientRef; constexpr auto PolynomialRegressorQueryParams = defineParameters( PolynomialRegressorRef::makeParam("model", "Source Model"), - LongParam("degree", "Prediction Polynomial Degree", 2, Min(0) ), + LongParam("degree", "Prediction Polynomial Degree", 2, Min(0)), InputDataSetClientRef::makeParam("dataSet", "DataSet Name"), InputBufferParam("inputPointBuffer", "Input Point Buffer"), BufferParam("predictionBuffer", "Prediction Buffer")); @@ -243,7 +233,7 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut public: using ParamDescType = decltype(PolynomialRegressorQueryParams); using ParamSetViewType = ParameterSetView; - + std::reference_wrapper mParams; void setParams(ParamSetViewType& p) { mParams = p; } @@ -259,8 +249,7 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut return PolynomialRegressorQueryParams; } - PolynomialRegressorQuery(ParamSetViewType& p, FluidContext& c) - : mParams(p) + PolynomialRegressorQuery(ParamSetViewType& p, FluidContext& c) : mParams(p) { controlChannelsIn(1); controlChannelsOut({1, 1}); @@ -269,17 +258,15 @@ class PolynomialRegressorQuery : public FluidBaseClient, ControlIn, ControlOut template void process(std::vector>& input, std::vector>& output, FluidContext& c) - { - - } + {} index latency() { return 0; } -}; +}; } // namespace polynomialregressor -using NRTThreadedPolynomialRegressorClient = - NRTThreadingAdaptor; +using NRTThreadedPolynomialRegressorClient = NRTThreadingAdaptor< + typename polynomialregressor::PolynomialRegressorRef::SharedType>; using RTPolynomialRegressorQueryClient = ClientWrapper; From 8702f6dad282ccba40b99972812afecd5854d65b Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 28 Aug 2023 13:26:52 +0100 Subject: [PATCH 29/30] re-allocate memory on regression for first run --- include/algorithms/public/PolynomialRegressor.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 868975049..68398448f 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -84,6 +84,7 @@ class PolynomialRegressor input = asEigen(in); output = asEigen(out); + mCoefficients.conservativeResize(mDegree + 1, mDims); generateTikhonovFilter(mDegree + 1); for (index i = 0; i < mDims; ++i) From 59d49322cd6a1b64c7af5ec033e02fa913ae7066 Mon Sep 17 00:00:00 2001 From: lewardo Date: Mon, 28 Aug 2023 18:44:30 +0100 Subject: [PATCH 30/30] now using the fluid memory allocator --- .../algorithms/public/PolynomialRegressor.hpp | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/include/algorithms/public/PolynomialRegressor.hpp b/include/algorithms/public/PolynomialRegressor.hpp index 68398448f..f70701fad 100644 --- a/include/algorithms/public/PolynomialRegressor.hpp +++ b/include/algorithms/public/PolynomialRegressor.hpp @@ -52,7 +52,6 @@ class PolynomialRegressor if (mDegree == degree) return; mDegree = degree; - mCoefficients.conservativeResize(mDegree + 1, mDims); mRegressed = false; } @@ -61,7 +60,6 @@ class PolynomialRegressor if (mDims == dims) return; mDims = dims; - mCoefficients.conservativeResize(mDegree + 1, mDims); mRegressed = false; } @@ -78,14 +76,20 @@ class PolynomialRegressor Allocator& alloc = FluidDefaultAllocator()) { using namespace _impl; + using namespace Eigen; - ScopedEigenMap input(in.rows(), in.cols(), alloc), - output(out.rows(), out.cols(), alloc); - input = asEigen(in); - output = asEigen(out); + ScopedEigenMap input(in.rows(), in.cols(), alloc), + output(out.rows(), out.cols(), alloc), + transposeProduct(mDegree + 1, mDegree + 1, alloc); - mCoefficients.conservativeResize(mDegree + 1, mDims); - generateTikhonovFilter(mDegree + 1); + input = asEigen(in); + output = asEigen(out); + + mCoefficients.resize(mDegree + 1, mDims); + mTikhonovMatrix.resize(mDegree + 1, mDegree + 1); + + asEigen(mTikhonovMatrix) = + mTikhonovFactor * MatrixXd::Identity(mDegree + 1, mDegree + 1); for (index i = 0; i < mDims; ++i) { @@ -95,21 +99,21 @@ class PolynomialRegressor // optimise the value _x = (A^T . A + R^T . R)^-1 . A^T . y // where R is a tikhonov filter matrix, in case of ridge regression of the // form a.I - Eigen::MatrixXd transposeDesignTikhonovProduct = - mDesignMatrix.transpose() * mDesignMatrix + - mTikhonovMatrix.transpose() * mTikhonovMatrix; - mCoefficients.col(i) = transposeDesignTikhonovProduct.inverse() * - mDesignMatrix.transpose() * output.col(i); + transposeProduct = asEigen(mDesignMatrix).transpose() * + asEigen(mDesignMatrix) + + asEigen(mTikhonovMatrix).transpose() * + asEigen(mTikhonovMatrix); + asEigen(mCoefficients.col(i)) = + transposeProduct.inverse() * + asEigen(mDesignMatrix).transpose() * output.col(i); } - mRegressed = true; }; void getCoefficients(RealMatrixView coefficients) const { - if (mInitialized) - _impl::asEigen(coefficients) = mCoefficients; + if (mInitialized) coefficients <<= mCoefficients; }; void setCoefficients(InputRealMatrixView coefficients) @@ -119,7 +123,7 @@ class PolynomialRegressor setDegree(coefficients.rows() - 1); setDims(coefficients.cols()); - mCoefficients = _impl::asEigen(coefficients); + mCoefficients <<= coefficients; mRegressed = true; } @@ -127,47 +131,43 @@ class PolynomialRegressor Allocator& alloc = FluidDefaultAllocator()) const { using namespace _impl; + using namespace Eigen; - ScopedEigenMap input(in.rows(), in.cols(), alloc), - output(out.rows(), out.cols(), alloc); - input = asEigen(in); - output = asEigen(out); + ScopedEigenMap coefficientsColumn(mCoefficients.rows(), alloc), + inputColumn(in.rows(), alloc); - calculateMappings(input, output); - - asEigen(out) = output; - } - -private: - void calculateMappings(Eigen::Ref in, - Eigen::Ref out) const - { for (index i = 0; i < mDims; ++i) { - generateDesignMatrix(in.col(i)); - out.col(i) = mDesignMatrix * mCoefficients.col(i); + inputColumn = asEigen(in.col(i)); + coefficientsColumn = asEigen(mCoefficients.col(i)); + + generateDesignMatrix(inputColumn); + + asEigen(out.col(i)) = + asEigen(mDesignMatrix) * coefficientsColumn; } } - void generateDesignMatrix(Eigen::Ref in) const +private: + void generateDesignMatrix(Eigen::Ref in, + Allocator& alloc = FluidDefaultAllocator()) const { - Eigen::VectorXd designColumn = Eigen::VectorXd::Ones(in.size()); - Eigen::ArrayXd inArray = in.array(); + using namespace _impl; + using namespace Eigen; + + ScopedEigenMap designColumn(in.size(), alloc), + inArray(in.size(), alloc); - mDesignMatrix.conservativeResize(in.size(), mDegree + 1); + designColumn = VectorXd::Ones(in.size()); + inArray = in.array(); + + mDesignMatrix.resize(in.size(), mDegree + 1); for (index i = 0; i < mDegree + 1; - ++i, designColumn = designColumn.array() * inArray) - mDesignMatrix.col(i) = designColumn; + ++i, designColumn = designColumn * inArray) + asEigen(mDesignMatrix.col(i)) = designColumn; } - // currently only ridge normalisation with scaled identity matrix as tikhonov - // filter - void generateTikhonovFilter(index size) - { - mTikhonovMatrix = mTikhonovFactor * Eigen::MatrixXd::Identity(size, size); - }; - index mDegree{2}; index mDims{1}; bool mRegressed{false}; @@ -175,10 +175,10 @@ class PolynomialRegressor double mTikhonovFactor{0}; - Eigen::MatrixXd mCoefficients; + RealMatrix mCoefficients; - mutable Eigen::MatrixXd mDesignMatrix; - mutable Eigen::MatrixXd mTikhonovMatrix; + mutable RealMatrix mDesignMatrix; + mutable RealMatrix mTikhonovMatrix; }; } // namespace algorithm