From 1d5cbb0c5f8c1b002bc4b433af92fe0339efcf57 Mon Sep 17 00:00:00 2001 From: "javier.vera" Date: Tue, 16 May 2023 11:14:01 +0000 Subject: [PATCH 1/5] Implmented the new method codisp_with_cut_dimension in class RCTree, added an example of how to use it to the README.md file. --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++ rrcf/rrcf.py | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/README.md b/README.md index edbb01c..ce21125 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,62 @@ for index, point in enumerate(points): ![Image](https://github.com/kLabUM/rrcf/blob/master/resources/sine.png) +## Obtain feature importance + +This example shows how to estimate the feature importance using the dimension of cut obtained during the calculation of the CoDisp. + + +```python +import numpy as np +import pandas as pd +import rrcf + +# Set parameters +np.random.seed(0) +n = 2010 +d = 3 +num_trees = 100 +tree_size = 256 + +# Generate data +X = np.zeros((n, d)) +X[:1000,0] = 5 +X[1000:2000,0] = -5 +X += 0.01*np.random.randn(*X.shape) + +# Construct forest +forest = [] +while len(forest) < num_trees: + # Select random subsets of points uniformly from point set + ixs = np.random.choice(n, size=(n // tree_size, tree_size), + replace=False) + # Add sampled trees to forest + trees = [rrcf.RCTree(X[ix], index_labels=ix) for ix in ixs] + forest.extend(trees) + + +# Compute average CoDisp with the cut dimension for each point +dim_codisp = np.zeros([n,d],dtype=float) +index = np.zeros(n) +for tree in forest: + for leaf in tree.leaves: + codisp,cutdim = tree.codisp_with_cut_dimension(leaf) + + dim_codisp[leaf,cutdim] += codisp + + index[leaf] += 1 + +avg_codisp = dim_codisp.sum(axis=1)/index + +#codisp anomaly threshold and calculate the mean over each feature +feature_importance_anomaly = np.mean(dim_codisp[avg_codisp>50,:],axis=0) +#create a dataframe with the feature importance +df_feature_importance = pd.DataFrame(feature_importance_anomaly,columns=['feature_importance']) +df_feature_importance +``` + + + ## Contributing We welcome contributions to the `rrcf` repo. To contribute, submit a [pull request](https://help.github.com/en/articles/about-pull-requests) to the `dev` branch. diff --git a/rrcf/rrcf.py b/rrcf/rrcf.py index 8484af1..aa419d8 100644 --- a/rrcf/rrcf.py +++ b/rrcf/rrcf.py @@ -633,6 +633,67 @@ def codisp(self, leaf): co_displacement = max(results) return co_displacement + + def codisp_with_cut_dimension(self, leaf): + """ + Compute collusive displacement at leaf and the dimension of the cut. + This method can be used to find the most importance fetures that determined the CoDisp. + + Parameters: + ----------- + leaf: index of leaf or Leaf instance + + Returns: + -------- + codisplacement: float + Collusive displacement if leaf is removed. + cut_dimension: int + Dimension of the cut + + Example: + -------- + # Create RCTree + >>> X = np.random.randn(100, 2) + >>> tree = rrcf.RCTree(X) + >>> new_point = np.array([4, 4]) + >>> tree.insert_point(new_point, index=100) + + # Compute collusive displacement with dimension + >>> tree.codisp_with_dim(100) + + (31.667, 1) + """ + if not isinstance(leaf, Leaf): + try: + leaf = self.leaves[leaf] + except KeyError: + raise KeyError( + 'leaf must be a Leaf instance or key to self.leaves') + # Handle case where leaf is root + if leaf is self.root: + return 0 + node = leaf + results = [] + cut_dimensions = [] + + for _ in range(node.d): + parent = node.u + if parent is None: + break + if node is parent.l: + sibling = parent.r + else: + sibling = parent.l + num_deleted = node.n + displacement = sibling.n + result = (displacement / num_deleted) + results.append(result) + cut_dimensions.append(parent.q) + node = parent + argmax = np.argmax(results) + + return results[argmax], cut_dimensions[argmax] + def get_bbox(self, branch=None): """ Compute bounding box of all points underneath a given branch. From 8c5a6e053543a7bed48030a89c71f3cc95db9e1c Mon Sep 17 00:00:00 2001 From: "javier.vera" Date: Tue, 16 May 2023 11:18:13 +0000 Subject: [PATCH 2/5] Corrected docstring in codisp_with_cut_dimension --- rrcf/rrcf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rrcf/rrcf.py b/rrcf/rrcf.py index aa419d8..afdbc60 100644 --- a/rrcf/rrcf.py +++ b/rrcf/rrcf.py @@ -659,7 +659,7 @@ def codisp_with_cut_dimension(self, leaf): >>> tree.insert_point(new_point, index=100) # Compute collusive displacement with dimension - >>> tree.codisp_with_dim(100) + >>> tree.codisp_with_cut_dimension(100) (31.667, 1) """ From 2463c216a91afa6afae46ff39eab2d52ad8a40f9 Mon Sep 17 00:00:00 2001 From: "javier.vera" Date: Tue, 16 May 2023 13:31:12 +0000 Subject: [PATCH 3/5] Added an unittest for codisp_with_cut_dimension --- test/test_rrcf.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/test_rrcf.py b/test/test_rrcf.py index ea57c39..7979690 100644 --- a/test/test_rrcf.py +++ b/test/test_rrcf.py @@ -36,6 +36,13 @@ def test_codisp(): codisp = tree.codisp(i) assert codisp > 0 +def test_codisp_with_cut_dimension(): + for i in range(100): + codisp,cut_dim = tree.codisp_with_cut_dimension(i) + assert codisp > 0 + assert cut_dim >= 0 and cut_dim < d + + def test_disp(): for i in range(100): disp = tree.disp(i) From 725f35b356d5bc04194a7b245fb8a144e004bcd5 Mon Sep 17 00:00:00 2001 From: "javier.vera" Date: Wed, 17 May 2023 06:28:49 +0000 Subject: [PATCH 4/5] Added example to index.md and an image to resources --- README.md | 1 + docs/index.md | 58 +++++++++++++++++++++++++++++++ resources/feature_importance.png | Bin 0 -> 16293 bytes 3 files changed, 59 insertions(+) create mode 100644 resources/feature_importance.png diff --git a/README.md b/README.md index ce21125..1de4332 100644 --- a/README.md +++ b/README.md @@ -285,6 +285,7 @@ feature_importance_anomaly = np.mean(dim_codisp[avg_codisp>50,:],axis=0) df_feature_importance = pd.DataFrame(feature_importance_anomaly,columns=['feature_importance']) df_feature_importance ``` +![Image](https://raw.githubusercontent.com/kLabUM/rrcf/master/feature_importance.png) diff --git a/docs/index.md b/docs/index.md index 192343c..399241b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -244,6 +244,64 @@ for index, point in enumerate(points): ![Image](https://raw.githubusercontent.com/kLabUM/rrcf/master/resources/sine.png) + +## Obtain feature importance + +This example shows how to estimate the feature importance using the dimension of cut obtained during the calculation of the CoDisp. + + +```python +import numpy as np +import pandas as pd +import rrcf + +# Set parameters +np.random.seed(0) +n = 2010 +d = 3 +num_trees = 100 +tree_size = 256 + +# Generate data +X = np.zeros((n, d)) +X[:1000,0] = 5 +X[1000:2000,0] = -5 +X += 0.01*np.random.randn(*X.shape) + +# Construct forest +forest = [] +while len(forest) < num_trees: + # Select random subsets of points uniformly from point set + ixs = np.random.choice(n, size=(n // tree_size, tree_size), + replace=False) + # Add sampled trees to forest + trees = [rrcf.RCTree(X[ix], index_labels=ix) for ix in ixs] + forest.extend(trees) + + +# Compute average CoDisp with the cut dimension for each point +dim_codisp = np.zeros([n,d],dtype=float) +index = np.zeros(n) +for tree in forest: + for leaf in tree.leaves: + codisp,cutdim = tree.codisp_with_cut_dimension(leaf) + + dim_codisp[leaf,cutdim] += codisp + + index[leaf] += 1 + +avg_codisp = dim_codisp.sum(axis=1)/index + +#codisp anomaly threshold and calculate the mean over each feature +feature_importance_anomaly = np.mean(dim_codisp[avg_codisp>50,:],axis=0) +#create a dataframe with the feature importance +df_feature_importance = pd.DataFrame(feature_importance_anomaly,columns=['feature_importance']) +df_feature_importance +``` + +![Image](https://raw.githubusercontent.com/kLabUM/rrcf/master/feature_importance.png) + + ## Contributing We welcome contributions to the `rrcf` repo. To contribute, submit a [pull request](https://help.github.com/en/articles/about-pull-requests) to the `dev` branch. diff --git a/resources/feature_importance.png b/resources/feature_importance.png new file mode 100644 index 0000000000000000000000000000000000000000..e223a1aaaf21c35607ce502bbf1a9435879d9572 GIT binary patch literal 16293 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%0A^x4W=x%`LnbyW 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 U11Y0&`fdK1)u% Date: Thu, 18 May 2023 13:41:44 +0000 Subject: [PATCH 5/5] missed a tab in argmax --- rrcf/rrcf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rrcf/rrcf.py b/rrcf/rrcf.py index afdbc60..40b525b 100644 --- a/rrcf/rrcf.py +++ b/rrcf/rrcf.py @@ -690,7 +690,7 @@ def codisp_with_cut_dimension(self, leaf): results.append(result) cut_dimensions.append(parent.q) node = parent - argmax = np.argmax(results) + argmax = np.argmax(results) return results[argmax], cut_dimensions[argmax]