From 3d480735740a0cbf798f850bd662bb1211fd905e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana?= Date: Sat, 10 Dec 2022 14:32:28 +0100 Subject: [PATCH] Refactor samples and fix Metrics tests --- README.md | 4 +- fimdlp/CPPFImdlp.cpp | 27 +--- fimdlp/CPPFImdlp.h | 16 +-- fimdlp/Metrics.cpp | 7 +- fimdlp/Metrics.h | 7 +- fimdlp/_version.py | 2 +- fimdlp/cfimdlp.pyx | 15 +- fimdlp/cppfimdlp.cpython-310-darwin.so | Bin 120280 -> 94112 bytes fimdlp/mdlp.py | 88 +++++------- fimdlp/testcpp/FImdlp_unittest.cc | 135 ++++++++---------- fimdlp/testcpp/Metrics_unittest.cc | 54 ++++--- fimdlp/testcpp/main | Bin 498817 -> 0 bytes fimdlp/testcpp/xx/ArffFiles.cpp | 6 +- fimdlp/testcpp/xx/ArffFiles.h | 2 +- fimdlp/tests/FImdlp_test.py | 91 ++++++++++-- fimdlp/typesFImdlp.h | 4 +- sample.py | 37 ----- {fimdlp/testcpp => samples}/ArffFiles.cpp | 6 +- {fimdlp/testcpp => samples}/ArffFiles.h | 2 +- samples/CMakeLists.txt | 6 + fimdlp/testcpp/main.cpp => samples/sample.cpp | 6 +- samples/sample.py | 44 ++++++ 22 files changed, 301 insertions(+), 258 deletions(-) delete mode 100755 fimdlp/testcpp/main delete mode 100644 sample.py rename {fimdlp/testcpp => samples}/ArffFiles.cpp (95%) rename {fimdlp/testcpp => samples}/ArffFiles.h (91%) create mode 100644 samples/CMakeLists.txt rename fimdlp/testcpp/main.cpp => samples/sample.cpp (91%) create mode 100644 samples/sample.py diff --git a/README.md b/README.md index e249e1c..906273f 100644 --- a/README.md +++ b/README.md @@ -6,5 +6,7 @@ Fayyad - Irani MDLP discretization algorithm ```bash python setup.py build_ext --inplace -python sample.py +python samples/sample.py iris --original +python samples/sample.py iris --proposal +python samples/sample.py -h # for more options ``` diff --git a/fimdlp/CPPFImdlp.cpp b/fimdlp/CPPFImdlp.cpp index 56f8ea2..f078ecb 100644 --- a/fimdlp/CPPFImdlp.cpp +++ b/fimdlp/CPPFImdlp.cpp @@ -1,21 +1,17 @@ #include -#include #include #include #include "CPPFImdlp.h" #include "Metrics.h" namespace mdlp { - CPPFImdlp::CPPFImdlp(): proposal(true), debug(false), indices(indices_t()), y(labels()), metrics(Metrics(y, indices)) - { - } - CPPFImdlp::CPPFImdlp(bool proposal, bool debug): proposal(proposal), debug(debug), indices(indices_t()), y(labels()), metrics(Metrics(y, indices)) + CPPFImdlp::CPPFImdlp(bool proposal):proposal(proposal), indices(indices_t()), y(labels_t()), metrics(Metrics(y, indices)) { } CPPFImdlp::~CPPFImdlp() = default; - CPPFImdlp& CPPFImdlp::fit(samples& X_, labels& y_) + CPPFImdlp& CPPFImdlp::fit(samples_t& X_, labels_t& y_) { X = X_; y = y_; @@ -28,8 +24,10 @@ namespace mdlp { } indices = sortIndices(X_); metrics.setData(y, indices); - //computeCutPoints(0, X.size()); - computeCutPointsProposal(); + if (proposal) + computeCutPointsProposal(); + else + computeCutPoints(0, X.size()); return *this; } void CPPFImdlp::computeCutPoints(size_t start, size_t end) @@ -53,7 +51,6 @@ namespace mdlp { } void CPPFImdlp::computeCutPointsOriginal(size_t start, size_t end) { - size_t idx; precision_t cut; if (end - start < 2) return; @@ -76,14 +73,9 @@ namespace mdlp { yCur = yPrev = y[indices[0]]; numElements = indices.size() - 1; idx = start = 0; - bool firstCutPoint = true; - if (debug) - printf("*idx=%lu -> (-1, -1) Prev(%3.1f, %d) Elementos: %lu\n", idx, xCur, yCur, numElements); while (idx < numElements) { xPivot = xCur; yPivot = yCur; - if (debug) - printf(" Prev(%3.1f, %d) Pivot(%3.1f, %d) Cur(%3.1f, %d) \n", idx, xPrev, yPrev, xPivot, yPivot, xCur, yCur); // Read the same values and check class changes do { idx++; @@ -92,17 +84,12 @@ namespace mdlp { if (yCur != yPivot && xCur == xPivot) { yPivot = -1; } - if (debug) - printf(">idx=%lu -> Prev(%3.1f, %d) Pivot(%3.1f, %d) Cur(%3.1f, %d) \n", idx, xPrev, yPrev, xPivot, yPivot, xCur, yCur); } while (idx < numElements && xCur == xPivot); // Check if the class changed and there are more than 1 element if ((idx - start > 1) && (yPivot == -1 || yPrev != yCur) && mdlp(start, idx, indices.size())) { start = idx; cutPoint = (xPrev + xCur) / 2; - if (debug) { - printf("Cutpoint idx=%lu Cur(%3.1f, %d) Prev(%3.1f, %d) Pivot(%3.1f, %d) = %3.1g \n", idx, xCur, yCur, xPrev, yPrev, xPivot, yPivot, cutPoint); - } cutPoints.push_back(cutPoint); } yPrev = yPivot; @@ -160,7 +147,7 @@ namespace mdlp { return output; } // Argsort from https://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes - indices_t CPPFImdlp::sortIndices(samples& X_) + indices_t CPPFImdlp::sortIndices(samples_t& X_) { indices_t idx(X_.size()); iota(idx.begin(), idx.end(), 0); diff --git a/fimdlp/CPPFImdlp.h b/fimdlp/CPPFImdlp.h index bc4285f..cab886a 100644 --- a/fimdlp/CPPFImdlp.h +++ b/fimdlp/CPPFImdlp.h @@ -6,15 +6,14 @@ namespace mdlp { class CPPFImdlp { protected: - bool proposal; // proposed algorithm or original algorithm - bool debug; + bool proposal; indices_t indices; // sorted indices to use with X and y - samples X; - labels y; + samples_t X; + labels_t y; Metrics metrics; cutPoints_t cutPoints; - static indices_t sortIndices(samples&); + static indices_t sortIndices(samples_t&); void computeCutPoints(size_t, size_t); long int getCandidate(size_t, size_t); bool mdlp(size_t, size_t, size_t); @@ -25,11 +24,10 @@ namespace mdlp { void computeCutPointsProposal(); public: - CPPFImdlp(); - CPPFImdlp(bool, bool debug = false); + CPPFImdlp(bool); ~CPPFImdlp(); - CPPFImdlp& fit(samples&, labels&); - samples getCutPoints(); + CPPFImdlp& fit(samples_t&, labels_t&); + samples_t getCutPoints(); }; } #endif \ No newline at end of file diff --git a/fimdlp/Metrics.cpp b/fimdlp/Metrics.cpp index f2e54f5..1275b00 100644 --- a/fimdlp/Metrics.cpp +++ b/fimdlp/Metrics.cpp @@ -1,8 +1,9 @@ #include "Metrics.h" #include +#include using namespace std; namespace mdlp { - Metrics::Metrics(labels& y_, indices_t& indices_): y(y_), indices(indices_), numClasses(computeNumClasses(0, indices.size())), entropyCache(cacheEnt_t()), igCache(cacheIg_t()) + Metrics::Metrics(labels_t& y_, indices_t& indices_): y(y_), indices(indices_), numClasses(computeNumClasses(0, indices.size())), entropyCache(cacheEnt_t()), igCache(cacheIg_t()) { } int Metrics::computeNumClasses(size_t start, size_t end) @@ -13,7 +14,7 @@ namespace mdlp { } return nClasses.size(); } - void Metrics::setData(labels& y_, indices_t& indices_) + void Metrics::setData(labels_t& y_, indices_t& indices_) { indices = indices_; y = y_; @@ -25,7 +26,7 @@ namespace mdlp { { precision_t p, ventropy = 0; int nElements = 0; - labels counts(numClasses + 1, 0); + labels_t counts(numClasses + 1, 0); if (end - start < 2) return 0; if (entropyCache.find(make_tuple(start, end)) != entropyCache.end()) { diff --git a/fimdlp/Metrics.h b/fimdlp/Metrics.h index 79bc286..a371502 100644 --- a/fimdlp/Metrics.h +++ b/fimdlp/Metrics.h @@ -1,18 +1,17 @@ #ifndef CCMETRICS_H #define CCMETRICS_H #include "typesFImdlp.h" -#include namespace mdlp { class Metrics { protected: - labels& y; + labels_t& y; indices_t& indices; int numClasses; cacheEnt_t entropyCache; cacheIg_t igCache; public: - Metrics(labels&, indices_t&); - void setData(labels&, indices_t&); + Metrics(labels_t&, indices_t&); + void setData(labels_t&, indices_t&); int computeNumClasses(size_t, size_t); precision_t entropy(size_t, size_t); precision_t informationGain(size_t, size_t, size_t); diff --git a/fimdlp/_version.py b/fimdlp/_version.py index c12f34c..d69d16e 100644 --- a/fimdlp/_version.py +++ b/fimdlp/_version.py @@ -1 +1 @@ -__version__ = '0.1.1' \ No newline at end of file +__version__ = "0.9.1" diff --git a/fimdlp/cfimdlp.pyx b/fimdlp/cfimdlp.pyx index db87af1..3ffea79 100644 --- a/fimdlp/cfimdlp.pyx +++ b/fimdlp/cfimdlp.pyx @@ -6,24 +6,15 @@ from libcpp cimport bool cdef extern from "CPPFImdlp.h" namespace "mdlp": ctypedef float precision_t cdef cppclass CPPFImdlp: - CPPFImdlp() except + - CPPFImdlp(bool, bool) except + + CPPFImdlp(bool) except + CPPFImdlp& fit(vector[precision_t]&, vector[int]&) vector[precision_t] getCutPoints() -class PcutPoint_t: - def __init__(self, start, end, fromValue, toValue): - self.start = start - self.end = end - self.fromValue = fromValue - self.toValue = toValue - cdef class CFImdlp: cdef CPPFImdlp *thisptr - def __cinit__(self, debug=False, proposal=True): - # Proposal or original algorithm - self.thisptr = new CPPFImdlp(proposal, debug) + def __cinit__(self, proposal): + self.thisptr = new CPPFImdlp(proposal) def __dealloc__(self): del self.thisptr def fit(self, X, y): diff --git a/fimdlp/cppfimdlp.cpython-310-darwin.so b/fimdlp/cppfimdlp.cpython-310-darwin.so index d5b5e7b262153633e94c3fe5aa55c1fbf8832b30..b61ccc01760019e09855e8e5d1b3085cb9db55bf 100755 GIT binary patch delta 24312 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 literal 120280 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 ?|GTKZR<&? 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

