From 7005dfb7319c6a6653fb18fdabadad66288c19ca Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Wed, 14 Jun 2023 14:10:09 -0400 Subject: [PATCH 01/18] ENH attempt for multi-output Co-Authored-By: Ronan Perry <13107341+rflperry@users.noreply.github.com> --- sktree/ensemble/_honest_forest.py | 60 ++++++++++++++++++++++-------- sktree/tests/test_honest_forest.py | 8 ++-- sktree/tree/_honest_tree.py | 54 +++++++++++++++++---------- 3 files changed, 83 insertions(+), 39 deletions(-) diff --git a/sktree/ensemble/_honest_forest.py b/sktree/ensemble/_honest_forest.py index 272878608..de4d4a576 100644 --- a/sktree/ensemble/_honest_forest.py +++ b/sktree/ensemble/_honest_forest.py @@ -400,7 +400,7 @@ def fit(self, X, y, sample_weight=None): Fitted tree estimator. """ super().fit(X, y, sample_weight) - X, y = check_X_y(X, y, multi_output=False) + X, y = check_X_y(X, y, multi_output=True) classes_k, y_encoded = np.unique(y, return_inverse=True) self.empirical_prior_ = np.bincount(y_encoded, minlength=classes_k.shape[0]) / len(y) @@ -440,7 +440,11 @@ def _predict_proba(self, X, indices=None, impute_missing=None): n_jobs, _, _ = _partition_estimators(self.n_estimators, self.n_jobs) # avoid storing the output of every tree estimator by summing them here - posteriors = np.zeros((X.shape[0], self.n_classes_), dtype=np.float64) + if self.n_outputs_ > 1: + posteriors = np.zeros((X.shape[0], self.n_classes_[0]), dtype=np.float64) + posteriors = np.array([posteriors for _ in range(len(self.n_classes_))]) + else: + posteriors = np.zeros((X.shape[0], self.n_classes_), dtype=np.float64) lock = threading.Lock() if indices is None: @@ -449,10 +453,14 @@ def _predict_proba(self, X, indices=None, impute_missing=None): delayed(_accumulate_prediction)(tree, X, posteriors, lock, idx) for tree, idx in zip(self.estimators_, indices) ) - # Normalize to unit length, due to prior weighting - zero_mask = posteriors.sum(1) == 0 - posteriors[~zero_mask] /= posteriors[~zero_mask].sum(1, keepdims=True) + if self.n_outputs_ > 1: + zero_mask = posteriors.sum(2) == 0 + posteriors[~zero_mask] /= posteriors[~zero_mask].sum(1, keepdims=True) + else: + zero_mask = posteriors.sum(1) == 0 + posteriors[~zero_mask] /= posteriors[~zero_mask].sum(1, keepdims=True) + if impute_missing is None: posteriors[zero_mask] = self.empirical_prior_ else: @@ -486,14 +494,36 @@ def _accumulate_prediction(tree, X, out, lock, indices=None): if indices is None: indices = np.arange(X.shape[0]) proba = tree.tree_.predict(X[indices]) - proba = proba[:, : tree._tree_n_classes_] - normalizer = proba.sum(axis=1)[:, np.newaxis] - normalizer[normalizer == 0.0] = 1.0 - proba /= normalizer - - if tree._tree_n_classes_ != tree.n_classes_: - proba = tree._impute_missing_classes(proba) - proba = tree._empty_leaf_correction(proba, normalizer) - with lock: - out[indices] += proba + # for single output cases: + if tree.n_outputs_ == 1: + proba = proba[:, : tree._tree_n_classes_] + normalizer = proba.sum(axis=1)[:, np.newaxis] + normalizer[normalizer == 0.0] = 1.0 + proba /= normalizer + + if tree._tree_n_classes_ != tree.n_classes_: + proba = tree._impute_missing_classes(proba) + proba = tree._empty_leaf_correction(proba) + + with lock: + out[indices] += proba + + # for multi-output cases + else: + all_proba = [] + + for k in range(tree.n_outputs_): + proba_k = proba[:, k, : tree._tree_n_classes_[k]] + normalizer = proba_k.sum(axis=1)[:, np.newaxis] + normalizer[normalizer == 0.0] = 1.0 + proba_k /= normalizer + + if tree._tree_n_classes_[k] != tree.n_classes_[k]: + proba_k = tree._impute_missing_classes(proba_k) + proba_k = tree._empty_leaf_correction(proba_k, k) + all_proba.append(proba_k) + + with lock: + for k in range(tree.n_outputs_): + out[k][indices] += all_proba[k] diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index dd7500584..1ed5b2377 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -145,10 +145,10 @@ def test_sklearn_compatible_estimator(estimator, check): # for fitting the tree's splits if check.func.__name__ in [ "check_class_weight_classifiers", - "check_classifiers_multilabel_output_format_decision_function", - "check_classifiers_multilabel_output_format_predict_proba", - "check_classifiers_multilabel_output_format_predict", - "check_classifiers_multilabel_representation_invariance", + # "check_classifiers_multilabel_output_format_decision_function", + # "check_classifiers_multilabel_output_format_predict_proba", + # "check_classifiers_multilabel_output_format_predict", + # "check_classifiers_multilabel_representation_invariance", ]: pytest.skip() check(estimator) diff --git a/sktree/tree/_honest_tree.py b/sktree/tree/_honest_tree.py index c3a327ea3..367d3404c 100644 --- a/sktree/tree/_honest_tree.py +++ b/sktree/tree/_honest_tree.py @@ -360,12 +360,6 @@ def fit(self, X, y, sample_weight=None, check_input=True): ) self._inherit_estimator_attributes() - if self.n_outputs_ > 1: - raise NotImplementedError( - "Multi-target honest trees not yet \ - implemented" - ) - # update the number of classes, unsplit if y.ndim == 1: # reshape is necessary to preserve the data contiguity against vs @@ -423,18 +417,29 @@ def _inherit_estimator_attributes(self): self.n_outputs_ = self.estimator_.n_outputs_ self.tree_ = self.estimator_.tree_ - def _empty_leaf_correction(self, proba, normalizer): + def _empty_leaf_correction(self, proba, pos=0): """Leaves with empty posteriors are assigned values""" zero_mask = proba.sum(axis=1) == 0.0 - if self.honest_prior == "empirical": - proba[zero_mask] = self.empirical_prior_ - elif self.honest_prior == "uniform": - proba[zero_mask] = 1 / self.n_classes_ - elif self.honest_prior == "ignore": - proba[zero_mask] = np.nan - else: - raise ValueError(f"honest_prior {self.honest_prior} not a valid input.") + # For multi-output cases + if self.n_outputs_ > 1: + if self.honest_prior == "empirical": + proba[zero_mask] = self.empirical_prior_[pos] + elif self.honest_prior == "uniform": + proba[zero_mask] = 1 / self.n_classes_[pos] + elif self.honest_prior == "ignore": + proba[zero_mask] = np.nan + else: + raise ValueError(f"honest_prior {self.honest_prior} not a valid input.") + else: + if self.honest_prior == "empirical": + proba[zero_mask] = self.empirical_prior_ + elif self.honest_prior == "uniform": + proba[zero_mask] = 1 / self.n_classes_ + elif self.honest_prior == "ignore": + proba[zero_mask] = np.nan + else: + raise ValueError(f"honest_prior {self.honest_prior} not a valid input.") return proba def _impute_missing_classes(self, proba): @@ -481,15 +486,24 @@ class in a leaf. proba /= normalizer if self._tree_n_classes_ != self.n_classes_: proba = self._impute_missing_classes(proba) - proba = self._empty_leaf_correction(proba, normalizer) + proba = self._empty_leaf_correction(proba) return proba else: - raise NotImplementedError( - "Multi-target honest trees not yet \ - implemented" - ) + all_proba = [] + + for k in range(self.n_outputs_): + proba_k = proba[:, k, : self._tree_n_classes_[k]] + normalizer = proba_k.sum(axis=1)[:, np.newaxis] + normalizer[normalizer == 0.0] = 1.0 + proba_k /= normalizer + if self._tree_n_classes_[k] != self.n_classes_[k]: + proba_k = self._impute_missing_classes(proba_k) + proba_k = self._empty_leaf_correction(proba_k, k) + all_proba.append(proba_k) + + return all_proba def predict(self, X, check_input=True): """Predict class for X. From 2c3606b7bb8a1e618be388becd1c71155399c277 Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Wed, 14 Jun 2023 16:00:03 -0400 Subject: [PATCH 02/18] ENH simplify predict_proba & multi-output --- sktree/ensemble/_honest_forest.py | 64 +++++++++--------------------- sktree/tests/test_honest_forest.py | 7 +--- 2 files changed, 20 insertions(+), 51 deletions(-) diff --git a/sktree/ensemble/_honest_forest.py b/sktree/ensemble/_honest_forest.py index de4d4a576..f843051a7 100644 --- a/sktree/ensemble/_honest_forest.py +++ b/sktree/ensemble/_honest_forest.py @@ -440,11 +440,9 @@ def _predict_proba(self, X, indices=None, impute_missing=None): n_jobs, _, _ = _partition_estimators(self.n_estimators, self.n_jobs) # avoid storing the output of every tree estimator by summing them here - if self.n_outputs_ > 1: - posteriors = np.zeros((X.shape[0], self.n_classes_[0]), dtype=np.float64) - posteriors = np.array([posteriors for _ in range(len(self.n_classes_))]) - else: - posteriors = np.zeros((X.shape[0], self.n_classes_), dtype=np.float64) + posteriors = [ + np.zeros((X.shape[0], j), dtype=np.float64) for j in np.atleast_1d(self.n_classes_) + ] lock = threading.Lock() if indices is None: @@ -454,19 +452,19 @@ def _predict_proba(self, X, indices=None, impute_missing=None): for tree, idx in zip(self.estimators_, indices) ) # Normalize to unit length, due to prior weighting - if self.n_outputs_ > 1: - zero_mask = posteriors.sum(2) == 0 - posteriors[~zero_mask] /= posteriors[~zero_mask].sum(1, keepdims=True) - else: - zero_mask = posteriors.sum(1) == 0 - posteriors[~zero_mask] /= posteriors[~zero_mask].sum(1, keepdims=True) + posteriors = np.array(posteriors) + zero_mask = posteriors.sum(2) == 0 + posteriors[~zero_mask] /= posteriors[~zero_mask].sum(1, keepdims=True) if impute_missing is None: posteriors[zero_mask] = self.empirical_prior_ else: posteriors[zero_mask] = impute_missing - return posteriors + if len(posteriors) == 1: + return posteriors[0] + else: + return posteriors @property def structure_indices_(self): @@ -493,37 +491,11 @@ def _accumulate_prediction(tree, X, out, lock, indices=None): if indices is None: indices = np.arange(X.shape[0]) - proba = tree.tree_.predict(X[indices]) - - # for single output cases: - if tree.n_outputs_ == 1: - proba = proba[:, : tree._tree_n_classes_] - normalizer = proba.sum(axis=1)[:, np.newaxis] - normalizer[normalizer == 0.0] = 1.0 - proba /= normalizer - - if tree._tree_n_classes_ != tree.n_classes_: - proba = tree._impute_missing_classes(proba) - proba = tree._empty_leaf_correction(proba) - - with lock: - out[indices] += proba - - # for multi-output cases - else: - all_proba = [] - - for k in range(tree.n_outputs_): - proba_k = proba[:, k, : tree._tree_n_classes_[k]] - normalizer = proba_k.sum(axis=1)[:, np.newaxis] - normalizer[normalizer == 0.0] = 1.0 - proba_k /= normalizer - - if tree._tree_n_classes_[k] != tree.n_classes_[k]: - proba_k = tree._impute_missing_classes(proba_k) - proba_k = tree._empty_leaf_correction(proba_k, k) - all_proba.append(proba_k) - - with lock: - for k in range(tree.n_outputs_): - out[k][indices] += all_proba[k] + proba = tree.predict_proba(X[indices], check_input=False) + + with lock: + if len(out) == 1: + out[0][indices] += proba + else: + for i in range(len(out)): + out[i][indices] += proba[i] diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index 1ed5b2377..6c339d124 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -138,17 +138,14 @@ def test_honest_decision_function(honest_fraction, val): [HonestForestClassifier(n_estimators=10, honest_fraction=0.5, random_state=0)] ) def test_sklearn_compatible_estimator(estimator, check): - # 1. multi-output is not supported + # 1. multi-output is not fully supported # 2. check_class_weight_classifiers is not supported since it requires sample weight # XXX: can include this "generalization" in the future if it's useful # zero sample weight is not "really supported" in honest subsample trees since sample weight # for fitting the tree's splits if check.func.__name__ in [ "check_class_weight_classifiers", - # "check_classifiers_multilabel_output_format_decision_function", - # "check_classifiers_multilabel_output_format_predict_proba", - # "check_classifiers_multilabel_output_format_predict", - # "check_classifiers_multilabel_representation_invariance", + "check_classifiers_multilabel_output_format_predict_proba", ]: pytest.skip() check(estimator) From f831bc426af7834292745f45171e698187038b5b Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Wed, 14 Jun 2023 16:12:08 -0400 Subject: [PATCH 03/18] DOC update changelog --- docs/whats_new/v0.1.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/whats_new/v0.1.rst b/docs/whats_new/v0.1.rst index 78b7bf5b2..7b250d974 100644 --- a/docs/whats_new/v0.1.rst +++ b/docs/whats_new/v0.1.rst @@ -36,6 +36,7 @@ Changelog - |Feature| A general-kernel MORF is now implemented where users can pass in a kernel library, by `Adam Li`_ (:pr:`70`) - |Feature| Implementation of ObliqueDecisionTreeRegressor, PatchObliqueDecisionTreeRegressor, ObliqueRandomForestRegressor, PatchObliqueRandomForestRegressor, by `SUKI-O`_ (:pr:`72`) - |Feature| Implementation of HonestTreeClassifier, HonestForestClassifier, by `Sambit Panda`_, `Adam Li`_, `Ronan Perry`_ and `Haoyin Xu`_ (:pr:`57`) +- |Feature| Add multi-output support to HonestTreeClassifier, HonestForestClassifier, by `Ronan Perry`_ and `Haoyin Xu`_ (:pr:`86`) Code and Documentation Contributors ----------------------------------- From f1ab592c9d01e0e8a6f5a514f69d5413754b98fc Mon Sep 17 00:00:00 2001 From: Adam Li Date: Thu, 15 Jun 2023 14:43:51 -0400 Subject: [PATCH 04/18] Fix multi-output Signed-off-by: Adam Li --- sktree/_lib/sklearn_fork | 2 +- sktree/ensemble/_honest_forest.py | 5 +++++ sktree/tests/test_honest_forest.py | 4 +--- sktree/tree/tests/test_honest_tree.py | 3 --- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sktree/_lib/sklearn_fork b/sktree/_lib/sklearn_fork index 45320b4d3..545e2a298 160000 --- a/sktree/_lib/sklearn_fork +++ b/sktree/_lib/sklearn_fork @@ -1 +1 @@ -Subproject commit 45320b4d3ef05b4ccbe81e8c13676b1c755d1973 +Subproject commit 545e2a298ab403262e00a16f4d85ccde1c2a250b diff --git a/sktree/ensemble/_honest_forest.py b/sktree/ensemble/_honest_forest.py index f843051a7..c38a09c65 100644 --- a/sktree/ensemble/_honest_forest.py +++ b/sktree/ensemble/_honest_forest.py @@ -451,6 +451,7 @@ def _predict_proba(self, X, indices=None, impute_missing=None): delayed(_accumulate_prediction)(tree, X, posteriors, lock, idx) for tree, idx in zip(self.estimators_, indices) ) + # Normalize to unit length, due to prior weighting posteriors = np.array(posteriors) zero_mask = posteriors.sum(2) == 0 @@ -461,6 +462,10 @@ def _predict_proba(self, X, indices=None, impute_missing=None): else: posteriors[zero_mask] = impute_missing + # preserve shape of multi-outputs + if self.n_outputs_ > 1: + posteriors = [post for post in posteriors] + if len(posteriors) == 1: return posteriors[0] else: diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index 6c339d124..d803c0b44 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -138,14 +138,12 @@ def test_honest_decision_function(honest_fraction, val): [HonestForestClassifier(n_estimators=10, honest_fraction=0.5, random_state=0)] ) def test_sklearn_compatible_estimator(estimator, check): - # 1. multi-output is not fully supported - # 2. check_class_weight_classifiers is not supported since it requires sample weight + # 1. check_class_weight_classifiers is not supported since it requires sample weight # XXX: can include this "generalization" in the future if it's useful # zero sample weight is not "really supported" in honest subsample trees since sample weight # for fitting the tree's splits if check.func.__name__ in [ "check_class_weight_classifiers", - "check_classifiers_multilabel_output_format_predict_proba", ]: pytest.skip() check(estimator) diff --git a/sktree/tree/tests/test_honest_tree.py b/sktree/tree/tests/test_honest_tree.py index f8068e758..ace165206 100644 --- a/sktree/tree/tests/test_honest_tree.py +++ b/sktree/tree/tests/test_honest_tree.py @@ -106,7 +106,4 @@ def test_impute_classes(): @parametrize_with_checks([HonestTreeClassifier(random_state=0)]) def test_sklearn_compatible_estimator(estimator, check): - # TODO: remove when we implement Regressor classes - # if TREE_ESTIMATORS[estimator].__name__ in TREE_CLASSIFIERS: - # pytest.skip() check(estimator) From dd0662df8dc2e512de1ad03c4c068d570756419e Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Thu, 15 Jun 2023 16:12:30 -0400 Subject: [PATCH 05/18] FIX simplify code & TST add multi-output test --- docs/whats_new/v0.1.rst | 2 +- sktree/ensemble/_honest_forest.py | 4 +--- sktree/tests/test_honest_forest.py | 33 +++++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/docs/whats_new/v0.1.rst b/docs/whats_new/v0.1.rst index 7b250d974..c0b275d55 100644 --- a/docs/whats_new/v0.1.rst +++ b/docs/whats_new/v0.1.rst @@ -36,7 +36,7 @@ Changelog - |Feature| A general-kernel MORF is now implemented where users can pass in a kernel library, by `Adam Li`_ (:pr:`70`) - |Feature| Implementation of ObliqueDecisionTreeRegressor, PatchObliqueDecisionTreeRegressor, ObliqueRandomForestRegressor, PatchObliqueRandomForestRegressor, by `SUKI-O`_ (:pr:`72`) - |Feature| Implementation of HonestTreeClassifier, HonestForestClassifier, by `Sambit Panda`_, `Adam Li`_, `Ronan Perry`_ and `Haoyin Xu`_ (:pr:`57`) -- |Feature| Add multi-output support to HonestTreeClassifier, HonestForestClassifier, by `Ronan Perry`_ and `Haoyin Xu`_ (:pr:`86`) +- |Feature| Add multi-output support to HonestTreeClassifier, HonestForestClassifier, by `Ronan Perry`_, `Haoyin Xu`_ and `Adam Li`_ (:pr:`86`) Code and Documentation Contributors ----------------------------------- diff --git a/sktree/ensemble/_honest_forest.py b/sktree/ensemble/_honest_forest.py index c38a09c65..8dbb571d7 100644 --- a/sktree/ensemble/_honest_forest.py +++ b/sktree/ensemble/_honest_forest.py @@ -401,8 +401,6 @@ def fit(self, X, y, sample_weight=None): """ super().fit(X, y, sample_weight) X, y = check_X_y(X, y, multi_output=True) - classes_k, y_encoded = np.unique(y, return_inverse=True) - self.empirical_prior_ = np.bincount(y_encoded, minlength=classes_k.shape[0]) / len(y) # Compute honest decision function self.honest_decision_function_ = self._predict_proba( @@ -458,7 +456,7 @@ def _predict_proba(self, X, indices=None, impute_missing=None): posteriors[~zero_mask] /= posteriors[~zero_mask].sum(1, keepdims=True) if impute_missing is None: - posteriors[zero_mask] = self.empirical_prior_ + pass else: posteriors[zero_mask] = impute_missing diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index d803c0b44..7ceb46c7e 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -1,7 +1,7 @@ import numpy as np import pytest from sklearn import datasets -from sklearn.metrics import accuracy_score +from sklearn.metrics import accuracy_score, mean_squared_error from sklearn.tree import DecisionTreeClassifier from sklearn.utils.estimator_checks import parametrize_with_checks @@ -59,6 +59,37 @@ def test_iris(criterion, max_features, estimator): ) +@pytest.mark.parametrize("criterion", ["gini", "entropy"]) +@pytest.mark.parametrize("max_features", [None, 2]) +@pytest.mark.parametrize( + "estimator", + [ + DecisionTreeClassifier(), + ObliqueDecisionTreeClassifier(), + PatchObliqueDecisionTreeClassifier(), + ], +) +def test_iris_multi(criterion, max_features, estimator): + # Check consistency on dataset iris. + clf = HonestForestClassifier( + criterion=criterion, + random_state=0, + max_features=max_features, + n_estimators=10, + tree_estimator=estimator, + ) + + second_y = np.concatenate([(np.ones(10) * 3), (np.ones(20) * 4), (np.ones(120) * 5)]) + + X = iris.data + y = np.stack((iris.target, second_y)).T + clf.fit(X, y) + score = mean_squared_error(clf.predict(X), y) + assert score < 0.5 and score < 1.0, "Failed with {0}, criterion = {1} and score = {2}".format( + "HForest", criterion, score + ) + + def test_impute_classes(): np.random.seed(0) X = np.random.normal(0, 1, (101, 2)) From b259441df21ef8743b65e2f51673864f173caecd Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Fri, 16 Jun 2023 11:22:43 -0400 Subject: [PATCH 06/18] TST update test format & increase code coverage --- sktree/tests/test_honest_forest.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index 7ceb46c7e..283e9c9a6 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -1,7 +1,7 @@ import numpy as np import pytest from sklearn import datasets -from sklearn.metrics import accuracy_score, mean_squared_error +from sklearn.metrics import accuracy_score, r2_score from sklearn.tree import DecisionTreeClassifier from sklearn.utils.estimator_checks import parametrize_with_checks @@ -30,6 +30,7 @@ def test_toy_accuracy(): @pytest.mark.parametrize("criterion", ["gini", "entropy"]) @pytest.mark.parametrize("max_features", [None, 2]) +@pytest.mark.parametrize("honest_prior", ["empirical", "uniform", "ignore"]) @pytest.mark.parametrize( "estimator", [ @@ -38,13 +39,14 @@ def test_toy_accuracy(): PatchObliqueDecisionTreeClassifier(), ], ) -def test_iris(criterion, max_features, estimator): +def test_iris(criterion, max_features, honest_prior, estimator): # Check consistency on dataset iris. clf = HonestForestClassifier( criterion=criterion, random_state=0, max_features=max_features, n_estimators=10, + honest_prior=honest_prior, tree_estimator=estimator, ) clf.fit(iris.data, iris.target) @@ -61,6 +63,7 @@ def test_iris(criterion, max_features, estimator): @pytest.mark.parametrize("criterion", ["gini", "entropy"]) @pytest.mark.parametrize("max_features", [None, 2]) +@pytest.mark.parametrize("honest_prior", ["empirical", "uniform", "ignore"]) @pytest.mark.parametrize( "estimator", [ @@ -69,13 +72,14 @@ def test_iris(criterion, max_features, estimator): PatchObliqueDecisionTreeClassifier(), ], ) -def test_iris_multi(criterion, max_features, estimator): +def test_iris_multi(criterion, max_features, honest_prior, estimator): # Check consistency on dataset iris. clf = HonestForestClassifier( criterion=criterion, random_state=0, max_features=max_features, n_estimators=10, + honest_prior=honest_prior, tree_estimator=estimator, ) @@ -84,10 +88,15 @@ def test_iris_multi(criterion, max_features, estimator): X = iris.data y = np.stack((iris.target, second_y)).T clf.fit(X, y) - score = mean_squared_error(clf.predict(X), y) - assert score < 0.5 and score < 1.0, "Failed with {0}, criterion = {1} and score = {2}".format( - "HForest", criterion, score - ) + score = r2_score(clf.predict(X), y) + if honest_prior == "ignore": + assert score < 1.0, "Failed with {0}, criterion = {1} and score = {2}".format( + "HForest", criterion, score + ) + else: + assert ( + score > 0.0 and score < 1.0 + ), "Failed with {0}, criterion = {1} and score = {2}".format("HForest", criterion, score) def test_impute_classes(): From 16f8561fa9dae044ae7497cee9054088d20c750f Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Fri, 16 Jun 2023 13:20:22 -0400 Subject: [PATCH 07/18] FIX optimize leaf updates with multi-output --- sktree/tests/test_honest_forest.py | 12 ++++++------ sktree/tree/_honest_tree.py | 22 ++++++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index 283e9c9a6..31c07d441 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -83,19 +83,19 @@ def test_iris_multi(criterion, max_features, honest_prior, estimator): tree_estimator=estimator, ) - second_y = np.concatenate([(np.ones(10) * 3), (np.ones(20) * 4), (np.ones(120) * 5)]) + second_y = np.concatenate([(np.ones(50) * 3), (np.ones(50) * 4), (np.ones(50) * 5)]) X = iris.data - y = np.stack((iris.target, second_y)).T + y = np.stack((iris.target, second_y[perm])).T clf.fit(X, y) score = r2_score(clf.predict(X), y) if honest_prior == "ignore": - assert score < 1.0, "Failed with {0}, criterion = {1} and score = {2}".format( - "HForest", criterion, score - ) + assert ( + score > 0.6 and score < 1.0 + ), "Failed with {0}, criterion = {1} and score = {2}".format("HForest", criterion, score) else: assert ( - score > 0.0 and score < 1.0 + score > 0.9 and score < 1.0 ), "Failed with {0}, criterion = {1} and score = {2}".format("HForest", criterion, score) diff --git a/sktree/tree/_honest_tree.py b/sktree/tree/_honest_tree.py index 367d3404c..78b4bd7b0 100644 --- a/sktree/tree/_honest_tree.py +++ b/sktree/tree/_honest_tree.py @@ -405,8 +405,8 @@ def fit(self, X, y, sample_weight=None, check_input=True): def _set_leaf_nodes(self, X, y): "Traverse the already built tree with X and set leaf nodes with y" self.tree_.value[:, :, :] = 0 - for leaf_id, yval in zip(X, y[self.honest_indices_, 0]): - self.tree_.value[leaf_id][0, yval] += 1 + for leaf_id, yval in zip(X, y[self.honest_indices_, :]): + self.tree_.value[leaf_id][:, yval] += 1 def _inherit_estimator_attributes(self): """Initialize necessary attributes from the provided tree estimator""" @@ -442,12 +442,18 @@ def _empty_leaf_correction(self, proba, pos=0): raise ValueError(f"honest_prior {self.honest_prior} not a valid input.") return proba - def _impute_missing_classes(self, proba): + def _impute_missing_classes(self, proba, pos=0): """Due to splitting, provide proba outputs for some classes""" - new_proba = np.zeros((proba.shape[0], self.n_classes_)) - for i, old_class in enumerate(self._tree_classes_): - j = np.where(self.classes_ == old_class)[0][0] - new_proba[:, j] = proba[:, i] + if self.n_outputs_ > 1: + new_proba = np.zeros((proba.shape[0], self.n_classes_[pos])) + for i, old_class in enumerate(self._tree_classes_[pos]): + j = np.where(self.classes_[pos] == old_class)[0][0] + new_proba[:, j] = proba[:, i] + else: + new_proba = np.zeros((proba.shape[0], self.n_classes_)) + for i, old_class in enumerate(self._tree_classes_): + j = np.where(self.classes_ == old_class)[0][0] + new_proba[:, j] = proba[:, i] return new_proba @@ -499,7 +505,7 @@ class in a leaf. normalizer[normalizer == 0.0] = 1.0 proba_k /= normalizer if self._tree_n_classes_[k] != self.n_classes_[k]: - proba_k = self._impute_missing_classes(proba_k) + proba_k = self._impute_missing_classes(proba_k, k) proba_k = self._empty_leaf_correction(proba_k, k) all_proba.append(proba_k) From 2e003588b7ca961687288f2cb2af2892a37f1962 Mon Sep 17 00:00:00 2001 From: Adam Li Date: Fri, 16 Jun 2023 17:39:52 -0400 Subject: [PATCH 08/18] Update submodule commit ID --- examples/overlapping_gaussians.png | Bin 0 -> 110138 bytes sktree/_lib/sklearn_fork | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 examples/overlapping_gaussians.png diff --git a/examples/overlapping_gaussians.png b/examples/overlapping_gaussians.png new file mode 100644 index 0000000000000000000000000000000000000000..0a21571362236b6700c12d8401129aa4cd67242c GIT binary patch literal 110138 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 bfG=GWm*Ai={w;d}KJ;}A4`l5B<;s5n#|}WI literal 0 HcmV?d00001 diff --git a/sktree/_lib/sklearn_fork b/sktree/_lib/sklearn_fork index 545e2a298..3f5cb6597 160000 --- a/sktree/_lib/sklearn_fork +++ b/sktree/_lib/sklearn_fork @@ -1 +1 @@ -Subproject commit 545e2a298ab403262e00a16f4d85ccde1c2a250b +Subproject commit 3f5cb6597e36a08f651f8f0eb7324e9658a14bea From fd6643a62c37a16313f88142a151ee7277f1e411 Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Mon, 19 Jun 2023 09:32:39 -0400 Subject: [PATCH 09/18] ENH remove impute_missing_classes function --- sktree/tests/test_honest_forest.py | 1 + sktree/tree/_honest_tree.py | 19 ------------------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index 31c07d441..a837ec2f1 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -100,6 +100,7 @@ def test_iris_multi(criterion, max_features, honest_prior, estimator): def test_impute_classes(): + # This test is unnecessary as sample_weight method doesn't impute np.random.seed(0) X = np.random.normal(0, 1, (101, 2)) y = [0] * 50 + [1] * 50 + [2] diff --git a/sktree/tree/_honest_tree.py b/sktree/tree/_honest_tree.py index 78b4bd7b0..7f792d2e3 100644 --- a/sktree/tree/_honest_tree.py +++ b/sktree/tree/_honest_tree.py @@ -442,21 +442,6 @@ def _empty_leaf_correction(self, proba, pos=0): raise ValueError(f"honest_prior {self.honest_prior} not a valid input.") return proba - def _impute_missing_classes(self, proba, pos=0): - """Due to splitting, provide proba outputs for some classes""" - if self.n_outputs_ > 1: - new_proba = np.zeros((proba.shape[0], self.n_classes_[pos])) - for i, old_class in enumerate(self._tree_classes_[pos]): - j = np.where(self.classes_[pos] == old_class)[0][0] - new_proba[:, j] = proba[:, i] - else: - new_proba = np.zeros((proba.shape[0], self.n_classes_)) - for i, old_class in enumerate(self._tree_classes_): - j = np.where(self.classes_ == old_class)[0][0] - new_proba[:, j] = proba[:, i] - - return new_proba - def predict_proba(self, X, check_input=True): """Predict class probabilities of the input samples X. @@ -490,8 +475,6 @@ class in a leaf. normalizer = proba.sum(axis=1)[:, np.newaxis] normalizer[normalizer == 0.0] = 1.0 proba /= normalizer - if self._tree_n_classes_ != self.n_classes_: - proba = self._impute_missing_classes(proba) proba = self._empty_leaf_correction(proba) return proba @@ -504,8 +487,6 @@ class in a leaf. normalizer = proba_k.sum(axis=1)[:, np.newaxis] normalizer[normalizer == 0.0] = 1.0 proba_k /= normalizer - if self._tree_n_classes_[k] != self.n_classes_[k]: - proba_k = self._impute_missing_classes(proba_k, k) proba_k = self._empty_leaf_correction(proba_k, k) all_proba.append(proba_k) From c182cad4b4fce2f51b837f29af770d516d74885e Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Mon, 19 Jun 2023 10:24:00 -0400 Subject: [PATCH 10/18] TST optimize prior test --- sktree/tests/test_honest_forest.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index a837ec2f1..9ab1e0b88 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -30,7 +30,7 @@ def test_toy_accuracy(): @pytest.mark.parametrize("criterion", ["gini", "entropy"]) @pytest.mark.parametrize("max_features", [None, 2]) -@pytest.mark.parametrize("honest_prior", ["empirical", "uniform", "ignore"]) +@pytest.mark.parametrize("honest_prior", ["empirical", "uniform", "ignore", "error"]) @pytest.mark.parametrize( "estimator", [ @@ -49,8 +49,11 @@ def test_iris(criterion, max_features, honest_prior, estimator): honest_prior=honest_prior, tree_estimator=estimator, ) - clf.fit(iris.data, iris.target) - score = accuracy_score(clf.predict(iris.data), iris.target) + try: + clf.fit(iris.data, iris.target) + score = accuracy_score(clf.predict(iris.data), iris.target) + except ValueError: + return assert score > 0.5 and score < 1.0, "Failed with {0}, criterion = {1} and score = {2}".format( "HForest", criterion, score ) From 72306d0adecf7bcfefae41482d9c35ce15ba018b Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Mon, 19 Jun 2023 10:37:25 -0400 Subject: [PATCH 11/18] TST add prior for multi-output --- sktree/tests/test_honest_forest.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index 9ab1e0b88..deafbd0cc 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -66,7 +66,7 @@ def test_iris(criterion, max_features, honest_prior, estimator): @pytest.mark.parametrize("criterion", ["gini", "entropy"]) @pytest.mark.parametrize("max_features", [None, 2]) -@pytest.mark.parametrize("honest_prior", ["empirical", "uniform", "ignore"]) +@pytest.mark.parametrize("honest_prior", ["empirical", "uniform", "ignore", "error"]) @pytest.mark.parametrize( "estimator", [ @@ -90,8 +90,11 @@ def test_iris_multi(criterion, max_features, honest_prior, estimator): X = iris.data y = np.stack((iris.target, second_y[perm])).T - clf.fit(X, y) - score = r2_score(clf.predict(X), y) + try: + clf.fit(X, y) + score = r2_score(clf.predict(X), y) + except ValueError: + return if honest_prior == "ignore": assert ( score > 0.6 and score < 1.0 From d4d23374aa6560f6c3d07b6a408f956d54302c89 Mon Sep 17 00:00:00 2001 From: Adam Li Date: Tue, 20 Jun 2023 13:59:25 -0400 Subject: [PATCH 12/18] Merging main Signed-off-by: Adam Li --- sktree/_lib/sklearn_fork | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sktree/_lib/sklearn_fork b/sktree/_lib/sklearn_fork index 3f5cb6597..1c1ec8cff 160000 --- a/sktree/_lib/sklearn_fork +++ b/sktree/_lib/sklearn_fork @@ -1 +1 @@ -Subproject commit 3f5cb6597e36a08f651f8f0eb7324e9658a14bea +Subproject commit 1c1ec8cff3a181b7a86a4df8a2aeb01fa7cdbe6a From c14f62980ff786e0b19f1c32c5eb425bdf89a882 Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Tue, 20 Jun 2023 14:15:01 -0400 Subject: [PATCH 13/18] FIX re-update leaf function for multi --- sktree/tree/_honest_tree.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sktree/tree/_honest_tree.py b/sktree/tree/_honest_tree.py index 58f9bc8b6..0f1e41c0e 100644 --- a/sktree/tree/_honest_tree.py +++ b/sktree/tree/_honest_tree.py @@ -413,8 +413,8 @@ def _set_leaf_nodes(self, leaf_ids, y): classes are ordered by their index in the tree_.value array. """ self.tree_.value[:, :, :] = 0 - for leaf_id, yval in zip(leaf_ids, y[self.honest_indices_, 0]): - self.tree_.value[leaf_id][0, yval] += 1 + for leaf_id, yval in zip(leaf_ids, y[self.honest_indices_, :]): + self.tree_.value[leaf_id][:, yval] += 1 def _inherit_estimator_attributes(self): """Initialize necessary attributes from the provided tree estimator""" From 2feb11790f3ceb188d69005852c808aa70dfa322 Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Tue, 20 Jun 2023 15:08:03 -0400 Subject: [PATCH 14/18] DOC optimize docstring & TST remove impute test --- sktree/tests/test_honest_forest.py | 13 ------------- sktree/tree/_honest_tree.py | 7 ++++++- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index deafbd0cc..6e64018a3 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -105,19 +105,6 @@ def test_iris_multi(criterion, max_features, honest_prior, estimator): ), "Failed with {0}, criterion = {1} and score = {2}".format("HForest", criterion, score) -def test_impute_classes(): - # This test is unnecessary as sample_weight method doesn't impute - np.random.seed(0) - X = np.random.normal(0, 1, (101, 2)) - y = [0] * 50 + [1] * 50 + [2] - clf = HonestForestClassifier(honest_fraction=0.02, random_state=0) - clf = clf.fit(X, y) - - y_proba = clf.predict_proba(X) - - assert y_proba.shape[1] == 3 - - def test_max_samples(): max_samples_list = [8, 0.5, None] depths = [] diff --git a/sktree/tree/_honest_tree.py b/sktree/tree/_honest_tree.py index 0f1e41c0e..99e3aba41 100644 --- a/sktree/tree/_honest_tree.py +++ b/sktree/tree/_honest_tree.py @@ -426,7 +426,12 @@ def _inherit_estimator_attributes(self): self.tree_ = self.estimator_.tree_ def _empty_leaf_correction(self, proba, pos=0): - """Leaves with empty posteriors are assigned values""" + """Leaves with empty posteriors are assigned values. + + The posteriors are corrected according to the honest prior. + In multi-output cases, the posterior corrections only correspond + to the respective y dimention, indicated by the position param pos. + """ zero_mask = proba.sum(axis=1) == 0.0 # For multi-output cases From f172880d70ecec27eb4c4fa76043e3e1550b0482 Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Tue, 20 Jun 2023 15:12:54 -0400 Subject: [PATCH 15/18] DOC correct typo Co-authored-by: Adam Li --- sktree/tree/_honest_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sktree/tree/_honest_tree.py b/sktree/tree/_honest_tree.py index 99e3aba41..343830429 100644 --- a/sktree/tree/_honest_tree.py +++ b/sktree/tree/_honest_tree.py @@ -430,7 +430,7 @@ def _empty_leaf_correction(self, proba, pos=0): The posteriors are corrected according to the honest prior. In multi-output cases, the posterior corrections only correspond - to the respective y dimention, indicated by the position param pos. + to the respective y dimension, indicated by the position param pos. """ zero_mask = proba.sum(axis=1) == 0.0 From a31e1de3e183e7546bd7c6042cb7c2b0b5c677cc Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Wed, 21 Jun 2023 10:24:21 -0400 Subject: [PATCH 16/18] TST add random state --- sktree/tests/test_honest_forest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index 6e64018a3..bcf0f7440 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -112,7 +112,7 @@ def test_max_samples(): X[:50] *= -1 y = [0, 1] * 50 for ms in max_samples_list: - uf = HonestForestClassifier(n_estimators=2, max_samples=ms, bootstrap=True) + uf = HonestForestClassifier(n_estimators=2, random_state=0, max_samples=ms, bootstrap=True) uf = uf.fit(X, y) depths.append(uf.estimators_[0].get_depth()) From 0fc8ec4f6a5ead85a839ab7a2974e59474245006 Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Thu, 22 Jun 2023 09:50:24 -0400 Subject: [PATCH 17/18] TXT optimize max sample test --- sktree/tests/test_honest_forest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index bcf0f7440..c4f401d5a 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -108,6 +108,7 @@ def test_iris_multi(criterion, max_features, honest_prior, estimator): def test_max_samples(): max_samples_list = [8, 0.5, None] depths = [] + np.random.seed(0) X = np.random.normal(0, 1, (100, 2)) X[:50] *= -1 y = [0, 1] * 50 From 0f773e14b27050210344dbb9c7938670e722abf8 Mon Sep 17 00:00:00 2001 From: Haoyin Xu Date: Thu, 22 Jun 2023 10:03:08 -0400 Subject: [PATCH 18/18] TST optimize random seed Co-Authored-By: Adam Li <3460267+adam2392@users.noreply.github.com> --- sktree/tests/test_honest_forest.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sktree/tests/test_honest_forest.py b/sktree/tests/test_honest_forest.py index c4f401d5a..a9846642a 100644 --- a/sktree/tests/test_honest_forest.py +++ b/sktree/tests/test_honest_forest.py @@ -108,8 +108,7 @@ def test_iris_multi(criterion, max_features, honest_prior, estimator): def test_max_samples(): max_samples_list = [8, 0.5, None] depths = [] - np.random.seed(0) - X = np.random.normal(0, 1, (100, 2)) + X = rng.normal(0, 1, (100, 2)) X[:50] *= -1 y = [0, 1] * 50 for ms in max_samples_list: @@ -129,8 +128,7 @@ def test_max_samples(): ], ) def test_impute_posteriors(honest_prior, val): - np.random.seed(0) - X = np.random.normal(0, 1, (100, 2)) + X = rng.normal(0, 1, (100, 2)) y = [0] * 75 + [1] * 25 clf = HonestForestClassifier( honest_fraction=0.02, random_state=0, honest_prior=honest_prior, n_estimators=2 @@ -156,8 +154,7 @@ def test_impute_posteriors(honest_prior, val): ], ) def test_honest_decision_function(honest_fraction, val): - np.random.seed(0) - X = np.random.normal(0, 1, (100, 2)) + X = rng.normal(0, 1, (100, 2)) y = [0] * 75 + [1] * 25 clf = HonestForestClassifier(honest_fraction=honest_fraction, random_state=0, n_estimators=2) clf = clf.fit(X, y)