x`kc0zu07PMhKTuo?7t{g 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

(ik3+zcy8WFXuXL)^P{8~JE1e5(3uY$ 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 diff --git a/fimdlp/mdlp.py b/fimdlp/mdlp.py index 50e5ca7..ab82dc6 100644 --- a/fimdlp/mdlp.py +++ b/fimdlp/mdlp.py @@ -3,33 +3,35 @@ from .cppfimdlp import CFImdlp from sklearn.base import BaseEstimator, TransformerMixin from sklearn.utils.multiclass import unique_labels from sklearn.utils.validation import check_X_y, check_array, check_is_fitted +from joblib import Parallel, delayed class FImdlp(TransformerMixin, BaseEstimator): - def __init__(self, proposal=True): - self.proposal = proposal # proposed algorithm or original algorithm + def __init__(self, n_jobs=-1, proposal=False): + self.n_jobs = n_jobs + self.proposal = proposal - """Fayyad - Irani MDLP discretization algorithm. + """Fayyad - Irani MDLP discretization algorithm based implementation. Parameters ---------- - demo_param : str, default='demo' - A parameter used for demonstation of how to pass and store paramters. + n_jobs : int, default=-1 + The number of jobs to run in parallel. :meth:`fit` and + :meth:`transform`, are parallelized over the features. ``-1`` means + using all cores available. Attributes ---------- n_features_ : int The number of features of the data passed to :meth:`fit`. discretizer_ : list - The list of discretizers for each feature. + The list of discretizers, one for each feature. cut_points_ : list The list of cut points for each feature. X_ : array the samples used to fit, shape (n_samples, n_features) y_ : array the labels used to fit, shape (n_samples,) - discretized_X_ : - array of the discretized samples passed to fit(n_samples, n_features) features_ : list the list of features to be discretized """ @@ -70,6 +72,8 @@ class FImdlp(TransformerMixin, BaseEstimator): y : None There is no need of a target in a transformer, yet the pipeline API requires this parameter. + features : list, default=[i for i in range(n_features)] + The list of features to be discretized. Returns ------- self : object @@ -83,36 +87,22 @@ class FImdlp(TransformerMixin, BaseEstimator): self.y_ = y self.discretizer_ = [None] * self.n_features_ self.cut_points_ = [None] * self.n_features_ - # Can do it in parallel - for feature in self.features_: - self.discretizer_[feature] = CFImdlp( - proposal=self.proposal, debug=False - ) - self.discretizer_[feature].fit(X[:, feature], y) - self.cut_points_[feature] = self.discretizer_[ - feature - ].get_cut_points() + Parallel(n_jobs=self.n_jobs, prefer="threads")( + delayed(self._fit_discretizer)(feature) + for feature in range(self.n_features_) + ) return self - def get_fitted(self): - """Return the discretized X computed during fit. + def _fit_discretizer(self, feature): + self.discretizer_[feature] = CFImdlp(proposal=self.proposal) + self.discretizer_[feature].fit(self.X_[:, feature], self.y_) + self.cut_points_[feature] = self.discretizer_[feature].get_cut_points() - Returns - ------- - X_transformed : array, shape (n_samples, n_features) - discretized X computed during fit. - """ - # Check is fit had been called - check_is_fitted(self, "n_features_") - result = np.zeros_like(self.X_, dtype=np.int32) - 1 - for feature in range(self.n_features_): - if feature in self.features_: - result[:, feature] = self.discretizer_[ - feature - ].get_discretized_values() - else: - result[:, feature] = self.X_[:, feature] - return result + def _discretize_feature(self, feature, X, result): + if feature in self.features_: + result[:, feature] = np.searchsorted(self.cut_points_[feature], X) + else: + result[:, feature] = X def transform(self, X): """Discretize X values. @@ -127,28 +117,28 @@ class FImdlp(TransformerMixin, BaseEstimator): """ # Check is fit had been called check_is_fitted(self, "n_features_") - # Input validation X = check_array(X) - # Check that the input is of the same shape as the one passed # during fit. - # if X.shape[1] != self.n_features_: - # raise ValueError( - # "Shape of input is different from what was seen in `fit`" - # ) + if X.shape[1] != self.n_features_: + raise ValueError( + "Shape of input is different from what was seen in `fit`" + ) result = np.zeros_like(X, dtype=np.int32) - 1 - # Can do it in parallel - for feature in range(self.n_features_): - if feature in self.features_: - result[:, feature] = np.searchsorted( - self.cut_points_[feature], X[:, feature] - ) - else: - result[:, feature] = X[:, feature] + Parallel(n_jobs=self.n_jobs, prefer="threads")( + delayed(self._discretize_feature)(feature, X[:, feature], result) + for feature in range(self.n_features_) + ) return result def get_cut_points(self): + """Get the cut points for each feature. + Returns + ------- + result: list + The list of cut points for each feature. + """ result = [] for feature in range(self.n_features_): result.append(self.cut_points_[feature]) diff --git a/fimdlp/testcpp/FImdlp_unittest.cc b/fimdlp/testcpp/FImdlp_unittest.cc index 173bd41..1382132 100644 --- a/fimdlp/testcpp/FImdlp_unittest.cc +++ b/fimdlp/testcpp/FImdlp_unittest.cc @@ -1,74 +1,63 @@ -//#include "gtest/gtest.h" -//#include "../Metrics.h" -//#include "../CPPFImdlp.h" -//namespace mdlp { -// class TestFImdlp : public CPPFImdlp, public testing::Test { -// public: -// TestFImdlp() : CPPFImdlp(true, true) {} -// void SetUp() -// { -// // 5.0, 5.1, 5.1, 5.1, 5.2, 5.3, 5.6, 5.7, 5.9, 6.0] -// //(5.0, 1) (5.1, 1) (5.1, 2) (5.1, 2) (5.2, 1) (5.3, 1) (5.6, 2) (5.7, 1) (5.9, 2) (6.0, 2) -// X = { 5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9 }; -// y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; -// fit(X, y); -// } -// void setProposal(bool value) -// { -// proposal = value; -// } -// void initCutPoints() -// { -// setCutPoints(cutPoints_t()); -// } -// void initIndices() -// { -// indices = indices_t(); -// } -// void initDiscretized() -// { -// xDiscretized = labels(); -// } -// void checkSortedVector(samples& X_, indices_t indices_) -// { -// X = X_; -// indices = indices_; -// indices_t testSortedIndices = sortIndices(X); -// precision_t prev = X[testSortedIndices[0]]; -// for (auto i = 0; i < X.size(); ++i) { -// EXPECT_EQ(testSortedIndices[i], indices[i]); -// EXPECT_LE(prev, X[testSortedIndices[i]]); -// prev = X[testSortedIndices[i]]; -// } -// } -// void checkCutPoints(cutPoints_t& expected) -// { -// int expectedSize = expected.size(); -// EXPECT_EQ(cutPoints.size(), expectedSize); -// for (auto i = 0; i < expectedSize; i++) { -// EXPECT_EQ(cutPoints[i].start, expected[i].start); -// EXPECT_EQ(cutPoints[i].end, expected[i].end); -// EXPECT_EQ(cutPoints[i].classNumber, expected[i].classNumber); -// EXPECT_NEAR(cutPoints[i].fromValue, expected[i].fromValue, precision); -// EXPECT_NEAR(cutPoints[i].toValue, expected[i].toValue, precision); -// } -// } -// template -// void checkVectors(std::vector const& expected, std::vector const& computed) -// { -// EXPECT_EQ(expected.size(), computed.size()); -// for (auto i = 0; i < expected.size(); i++) { -// EXPECT_EQ(expected[i], computed[i]); -// } -// } -// -// }; -// TEST_F(TestFImdlp, FitErrorEmptyDataset) -// { -// X = samples(); -// y = labels(); -// EXPECT_THROW(fit(X, y), std::invalid_argument); -// } +#include "gtest/gtest.h" +#include "../Metrics.h" +#include "../CPPFImdlp.h" +namespace mdlp { + class TestFImdlp: public CPPFImdlp, public testing::Test { + public: + TestFImdlp(): CPPFImdlp(false) {} + void SetUp() + { + // 5.0, 5.1, 5.1, 5.1, 5.2, 5.3, 5.6, 5.7, 5.9, 6.0] + //(5.0, 1) (5.1, 1) (5.1, 2) (5.1, 2) (5.2, 1) (5.3, 1) (5.6, 2) (5.7, 1) (5.9, 2) (6.0, 2) + X = { 5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9 }; + y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + fit(X, y); + } + void setProposal(bool value) + { + proposal = value; + } + void initIndices() + { + indices = indices_t(); + } + void checkSortedVector(samples_t& X_, indices_t indices_) + { + X = X_; + indices = indices_; + indices_t testSortedIndices = sortIndices(X); + precision_t prev = X[testSortedIndices[0]]; + for (auto i = 0; i < X.size(); ++i) { + EXPECT_EQ(testSortedIndices[i], indices[i]); + EXPECT_LE(prev, X[testSortedIndices[i]]); + prev = X[testSortedIndices[i]]; + } + } + void checkCutPoints(cutPoints_t& expected) + { + int expectedSize = expected.size(); + EXPECT_EQ(cutPoints.size(), expectedSize); + for (auto i = 0; i < expectedSize; i++) { + EXPECT_EQ(cutPoints[i], expected[i]); + } + } + template + void checkVectors(std::vector const& expected, std::vector const& computed) + { + EXPECT_EQ(expected.size(), computed.size()); + for (auto i = 0; i < expected.size(); i++) { + EXPECT_EQ(expected[i], computed[i]); + } + } + }; + TEST_F(TestFImdlp, FitErrorEmptyDataset) + { + X = samples_t(); + y = labels_t(); + EXPECT_THROW(fit(X, y), std::invalid_argument); + } +} +// // TEST_F(TestFImdlp, FitErrorDifferentSize) // { // X = { 1, 2, 3 }; @@ -143,7 +132,7 @@ // } // TEST_F(TestFImdlp, DiscretizedValues) // { -// labels computed, expected = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +// labels_t computed, expected = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // computed = getDiscretizedValues(); // checkVectors(expected, computed); // } @@ -157,7 +146,7 @@ // TEST_F(TestFImdlp, Constructor) // { // samples X = { 5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9 }; -// labels y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; +// labels_t y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; // setProposal(false); // fit(X, y); // computeCutPointsOriginal(); diff --git a/fimdlp/testcpp/Metrics_unittest.cc b/fimdlp/testcpp/Metrics_unittest.cc index 0bea1c1..c6e3e56 100644 --- a/fimdlp/testcpp/Metrics_unittest.cc +++ b/fimdlp/testcpp/Metrics_unittest.cc @@ -1,31 +1,43 @@ #include "gtest/gtest.h" #include "../Metrics.h" + namespace mdlp { - precision_t precision = 0.000001; - TEST(MetricTest, NumClasses) + class TestMetrics: public Metrics, public testing::Test { + public: + labels_t y; + samples_t X; + indices_t indices; + precision_t precision = 0.000001; + + TestMetrics(): Metrics(y, indices) {} + void SetUp() + { + y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + setData(y, indices); + } + }; + TEST_F(TestMetrics, NumClasses) { - labels y = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; - indices_t indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - EXPECT_EQ(1, Metrics::numClasses(y, indices, 4, 8)); - EXPECT_EQ(2, Metrics::numClasses(y, indices, 0, 10)); - EXPECT_EQ(2, Metrics::numClasses(y, indices, 8, 10)); + y = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; + EXPECT_EQ(1, computeNumClasses(4, 8)); + EXPECT_EQ(2, computeNumClasses(0, 10)); + EXPECT_EQ(2, computeNumClasses(8, 10)); } - TEST(MetricTest, Entropy) + TEST_F(TestMetrics, Entropy) { - labels y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; - indices_t indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - EXPECT_EQ(1, Metrics::entropy(y, indices, 0, 10, 2)); - EXPECT_EQ(0, Metrics::entropy(y, indices, 0, 5, 1)); - labels yz = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; - ASSERT_NEAR(0.468996, Metrics::entropy(yz, indices, 0, 10, 2), precision); + EXPECT_EQ(1, entropy(0, 10)); + EXPECT_EQ(0, entropy(0, 5)); + y = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; + setData(y, indices); + ASSERT_NEAR(0.468996, entropy(0, 10), precision); } - TEST(MetricTest, InformationGain) + TEST_F(TestMetrics, InformationGain) { - labels y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; - indices_t indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - labels yz = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; - ASSERT_NEAR(1, Metrics::informationGain(y, indices, 0, 10, 5, 2), precision); - ASSERT_NEAR(0.108032, Metrics::informationGain(yz, indices, 0, 10, 5, 2), precision); + ASSERT_NEAR(1, informationGain(0, 5, 10), precision); + y = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; + setData(y, indices); + ASSERT_NEAR(0.108032, informationGain(0, 5, 10), precision); } -} \ No newline at end of file +} diff --git a/fimdlp/testcpp/main b/fimdlp/testcpp/main deleted file mode 100755 index a1bfdfbe5a50c7c6852b1b15f128b136ba09824d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 498817 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%0A>qvxXI3VGcDn z@@+|P?zv`9E*Hei(VgrIrT6RoFXr`1zH=_~J|f?1j_UWa+uLe3V`po%?K!YpmBXuR zLS+L{WsV8V@sAmZz!hAbk z?iH~L_md6Oy{4BozGzmb4S2x!-}u&*zVQRS{m*`X$w8{laBn#BVp+%Ca%)>pc-l`+D2KdhqWZx9 zi5Ft5Ja9A~pshP_9rybUyw>5F1LdUYd9&t}b(rl^?>*+ftL`>y(Pp2FTiyG~mQyxz zYdNLekY8wEJ$ZN_Tz@xU zv$mG!&ewgLIGw@ljm*i++TSKM{JjNFP8hwdNv$m9qW5IV?crAIL8G-bS3V4L&6rX2Zf)Z4D+@zD159gK)YOCMyudWswazb?}(JL*R#u5;D;Z+Nh{HexiMhk7z%@R6j3h;^-BJmmV4 ztOOM=neNeDYyPgf&G+}y<|~*{y>x0_KgD-8v9A5%MqTQ)-a6cF?<_P|U;Pf@H+%j4 zdfI=(`uo;lX8rx}FuT31!@t z=y9yy)p4tBh79j1bBS;GswefJKoFJ`pId0N}bEPq(w;bP;e%}92nF3jk zbkH*UG{yG!h$Op|HiXDFEY@ZaWFEfSK|0QF%bwg~5_0ufreV_TRb`Br2`{G8p z!FJRi-?~=@-`M3Fyj2so@i%$P)mxsr`c5jWZ&56v1lJ27jlJ#5c2w&@3 zpC^p)U9Q!C{0Lv*S{*0JiP1mhde2zD2PPhzEo;Z{9^Ny1gjr?v&z7yj7v>A2{%=ed zkQ>2&m>p+bImd3VeTVPA)^?fu-}E5UrE^Ajh-Jecz=;`re1->-K2DHnd)qhDtlHTd zzcdG)JbLW7fxFPH=Z~}78*VmxqO$wVS%}+MzLnkduMuu# z->~P5>W>>?zW-UHv|-P5+?FU;JU=nLwev#Xk;(8aZ)Kv{Cp>Wc2pxTtpS=0uc=_5| z?nm(7@2vNUqkE3`TPvkd=dI?dP=BFJkz7H$FLC3$K9Gb)PuoS(|T9lrhO-xW%@|c2+P#EP&R+{SDUTW z@V)zGa(rz%#5$hVxbl<@y|HejN*n%&#-s9GeCL(sE0FF> z%wGCrD{ztg+UNYtbh#TgB`Y&co_Dd{O_oi*1XHZ%k{8J>^2T{n?D{;uE!()M!1t*p3p4$ zL7go>)a7(JqFhdg%i}7xxdRvgF8LePRb3{2jGIWPK!4u(edz_BY3{TM*NADKpV;qe( zSF}udn8)KvaCu@QddEZtdqP8Hq#P0P6=M<-gA-lBZjZ|??Gs%xMTwqBcZDs&9qe++ zSd`f!@*`aC*vNQ^IUUK)43|UZScHsZvJ5sV$`kEy$ZT+Q*K^GZ7xq# zsEl`LXv7MeyU$i(^SHu-yT*o;**(D-PIs^@iTFfkuq&X*=8o_<&G^SgW+lpmI2@h? zNBJ0!-Q6(8;c$3Uqa))T&R~Zp$`chS#XX_1!4CbW-WKG_aaGugZTZqHGAY90Ney

5$$WE$xZJ_jwy?IN^KcIPDhc=73D5) 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 diff --git a/fimdlp/testcpp/xx/ArffFiles.cpp b/fimdlp/testcpp/xx/ArffFiles.cpp index b8a8928..9baf861 100644 --- a/fimdlp/testcpp/xx/ArffFiles.cpp +++ b/fimdlp/testcpp/xx/ArffFiles.cpp @@ -101,13 +101,13 @@ string ArffFiles::trim(const string& source) s.erase(s.find_last_not_of(" \n\r\t") + 1); return s; } -vector ArffFiles::factorize(const vector& labels) +vector ArffFiles::factorize(const vector& labels_t) { vector yy; - yy.reserve(labels.size()); + yy.reserve(labels_t.size()); map labelMap; int i = 0; - for (string label : labels) { + for (string label : labels_t) { if (labelMap.find(label) == labelMap.end()) { labelMap[label] = i++; } diff --git a/fimdlp/testcpp/xx/ArffFiles.h b/fimdlp/testcpp/xx/ArffFiles.h index 317ebb5..6986d3b 100644 --- a/fimdlp/testcpp/xx/ArffFiles.h +++ b/fimdlp/testcpp/xx/ArffFiles.h @@ -23,6 +23,6 @@ public: vector>& getX(); vector& getY(); vector> getAttributes(); - vector factorize(const vector& labels); + vector factorize(const vector& labels_t); }; #endif \ No newline at end of file diff --git a/fimdlp/tests/FImdlp_test.py b/fimdlp/tests/FImdlp_test.py index 6d136ee..9e681e6 100644 --- a/fimdlp/tests/FImdlp_test.py +++ b/fimdlp/tests/FImdlp_test.py @@ -8,12 +8,14 @@ from ..mdlp import FImdlp class FImdlpTest(unittest.TestCase): def test_init(self): clf = FImdlp() - self.assertTrue(clf.proposal) - clf = FImdlp(proposal=False) + self.assertEqual(-1, clf.n_jobs) self.assertFalse(clf.proposal) + clf = FImdlp(proposal=True, n_jobs=7) + self.assertTrue(clf.proposal) + self.assertEqual(7, clf.n_jobs) - def test_fit(self): - clf = FImdlp() + def test_fit_proposal(self): + clf = FImdlp(proposal=True) clf.fit([[1, 2], [3, 4]], [1, 2]) self.assertEqual(clf.n_features_, 2) self.assertListEqual(clf.X_.tolist(), [[1, 2], [3, 4]]) @@ -25,10 +27,39 @@ class FImdlpTest(unittest.TestCase): self.assertTrue(np.array_equal(X, clf.X_)) self.assertTrue(np.array_equal(y, clf.y_)) expected = [ - [4.900000095367432, 5.0, 5.099999904632568, 5.400000095367432], - [2.6999998092651367, 2.9000000953674316], - [2.3499999046325684, 4.5], - [0.75, 1.399999976158142, 1.5], + [ + 4.900000095367432, + 5.0, + 5.099999904632568, + 5.400000095367432, + 5.699999809265137, + ], + [2.6999998092651367, 2.9000000953674316, 3.1999998092651367], + [2.3499999046325684, 4.5, 4.800000190734863], + [0.75, 1.399999976158142, 1.5, 1.7000000476837158], + ] + self.assertListEqual(expected, clf.get_cut_points()) + self.assertListEqual([0, 1, 2, 3], clf.features_) + clf.fit(X, y, features=[0, 2, 3]) + self.assertListEqual([0, 2, 3], clf.features_) + + def test_fit_original(self): + clf = FImdlp(proposal=False) + clf.fit([[1, 2], [3, 4]], [1, 2]) + self.assertEqual(clf.n_features_, 2) + self.assertListEqual(clf.X_.tolist(), [[1, 2], [3, 4]]) + self.assertListEqual(clf.y_.tolist(), [1, 2]) + self.assertListEqual([[], []], clf.get_cut_points()) + X, y = load_iris(return_X_y=True) + clf.fit(X, y) + self.assertEqual(clf.n_features_, 4) + self.assertTrue(np.array_equal(X, clf.X_)) + self.assertTrue(np.array_equal(y, clf.y_)) + expected = [ + [5.5, 5.800000190734863], + [3.0999999046325684], + [2.450000047683716, 4.800000190734863, 5.099999904632568], + [0.800000011920929, 1.7000000476837158], ] self.assertListEqual(expected, clf.get_cut_points()) self.assertListEqual([0, 1, 2, 3], clf.features_) @@ -44,8 +75,38 @@ class FImdlpTest(unittest.TestCase): with self.assertRaises(ValueError): clf.fit([[1, 2], [3, 4]], [1, 2], unexpected="class_name") - def test_transform(self): - clf = FImdlp() + def test_transform_original(self): + clf = FImdlp(proposal=False) + clf.fit([[1, 2], [3, 4]], [1, 2]) + self.assertEqual( + clf.transform([[1, 2], [3, 4]]).tolist(), [[0, 0], [0, 0]] + ) + X, y = load_iris(return_X_y=True) + clf.fit(X, y) + self.assertEqual(clf.n_features_, 4) + self.assertTrue(np.array_equal(X, clf.X_)) + self.assertTrue(np.array_equal(y, clf.y_)) + self.assertListEqual( + clf.transform(X).tolist(), clf.fit(X, y).transform(X).tolist() + ) + expected = [ + [0, 0, 1, 1], + [2, 0, 1, 1], + [1, 0, 1, 1], + [0, 0, 1, 1], + [1, 0, 1, 1], + [1, 0, 1, 1], + [1, 0, 1, 1], + ] + self.assertTrue(np.array_equal(clf.transform(X[90:97]), expected)) + with self.assertRaises(ValueError): + clf.transform([[1, 2, 3], [4, 5, 6]]) + with self.assertRaises(sklearn.exceptions.NotFittedError): + clf = FImdlp(proposal=False) + clf.transform([[1, 2], [3, 4]]) + + def test_transform_proposal(self): + clf = FImdlp(proposal=True) clf.fit([[1, 2], [3, 4]], [1, 2]) self.assertEqual( clf.transform([[1, 2], [3, 4]]).tolist(), [[0, 0], [0, 0]] @@ -60,16 +121,16 @@ class FImdlpTest(unittest.TestCase): ) expected = [ [4, 0, 1, 1], - [4, 2, 2, 2], - [4, 0, 1, 1], + [5, 2, 2, 2], + [5, 0, 1, 1], [1, 0, 1, 1], [4, 1, 1, 1], - [4, 2, 1, 1], - [4, 1, 1, 1], + [5, 2, 1, 1], + [5, 1, 1, 1], ] self.assertTrue(np.array_equal(clf.transform(X[90:97]), expected)) with self.assertRaises(ValueError): clf.transform([[1, 2, 3], [4, 5, 6]]) with self.assertRaises(sklearn.exceptions.NotFittedError): - clf = FImdlp() + clf = FImdlp(proposal=True) clf.transform([[1, 2], [3, 4]]) diff --git a/fimdlp/typesFImdlp.h b/fimdlp/typesFImdlp.h index b94b943..43e5842 100644 --- a/fimdlp/typesFImdlp.h +++ b/fimdlp/typesFImdlp.h @@ -6,8 +6,8 @@ using namespace std; namespace mdlp { typedef float precision_t; - typedef vector samples; - typedef vector labels; + typedef vector samples_t; + typedef vector labels_t; typedef vector indices_t; typedef vector cutPoints_t; typedef map, precision_t> cacheEnt_t; diff --git a/sample.py b/sample.py deleted file mode 100644 index 413df30..0000000 --- a/sample.py +++ /dev/null @@ -1,37 +0,0 @@ -from fimdlp.mdlp import FImdlp -from fimdlp.cppfimdlp import CFImdlp -from sklearn.ensemble import RandomForestClassifier -import time - -from scipy.io import arff -import pandas as pd - -path = "fimdlp/testcpp/datasets/" -# class_name = "speaker" -# file_name = "kdd_JapaneseVowels.arff" -class_name = "class" -# file_name = "mfeat-factors.arff" -file_name = "letter.arff" -data = arff.loadarff(path + file_name) -df = pd.DataFrame(data[0]) -df.dropna(axis=0, how="any", inplace=True) -dataset = df -X = df.drop(class_name, axis=1) -features = X.columns -class_name = class_name -y, _ = pd.factorize(df[class_name]) -X = X.to_numpy() - -test = FImdlp() -now = time.time() -# test.fit(X, y, features=[i for i in (range(3, 14))]) -test.fit(X, y) -fit_time = time.time() -print("Fitting: ", fit_time - now) -now = time.time() -Xt = test.transform(X) -print("Transforming: ", time.time() - now) -print(test.get_cut_points()) - -clf = RandomForestClassifier(random_state=0) -print(clf.fit(Xt, y).score(Xt, y)) diff --git a/fimdlp/testcpp/ArffFiles.cpp b/samples/ArffFiles.cpp similarity index 95% rename from fimdlp/testcpp/ArffFiles.cpp rename to samples/ArffFiles.cpp index b8a8928..9baf861 100644 --- a/fimdlp/testcpp/ArffFiles.cpp +++ b/samples/ArffFiles.cpp @@ -101,13 +101,13 @@ string ArffFiles::trim(const string& source) s.erase(s.find_last_not_of(" \n\r\t") + 1); return s; } -vector ArffFiles::factorize(const vector& labels) +vector ArffFiles::factorize(const vector& labels_t) { vector yy; - yy.reserve(labels.size()); + yy.reserve(labels_t.size()); map labelMap; int i = 0; - for (string label : labels) { + for (string label : labels_t) { if (labelMap.find(label) == labelMap.end()) { labelMap[label] = i++; } diff --git a/fimdlp/testcpp/ArffFiles.h b/samples/ArffFiles.h similarity index 91% rename from fimdlp/testcpp/ArffFiles.h rename to samples/ArffFiles.h index 317ebb5..6986d3b 100644 --- a/fimdlp/testcpp/ArffFiles.h +++ b/samples/ArffFiles.h @@ -23,6 +23,6 @@ public: vector>& getX(); vector& getY(); vector> getAttributes(); - vector factorize(const vector& labels); + vector factorize(const vector& labels_t); }; #endif \ No newline at end of file diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt new file mode 100644 index 0000000..df85077 --- /dev/null +++ b/samples/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.24) +project(main) + +set(CMAKE_CXX_STANDARD 17) + +add_executable(sample sample.cpp ArffFiles.cpp ../fimdlp/Metrics.cpp ../fimdlp/CPPFImdlp.cpp) diff --git a/fimdlp/testcpp/main.cpp b/samples/sample.cpp similarity index 91% rename from fimdlp/testcpp/main.cpp rename to samples/sample.cpp index 201b930..1a9e407 100644 --- a/fimdlp/testcpp/main.cpp +++ b/samples/sample.cpp @@ -2,7 +2,7 @@ #include #include #include -#include "../CPPFImdlp.h" +#include "../fimdlp/CPPFImdlp.h" using namespace std; @@ -10,7 +10,7 @@ int main(int argc, char** argv) { ArffFiles file; vector lines; - string path = "/Users/rmontanana/Code/FImdlp/fimdlp/testcpp/datasets/"; + string path = "../fimdlp/testcpp/datasets/"; map datasets = { {"mfeat-factors", true}, {"iris", true}, @@ -41,7 +41,7 @@ int main(int argc, char** argv) } cout << y[i] << endl; } - mdlp::CPPFImdlp test = mdlp::CPPFImdlp(); + mdlp::CPPFImdlp test = mdlp::CPPFImdlp(false); for (auto i = 0; i < attributes.size(); i++) { cout << "Cut points for " << get<0>(attributes[i]) << endl; cout << "--------------------------" << setprecision(3) << endl; diff --git a/samples/sample.py b/samples/sample.py new file mode 100644 index 0000000..6fcf065 --- /dev/null +++ b/samples/sample.py @@ -0,0 +1,44 @@ +import time +import argparse +import os +from scipy.io import arff +import pandas as pd +from sklearn.ensemble import RandomForestClassifier +from fimdlp.mdlp import FImdlp + +datasets = { + "mfeat-factors": True, + "iris": True, + "letter": True, + "kdd_JapaneseVowels": False, +} + +ap = argparse.ArgumentParser() +ap.add_argument("--proposal", action="store_true") +ap.add_argument("--original", dest="proposal", action="store_false") +ap.add_argument("dataset", type=str, choices=datasets.keys()) +args = ap.parse_args() +relative = "" if os.path.isdir("fimdlp") else ".." +file_name = os.path.join( + relative, "fimdlp", "testcpp", "datasets", args.dataset +) +data = arff.loadarff(file_name + ".arff") +df = pd.DataFrame(data[0]) +class_column = -1 if datasets[args.dataset] else 0 +class_name = df.columns.to_list()[class_column] +X = df.drop(class_name, axis=1) +y, _ = pd.factorize(df[class_name]) +X = X.to_numpy() +test = FImdlp(proposal=args.proposal) +now = time.time() +test.fit(X, y) +fit_time = time.time() +print("Fitting: ", fit_time - now) +now = time.time() +Xt = test.transform(X) +print("Transforming: ", time.time() - now) +print(test.get_cut_points()) +clf = RandomForestClassifier(random_state=0) +print( + "Random Forest score with discretized data: ", clf.fit(Xt, y).score(Xt, y) +)