From 3ca02c9af996683986a3fd659618b8e7381abe0c Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Wed, 7 Apr 2021 03:08:39 -0400 Subject: [PATCH 01/11] Implement count-based feature importance and tests --- MANIFEST | 16 --------- oblique_forests/sporf.py | 35 ++++++++++++++++++- oblique_forests/tree/oblique_tree.py | 43 ++++++++++++++++++++++++ oblique_forests/tree/tests/test_sporf.py | 11 ++++++ 4 files changed, 88 insertions(+), 17 deletions(-) delete mode 100644 MANIFEST diff --git a/MANIFEST b/MANIFEST deleted file mode 100644 index 7f811a8..0000000 --- a/MANIFEST +++ /dev/null @@ -1,16 +0,0 @@ -# file GENERATED by distutils, do NOT edit -Pipfile -Pipfile.lock -requirements.txt -setup.cfg -setup.py -oblique_forests/__init__.py -oblique_forests/morf.py -oblique_forests/setup.py -oblique_forests/sporf.py -oblique_forests/tree/__init__.py -oblique_forests/tree/_split.cpp -oblique_forests/tree/morf_split.py -oblique_forests/tree/morf_tree.py -oblique_forests/tree/oblique_tree.py -oblique_forests/tree/setup.py diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index 485e469..ff3159a 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -1,4 +1,8 @@ +import numpy as np +from joblib import Parallel, delayed from sklearn.ensemble._forest import ForestClassifier +from sklearn.utils.validation import check_is_fitted +from sklearn.utils.fixes import _joblib_parallel_args from .tree.oblique_tree import ObliqueTreeClassifier @@ -59,4 +63,33 @@ def __init__( # self.min_impurity_decrease = min_impurity_decrease # self.min_impurity_split = min_impurity_split - + @property + def feature_importances_(self): + """ + Computes the importance of every unique feature used to make a split + in the Oblique Tree. + + Parameters + ---------- + normalize : bool, default=True + A boolean to indicate whether to normalize feature importances. + + Returns + ------- + importances : array of shape [n_features] + Array of count-based feature importances. + """ + check_is_fitted(self) + + all_importances = Parallel(n_jobs=self.n_jobs, + **_joblib_parallel_args(prefer='threads'))( + delayed(getattr)(tree, 'feature_importances_') + for tree in self.estimators_ if tree.tree.node_count > 1) + + if not all_importances: + return np.zeros(self.n_features_, dtype=np.float64) + + all_importances = np.mean(all_importances, + axis=0, dtype=np.float64) + return all_importances / np.sum(all_importances) + diff --git a/oblique_forests/tree/oblique_tree.py b/oblique_forests/tree/oblique_tree.py index 1d5b8aa..b1ad7b8 100644 --- a/oblique_forests/tree/oblique_tree.py +++ b/oblique_forests/tree/oblique_tree.py @@ -3,6 +3,7 @@ from joblib import Parallel, delayed from sklearn.base import BaseEstimator from sklearn.utils.validation import check_array, check_is_fitted, check_X_y +from sklearn.utils.fixes import _joblib_parallel_args from ._split import BaseObliqueSplitter @@ -628,6 +629,31 @@ def predict(self, X, check_input=True): return predictions + def compute_feature_importances(self, normalize=True): + """ + Computes the importance of each feature (aka variable). + + Returns + ------- + feature_importances_ : ndarray of shape (n_features,) + Normalized importance (counts) of each feature. + """ + # XXX: Still raises error even when OTC instance is fitted + # check_is_fitted(self) + importances = np.zeros((self.splitter.n_features,)) + + # Count number of times a feature is used in a projection across all nodes + for node in self.nodes: + importances[np.nonzero(node.proj_vec)] += 1 + + if normalize: + normalizer = np.sum(importances) + if normalizer > 0.0: + # Avoid dividing by zero (e.g., when root is pure) + importances /= normalizer + + return importances + # -------------------------------------------------------------------------- @@ -829,3 +855,20 @@ def predict_log_proba(self, X, check_input=True): # TODO: Actually do this function def _validate_X_predict(self, X, check_input=True): return X + + @property + def feature_importances_(self): + """ + Return the feature importances. + The importance of a feature is computed as the number of times it + is used in a projection across all split nodes + + Returns + ------- + feature_importances_ : ndarray of shape (n_features,) + Array of count-based feature importances. + """ + # XXX: Still raises error even when OTC instance is fitted + # check_is_fitted(self) + + return self.tree.compute_feature_importances() diff --git a/oblique_forests/tree/tests/test_sporf.py b/oblique_forests/tree/tests/test_sporf.py index 7295088..2698c8f 100644 --- a/oblique_forests/tree/tests/test_sporf.py +++ b/oblique_forests/tree/tests/test_sporf.py @@ -9,6 +9,7 @@ import pytest from oblique_forests.tree.oblique_tree import ObliqueTreeClassifier as OTC +from oblique_forests.sporf import ObliqueForestClassifier as OFC from sklearn import datasets from sklearn.metrics import accuracy_score @@ -148,5 +149,15 @@ def test_pure_set(): clf.fit(X, y) assert_array_equal(clf.predict(X), y) +def test_tree_feature_importances(): + + clf = OFC(random_state=0) + + clf.fit(diabetes.data, diabetes.target) + importances = clf.feature_importances_ +def test_forest_feature_importances(): + clf = OFC(random_state=0) + clf.fit(diabetes.data, diabetes.target) + importances = clf.feature_importances_ \ No newline at end of file From 84dacb90082d324ef074beb1b3ad3370f442a1e1 Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Fri, 9 Apr 2021 03:03:17 -0400 Subject: [PATCH 02/11] Add importances notebook on MNIST data --- docs/tutorials/test_feature_importance.ipynb | 5928 ++++++++++++++++++ oblique_forests/morf.py | 34 + oblique_forests/sporf.py | 2 +- oblique_forests/tree/oblique_tree.py | 3 +- 4 files changed, 5965 insertions(+), 2 deletions(-) create mode 100644 docs/tutorials/test_feature_importance.ipynb diff --git a/docs/tutorials/test_feature_importance.ipynb b/docs/tutorials/test_feature_importance.ipynb new file mode 100644 index 0000000..9def664 --- /dev/null +++ b/docs/tutorials/test_feature_importance.ipynb @@ -0,0 +1,5928 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Feature Importance\n", + "One of the benefits to decision trees is that their results are fairly interpretable in that they allow for estimation of the relative importance of each feature.\n", + "\n", + "There are many approaches that have been suggested for quantifying importances. The `scikit-learn` implementation of the random forest quantifies these importances using the Gini impurity. For `SPORF` and `MORF`, we use a projection forest specific metric to quantify feature importance by computing the normalized count of the number of times a feature $k$ was used in projections across the ensemble of decision trees.\n", + "\n", + "Specifically, if we denote $\\mathcal{T}$ as the set of decision trees in our forest where each decision tree $T \\in \\mathcal{T}$ is composed of many nodes $j$, then for each feature $k$ the number of times $\\pi_k$ it is used in a projection across all split nodes and decision trees is counted as\n", + "$$\n", + "\\pi_k = \\sum_{T \\in \\mathcal{T}} \\sum_{j \\in T} \\mathbb{I}(a_{jk}^* \\not= 0)\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], + "source": [ + "from sklearn.ensemble import RandomForestClassifier\n", + "from sklearn.metrics import accuracy_score\n", + "from oblique_forests.tree.oblique_tree import ObliqueTreeClassifier as OTC\n", + "from oblique_forests.sporf import ObliqueForestClassifier as SPORF\n", + "from oblique_forests.morf import Conv2DObliqueForestClassifier as MORF\n", + "\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import seaborn as sns\n", + "\n", + "mpl.rcParams.update({\n", + " \"axes.titlesize\": \"xx-large\",\n", + " \"axes.spines.bottom\": False,\n", + " \"axes.spines.left\": False,\n", + " \"xtick.bottom\": False,\n", + " \"ytick.left\": False,\n", + " \"image.cmap\": \"inferno\",\n", + " \"image.aspect\": 1\n", + "})\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Digits Dataset\n", + "We visualize feature importances identified by `RF`, `SPORF`, and `MORF` on a subset of the MNIST dataset. We only consider threes and fives and use 100 8x8 images from each class." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1797, 64) (1797,)\n" + ] + } + ], + "source": [ + "from sklearn.datasets import load_digits\n", + "\n", + "images, labels = load_digits(n_class=10, return_X_y=True, as_frame=False)\n", + "print(images.shape, labels.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(200, 64) (200,)\n" + ] + } + ], + "source": [ + "# Get 100 samples of 3s and 5s\n", + "n = 100\n", + "class0_idx = np.where(labels == 3)[0][:n]\n", + "class1_idx = np.where(labels == 5)[0][:n]\n", + "\n", + "# Stack class data\n", + "X = np.vstack([images[class0_idx], images[class1_idx]])\n", + "y = np.hstack([labels[class0_idx], labels[class1_idx]])\n", + "\n", + "# Apply random shuffling\n", + "permuted_idx = np.random.permutation(2 * n)\n", + "X = X[permuted_idx]\n", + "y = y[permuted_idx]\n", + "print(X.shape, y.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 3, figsize=(12, 4))\n", + "avg_3 = images[class0_idx].mean(axis=0).reshape(8, 8)\n", + "avg_5 = images[class1_idx].mean(axis=0).reshape(8, 8)\n", + "diff = np.abs(avg_3 - avg_5)\n", + "\n", + "axs[0].imshow(avg_3)\n", + "axs[0].set_title(\"Average 3\")\n", + "\n", + "axs[1].imshow(avg_5)\n", + "axs[1].set_title(\"Average 5\")\n", + "\n", + "axs[2].imshow(diff)\n", + "axs[2].set_title(\"Absolute Difference\")\n", + "for ax in axs:\n", + " ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + " )\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "clfs = [\n", + " RandomForestClassifier(random_state=0),\n", + " SPORF(random_state=0),\n", + " MORF(random_state=0, image_height=8, image_width=8)\n", + "]\n", + "for clf in clfs:\n", + " clf.fit(X, y)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "def rename_clf(clf):\n", + " if isinstance(clf, RandomForestClassifier):\n", + " return \"RF\"\n", + " elif isinstance(clf, SPORF):\n", + " return \"SPORF\"\n", + " elif isinstance(clf, MORF):\n", + " return \"MORF\"" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 3, figsize=(19, 4))\n", + "\n", + "for clf, ax in zip(clfs, axs):\n", + " importances = clf.feature_importances_\n", + " sns.heatmap(importances.reshape(8, 8), cmap='inferno', square=True, ax=ax)\n", + " ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + " )\n", + " ax.set_title(f\"{rename_clf(clf)} Importance\")\n", + "fig.tight_layout();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## MNIST Dataset\n", + "We visualize feature importances identified by `RF`, `SPORF`, and `MORF` on a subset of the MNIST dataset. We only consider threes and fives and use 100 28x28 images from each class." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(70000, 784) (70000,)\n" + ] + } + ], + "source": [ + "from sklearn.datasets import fetch_openml\n", + "\n", + "images, labels = fetch_openml('mnist_784', version=1, return_X_y=True, as_frame=False)\n", + "labels = labels.astype(int)\n", + "print(images.shape, labels.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(200, 784) (200,)\n" + ] + } + ], + "source": [ + "# Get 100 samples of 3s and 5s\n", + "n = 100\n", + "class0_idx = np.where(labels == 3)[0][:n]\n", + "class1_idx = np.where(labels == 5)[0][:n]\n", + "\n", + "# Stack class data\n", + "X = np.vstack([images[class0_idx], images[class1_idx]])\n", + "y = np.hstack([labels[class0_idx], labels[class1_idx]])\n", + "\n", + "# Apply random shuffling\n", + "permuted_idx = np.random.permutation(2 * n)\n", + "X = X[permuted_idx]\n", + "y = y[permuted_idx]\n", + "print(X.shape, y.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 3, figsize=(12, 4))\n", + "avg_3 = images[class0_idx].mean(axis=0).reshape(28, 28)\n", + "avg_5 = images[class1_idx].mean(axis=0).reshape(28, 28)\n", + "diff = np.abs(avg_3 - avg_5)\n", + "\n", + "axs[0].imshow(avg_3)\n", + "axs[0].set_title(\"Average 3\")\n", + "\n", + "axs[1].imshow(avg_5)\n", + "axs[1].set_title(\"Average 5\")\n", + "\n", + "axs[2].imshow(diff)\n", + "axs[2].set_title(\"Absolute Difference\")\n", + "for ax in axs:\n", + " ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + " )\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ObliqueForestClassifier(n_estimators=500, random_state=0)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "clf = SPORF(n_estimators=500, random_state=0)\n", + "clf.fit(X, y)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def rename_clf(clf):\n", + " if isinstance(clf, RandomForestClassifier):\n", + " return \"RF\"\n", + " elif isinstance(clf, SPORF):\n", + " return \"SPORF\"\n", + " elif isinstance(clf, MORF):\n", + " return \"MORF\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2021-04-08T14:30:05.948935\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.4.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(figsize=(5, 4))\n", + "importances = clf.feature_importances_\n", + "sns.heatmap(importances.reshape(28, 28), cmap='inferno', square=True)\n", + "ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + ")\n", + "ax.set_title(f\"{rename_clf(clf)} Importance\")\n", + "fig.tight_layout();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# XXX: MORF fits too slowly\n", + "clfs = [\n", + " RandomForestClassifier(random_state=0),\n", + " SPORF(random_state=0),\n", + " MORF(random_state=0, image_height=28, image_width=28)\n", + "]\n", + "for clf in clfs:\n", + " clf.fit(X, y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, axs = plt.subplots(1, 3, figsize=(19, 4))\n", + "\n", + "for clf, ax in zip(clfs, ax):\n", + " importances = clf.feature_importances_\n", + " sns.heatmap(importances.reshape(28, 28), cmap='inferno', square=True, ax=ax)\n", + " ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + " )\n", + " ax.set_title(f\"{rename_clf(clf)} Importance\")\n", + "fig.tight_layout();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:ProgLearn]", + "language": "python", + "name": "conda-env-ProgLearn-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/oblique_forests/morf.py b/oblique_forests/morf.py index 8f3c65c..212c264 100644 --- a/oblique_forests/morf.py +++ b/oblique_forests/morf.py @@ -1,4 +1,8 @@ +import numpy as np +from joblib import Parallel, delayed from sklearn.ensemble._forest import ForestClassifier +from sklearn.utils.validation import check_is_fitted +from sklearn.utils.fixes import _joblib_parallel_args from .tree.morf_tree import Conv2DObliqueTreeClassifier @@ -84,3 +88,33 @@ def __init__( self.patch_height_min = patch_height_min self.patch_width_max = patch_width_max self.patch_width_min = patch_width_min + + @property + def feature_importances_(self): + """ + Computes the importance of every unique feature used to make a split + in each tree of the forest. + + Parameters + ---------- + normalize : bool, default=True + A boolean to indicate whether to normalize feature importances. + + Returns + ------- + importances : array of shape [n_features] + Array of count-based feature importances. + """ + check_is_fitted(self) + + all_importances = Parallel(n_jobs=self.n_jobs, + **_joblib_parallel_args(prefer='threads'))( + delayed(getattr)(tree, 'feature_importances_') + for tree in self.estimators_ if tree.tree.node_count > 1) + + if not all_importances: + return np.zeros(self.n_features_, dtype=np.float64) + + all_importances = np.mean(all_importances, + axis=0, dtype=np.float64) + return all_importances / np.sum(all_importances) \ No newline at end of file diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index ff3159a..838c9c3 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -67,7 +67,7 @@ def __init__( def feature_importances_(self): """ Computes the importance of every unique feature used to make a split - in the Oblique Tree. + in each tree of the forest. Parameters ---------- diff --git a/oblique_forests/tree/oblique_tree.py b/oblique_forests/tree/oblique_tree.py index b1ad7b8..1bddbf0 100644 --- a/oblique_forests/tree/oblique_tree.py +++ b/oblique_forests/tree/oblique_tree.py @@ -728,6 +728,7 @@ def __init__( # Max features self.max_features = max_features + self.n_jobs = n_jobs self.n_classes=None @@ -868,7 +869,7 @@ def feature_importances_(self): feature_importances_ : ndarray of shape (n_features,) Array of count-based feature importances. """ - # XXX: Still raises error even when OTC instance is fitted + # XXX: check_is_fitted raises error even when OTC instance is fitted # check_is_fitted(self) return self.tree.compute_feature_importances() From 2d3bf1f09c4a9488e730414b589c2959c77eec70 Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Fri, 9 Apr 2021 03:03:41 -0400 Subject: [PATCH 03/11] Copy sklearn feature importances tests for SPORF --- oblique_forests/tree/tests/test_sporf.py | 38 +++++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/oblique_forests/tree/tests/test_sporf.py b/oblique_forests/tree/tests/test_sporf.py index 2698c8f..86df4c8 100644 --- a/oblique_forests/tree/tests/test_sporf.py +++ b/oblique_forests/tree/tests/test_sporf.py @@ -149,15 +149,37 @@ def test_pure_set(): clf.fit(X, y) assert_array_equal(clf.predict(X), y) -def test_tree_feature_importances(): - - clf = OFC(random_state=0) +def test_importances(): + # Check variable importances. + X, y = datasets.make_classification(n_samples=5000, + n_features=10, + n_informative=3, + n_redundant=0, + n_repeated=0, + shuffle=False, + random_state=0) - clf.fit(diabetes.data, diabetes.target) + clf = OTC(random_state=0) + + clf.fit(X, y) importances = clf.feature_importances_ + n_important = np.sum(importances > 0.1) -def test_forest_feature_importances(): - clf = OFC(random_state=0) + assert importances.shape[0] == 10, "Failed with SPORF" + assert n_important == 3, "Failed with SPORF" - clf.fit(diabetes.data, diabetes.target) - importances = clf.feature_importances_ \ No newline at end of file + # Check on iris that importances are the same for all builders + clf = OTC(random_state=0) + clf.fit(iris.data, iris.target) + clf2 = OTC(random_state=0, max_leaf_nodes=len(iris.data)) + clf2.fit(iris.data, iris.target) + + assert_array_equal(clf.feature_importances_, + clf2.feature_importances_) + +def test_importances_raises(): + # XXX: check_is_fitted does not work for our trees yet + # Check if variable importance before fit raises ValueError. + clf = OTC(random_state=0) + with pytest.raises(ValueError): + getattr(clf, 'feature_importances_') \ No newline at end of file From c274d7120b9de286fbcdd458d8da7b4654ab7db9 Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Tue, 20 Apr 2021 02:33:26 -0400 Subject: [PATCH 04/11] Update importance notebook with digits dataset --- docs/tutorials/test_feature_importance.ipynb | 5699 +----------------- oblique_forests/sporf.py | 1 - oblique_forests/tree/morf_tree.py | 10 + 3 files changed, 159 insertions(+), 5551 deletions(-) diff --git a/docs/tutorials/test_feature_importance.ipynb b/docs/tutorials/test_feature_importance.ipynb index 9def664..4c8cb64 100644 --- a/docs/tutorials/test_feature_importance.ipynb +++ b/docs/tutorials/test_feature_importance.ipynb @@ -17,18 +17,9 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ "from sklearn.ensemble import RandomForestClassifier\n", "from sklearn.metrics import accuracy_score\n", @@ -66,12 +57,12 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 2, "metadata": {}, "outputs": [ { - "name": "stdout", "output_type": "stream", + "name": "stdout", "text": [ "(1797, 64) (1797,)\n" ] @@ -80,18 +71,18 @@ "source": [ "from sklearn.datasets import load_digits\n", "\n", - "images, labels = load_digits(n_class=10, return_X_y=True, as_frame=False)\n", + "images, labels = load_digits(return_X_y=True)\n", "print(images.shape, labels.shape)" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 3, "metadata": {}, "outputs": [ { - "name": "stdout", "output_type": "stream", + "name": "stdout", "text": [ "(200, 64) (200,)\n" ] @@ -99,41 +90,42 @@ ], "source": [ "# Get 100 samples of 3s and 5s\n", - "n = 100\n", - "class0_idx = np.where(labels == 3)[0][:n]\n", - "class1_idx = np.where(labels == 5)[0][:n]\n", + "num = 100\n", + "threes = np.where(labels == 3)[0][:num]\n", + "fives = np.where(labels == 5)[0][:num]\n", + "idx = np.concatenate((threes, fives))\n", "\n", - "# Stack class data\n", - "X = np.vstack([images[class0_idx], images[class1_idx]])\n", - "y = np.hstack([labels[class0_idx], labels[class1_idx]])\n", + "# Subset train data\n", + "X = images[idx]\n", + "y = labels[idx]\n", "\n", "# Apply random shuffling\n", - "permuted_idx = np.random.permutation(2 * n)\n", + "permuted_idx = np.random.permutation(len(idx))\n", "X = X[permuted_idx]\n", "y = y[permuted_idx]\n", + "\n", "print(X.shape, y.shape)" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [ { + "output_type": "display_data", "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-19T23:33:49.858551\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} } ], "source": [ "fig, axs = plt.subplots(1, 3, figsize=(12, 4))\n", - "avg_3 = images[class0_idx].mean(axis=0).reshape(8, 8)\n", - "avg_5 = images[class1_idx].mean(axis=0).reshape(8, 8)\n", + "avg_3 = images[threes].mean(axis=0).reshape(8, 8)\n", + "avg_5 = images[fives].mean(axis=0).reshape(8, 8)\n", "diff = np.abs(avg_3 - avg_5)\n", "\n", "axs[0].imshow(avg_3)\n", @@ -158,7 +150,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -173,7 +165,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -188,20 +180,19 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 7, "metadata": {}, "outputs": [ { + "output_type": "display_data", "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-19T23:42:06.515360\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" }, "metadata": { "needs_background": "light" - }, - "output_type": "display_data" + } } ], "source": [ @@ -232,77 +223,83 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 8, "metadata": { "scrolled": true }, "outputs": [ { - "name": "stdout", "output_type": "stream", + "name": "stdout", "text": [ - "(70000, 784) (70000,)\n" + "(60000, 28, 28)\n(60000,)\n(10000, 28, 28)\n(10000,)\n" ] } ], "source": [ - "from sklearn.datasets import fetch_openml\n", + "# from sklearn.datasets import fetch_openml\n", + "from keras.datasets import mnist\n", "\n", - "images, labels = fetch_openml('mnist_784', version=1, return_X_y=True, as_frame=False)\n", - "labels = labels.astype(int)\n", - "print(images.shape, labels.shape)" + "(X_train, y_train), (X_test, y_test) = mnist.load_data()\n", + "print(X_train.shape, y_train.shape, X_test.shape, y_test.shape, sep='\\n')" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 13, "metadata": {}, "outputs": [ { - "name": "stdout", "output_type": "stream", + "name": "stdout", "text": [ - "(200, 784) (200,)\n" + "(200, 28, 28)\n(200,)\n(1010, 28, 28)\n(1010,)\n" ] } ], "source": [ "# Get 100 samples of 3s and 5s\n", - "n = 100\n", - "class0_idx = np.where(labels == 3)[0][:n]\n", - "class1_idx = np.where(labels == 5)[0][:n]\n", + "num = 100\n", + "threes = np.where(y_train == 3)[0][:num]\n", + "fives = np.where(y_train == 5)[0][:num]\n", + "train_idx = np.concatenate((threes, fives))\n", "\n", - "# Stack class data\n", - "X = np.vstack([images[class0_idx], images[class1_idx]])\n", - "y = np.hstack([labels[class0_idx], labels[class1_idx]])\n", + "# Subset train data\n", + "Xtrain = X_train[train_idx]\n", + "ytrain = y_train[train_idx]\n", "\n", "# Apply random shuffling\n", - "permuted_idx = np.random.permutation(2 * n)\n", - "X = X[permuted_idx]\n", - "y = y[permuted_idx]\n", - "print(X.shape, y.shape)" + "permuted_idx = np.random.permutation(len(train_idx))\n", + "Xtrain = Xtrain[permuted_idx]\n", + "ytrain = ytrain[permuted_idx]\n", + "\n", + "# Subset test data\n", + "test_idx = np.where(y_test == 3)[0]\n", + "Xtest = X_test[test_idx]\n", + "ytest = y_test[test_idx]\n", + "\n", + "print(Xtrain.shape, ytrain.shape, Xtest.shape, ytest.shape, sep='\\n')" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 14, "metadata": {}, "outputs": [ { + "output_type": "display_data", "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-19T23:45:39.120271\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} } ], "source": [ "fig, axs = plt.subplots(1, 3, figsize=(12, 4))\n", - "avg_3 = images[class0_idx].mean(axis=0).reshape(28, 28)\n", - "avg_5 = images[class1_idx].mean(axis=0).reshape(28, 28)\n", + "avg_3 = X_train[threes].mean(axis=0)\n", + "avg_5 = X_train[fives].mean(axis=0)\n", "diff = np.abs(avg_3 - avg_5)\n", "\n", "axs[0].imshow(avg_3)\n", @@ -327,30 +324,38 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": { - "scrolled": true - }, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# morf = MORF(random_state=0, image_height=28, image_width=28)\n", + "# morf.fit(X, y)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, "outputs": [ { + "output_type": "execute_result", "data": { "text/plain": [ - "ObliqueForestClassifier(n_estimators=500, random_state=0)" + "RandomForestClassifier(random_state=0)" ] }, - "execution_count": 5, "metadata": {}, - "output_type": "execute_result" + "execution_count": 21 } ], "source": [ - "clf = SPORF(n_estimators=500, random_state=0)\n", - "clf.fit(X, y)" + "clf = RandomForestClassifier(random_state=0)\n", + "clf.fit(Xtrain.reshape(Xtrain.shape[0], -1), ytrain)" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 22, "metadata": {}, "outputs": [], "source": [ @@ -365,5480 +370,75 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 23, "metadata": {}, "outputs": [ { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-20T02:19:29.789968\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "fig, ax = plt.subplots(figsize=(5, 4))\n", + "importances = clf.feature_importances_\n", + "sns.heatmap(importances.reshape(28, 28), cmap='inferno', square=True)\n", + "ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + ")\n", + "ax.set_title(f\"{rename_clf(clf)} Importance\")\n", + "fig.tight_layout();" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "output_type": "execute_result", "data": { - "image/png": "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\n", - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2021-04-08T14:30:05.948935\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.4.1, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], "text/plain": [ - "
" + "ObliqueForestClassifier(n_estimators=500, random_state=0)" ] }, + "metadata": {}, + "execution_count": 28 + } + ], + "source": [ + "clf = SPORF(n_estimators=500, random_state=0)\n", + "clf.fit(Xtrain.reshape(Xtrain.shape[0], -1), ytrain)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-20T02:31:06.856520\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, "metadata": { "needs_background": "light" - }, - "output_type": "display_data" + } } ], "source": [ @@ -5906,9 +506,8 @@ ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:ProgLearn]", - "language": "python", - "name": "conda-env-ProgLearn-py" + "name": "python380jvsc74a57bd039ca1c7a169e56d6a333ccd59f8c6786beb2b8f5c3cc68b80d4610822621472b", + "display_name": "Python 3.8.0 64-bit ('ProgLearn': conda)" }, "language_info": { "codemirror_mode": { @@ -5920,9 +519,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.0" + "version": "3.8.0-final" } }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index 838c9c3..4271b3e 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -92,4 +92,3 @@ def feature_importances_(self): all_importances = np.mean(all_importances, axis=0, dtype=np.float64) return all_importances / np.sum(all_importances) - diff --git a/oblique_forests/tree/morf_tree.py b/oblique_forests/tree/morf_tree.py index b38e451..ca4c6fb 100644 --- a/oblique_forests/tree/morf_tree.py +++ b/oblique_forests/tree/morf_tree.py @@ -471,3 +471,13 @@ def sample_proj_mat(self, sample_inds): proj_X = self.X[sample_inds, :] @ proj_mat return proj_X, proj_mat + +# %% +if __name__ == "__main__": + import numpy as np + from scipy.linalg import toeplitz + from scipy.signal import convolve2d + + X = np.random.randint(5, size=(3, 3)) + k = np.ones((2, 2)) +# %% From 15271a0827515f48e8ef01ab57cc7161464485fb Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Tue, 20 Apr 2021 03:48:33 -0400 Subject: [PATCH 05/11] Add naive implementation of Ronan's feature importance --- docs/tutorials/test_feature_importance.ipynb | 4 +- oblique_forests/sporf.py | 39 +++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/test_feature_importance.ipynb b/docs/tutorials/test_feature_importance.ipynb index 4c8cb64..91cc1e0 100644 --- a/docs/tutorials/test_feature_importance.ipynb +++ b/docs/tutorials/test_feature_importance.ipynb @@ -9,9 +9,9 @@ "\n", "There are many approaches that have been suggested for quantifying importances. The `scikit-learn` implementation of the random forest quantifies these importances using the Gini impurity. For `SPORF` and `MORF`, we use a projection forest specific metric to quantify feature importance by computing the normalized count of the number of times a feature $k$ was used in projections across the ensemble of decision trees.\n", "\n", - "Specifically, if we denote $\\mathcal{T}$ as the set of decision trees in our forest where each decision tree $T \\in \\mathcal{T}$ is composed of many nodes $j$, then for each feature $k$ the number of times $\\pi_k$ it is used in a projection across all split nodes and decision trees is counted as\n", + "Specifically, consider our forest $\\mathcal{T}$ to be a collection of decision trees $\\{T_i\\}_{i=1}^n$, where each decision tree $T_i \\in \\mathcal{T}$ is composed of many nodes $j$. Let $\\mathcal{A}$ be the set of unique atoms across all nodes and all trees in our forest. For each feature $k$, its importance $\\pi_k$ is computed as the number of times an atom assigns it a nonzero weighting, followed by a normalization of $|\\mathcal{A}|$.\n", "$$\n", - "\\pi_k = \\sum_{T \\in \\mathcal{T}} \\sum_{j \\in T} \\mathbb{I}(a_{jk}^* \\not= 0)\n", + "\\pi_k = \\frac{1}{|\\mathcal{A}|} \\sum_{T_i \\in \\mathcal{T}} \\sum_{j \\in T_i} \\mathbb{I}(a_{jk} \\not= 0)\n", "$$" ] }, diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index 4271b3e..e354cc1 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -4,7 +4,7 @@ from sklearn.utils.validation import check_is_fitted from sklearn.utils.fixes import _joblib_parallel_args -from .tree.oblique_tree import ObliqueTreeClassifier +from oblique_forests.tree.oblique_tree import ObliqueTreeClassifier class ObliqueForestClassifier(ForestClassifier): @@ -92,3 +92,40 @@ def feature_importances_(self): all_importances = np.mean(all_importances, axis=0, dtype=np.float64) return all_importances / np.sum(all_importances) + + @property + def feature_importances2_(self): + """ + Computes the importance of every unique feature used to make a split + in each tree of the forest. + + Parameters + ---------- + normalize : bool, default=True + A boolean to indicate whether to normalize feature importances. + + Returns + ------- + importances : array of shape [n_features] + Array of count-based feature importances. + """ + # TODO: Parallelize this + # 1. Find all unique atoms in the forest + # 2. Compute number of times each atom appears across all trees + atoms = [node.proj_vec + for node in tree.tree.nodes + if node.proj_vec is not None + for tree in self.estimators_ + if tree.tree.node_count > 1] + unique_atoms, counts = np.unique(atoms, axis=0, return_counts=True) + + # 3. An atom assigns importance to each feature based on count of atom usage + importances = np.zeros(self.n_features_, dtype=np.float64) + for atom, count in zip(unique_atoms, counts): + importances[np.nonzero(atom)] += count + + # 4. Average across atoms + if len(unique_atoms) > 0: + importances /= len(unique_atoms) + + return importances From 9194573fc0201faf712c85c171400e9a0ab863cd Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Tue, 20 Apr 2021 11:56:38 -0400 Subject: [PATCH 06/11] Fix small bug in new feature importance --- oblique_forests/sporf.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index e354cc1..553e37d 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -109,14 +109,12 @@ def feature_importances2_(self): importances : array of shape [n_features] Array of count-based feature importances. """ - # TODO: Parallelize this + # TODO: Parallelize this and see if there is an equivalent way to express this better # 1. Find all unique atoms in the forest # 2. Compute number of times each atom appears across all trees atoms = [node.proj_vec - for node in tree.tree.nodes - if node.proj_vec is not None - for tree in self.estimators_ - if tree.tree.node_count > 1] + for tree in self.estimators_ if tree.tree.node_count > 1 + for node in tree.tree.nodes if node.proj_vec is not None] unique_atoms, counts = np.unique(atoms, axis=0, return_counts=True) # 3. An atom assigns importance to each feature based on count of atom usage From 6363df3bf50265fbc363216e54a96d691347ee6a Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Tue, 20 Apr 2021 13:18:47 -0400 Subject: [PATCH 07/11] Sync second feature importances implementation --- oblique_forests/sporf.py | 12 ++++++------ oblique_forests/tree/morf_tree.py | 10 ---------- oblique_forests/tree/tests/test_sporf.py | 24 +++++++++++++++++++++++- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index 553e37d..7df4cce 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -112,18 +112,18 @@ def feature_importances2_(self): # TODO: Parallelize this and see if there is an equivalent way to express this better # 1. Find all unique atoms in the forest # 2. Compute number of times each atom appears across all trees - atoms = [node.proj_vec - for tree in self.estimators_ if tree.tree.node_count > 1 + forest_projections = [node.proj_vec + for tree in self.estimators_ if tree.tree.node_count > 0 for node in tree.tree.nodes if node.proj_vec is not None] - unique_atoms, counts = np.unique(atoms, axis=0, return_counts=True) + unique_projections, counts = np.unique(forest_projections, axis=0, return_counts=True) # 3. An atom assigns importance to each feature based on count of atom usage importances = np.zeros(self.n_features_, dtype=np.float64) - for atom, count in zip(unique_atoms, counts): + for atom, count in zip(unique_projections, counts): importances[np.nonzero(atom)] += count # 4. Average across atoms - if len(unique_atoms) > 0: - importances /= len(unique_atoms) + if len(unique_projections) > 0: + importances /= len(unique_projections) return importances diff --git a/oblique_forests/tree/morf_tree.py b/oblique_forests/tree/morf_tree.py index ca4c6fb..b38e451 100644 --- a/oblique_forests/tree/morf_tree.py +++ b/oblique_forests/tree/morf_tree.py @@ -471,13 +471,3 @@ def sample_proj_mat(self, sample_inds): proj_X = self.X[sample_inds, :] @ proj_mat return proj_X, proj_mat - -# %% -if __name__ == "__main__": - import numpy as np - from scipy.linalg import toeplitz - from scipy.signal import convolve2d - - X = np.random.randint(5, size=(3, 3)) - k = np.ones((2, 2)) -# %% diff --git a/oblique_forests/tree/tests/test_sporf.py b/oblique_forests/tree/tests/test_sporf.py index 86df4c8..a751040 100644 --- a/oblique_forests/tree/tests/test_sporf.py +++ b/oblique_forests/tree/tests/test_sporf.py @@ -182,4 +182,26 @@ def test_importances_raises(): # Check if variable importance before fit raises ValueError. clf = OTC(random_state=0) with pytest.raises(ValueError): - getattr(clf, 'feature_importances_') \ No newline at end of file + getattr(clf, 'feature_importances_') + + +def test_importances2(): + # XXX: Print-based checks + X, y = datasets.make_classification(n_samples=500, + n_features=10, + n_informative=3, + n_redundant=0, + n_repeated=0, + shuffle=False, + random_state=0) + + clf = OFC(random_state=0) + clf.fit(X, y) + + # Test ArXiv paper implementation + imps = clf.feature_importances_ + print(imps) + + # Test Ronan's pseudocode implementation + imps2 = clf.feature_importances2_ + print(imps2) From de2771ab2c450fdeb4332f1e271ae5ca22063f4f Mon Sep 17 00:00:00 2001 From: Adam Li Date: Tue, 20 Apr 2021 13:43:38 -0400 Subject: [PATCH 08/11] Fixing check is fitted. --- MANIFEST | 34 ++ oblique_forests/morf.py | 14 +- oblique_forests/sporf.py | 32 +- oblique_forests/tree/morf_tree.py | 4 +- oblique_forests/tree/oblique_tree.py | 18 +- oblique_forests/tree/tests/test_splitter.py | 9 +- oblique_forests/tree/tests/test_sporf.py | 507 +++++++++++++++++--- 7 files changed, 519 insertions(+), 99 deletions(-) create mode 100644 MANIFEST diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..f986d3b --- /dev/null +++ b/MANIFEST @@ -0,0 +1,34 @@ +# file GENERATED by distutils, do NOT edit +MANIFEST.in +Pipfile +Pipfile.lock +README.md +requirements.txt +setup.cfg +setup.py +setup_old.py +data/orthant_test.npy +data/orthant_train_400.npy +data/sparse_parity_test.npy +data/sparse_parity_train_1000.npy +oblique_forests/__init__.py +oblique_forests/morf.py +oblique_forests/setup.py +oblique_forests/sporf.py +oblique_forests/_build_utils/__init__.py +oblique_forests/_build_utils/deprecated_modules.py +oblique_forests/_build_utils/openmp_helpers.py +oblique_forests/tests/test_sporf_forest.py +oblique_forests/tree/__init__.py +oblique_forests/tree/_split.cpp +oblique_forests/tree/_split.pyx +oblique_forests/tree/conv.py +oblique_forests/tree/morf_split.py +oblique_forests/tree/morf_tree.py +oblique_forests/tree/oblique_base.py +oblique_forests/tree/oblique_tree.py +oblique_forests/tree/setup.py +oblique_forests/tree/tests/test_morf_tree.py +oblique_forests/tree/tests/test_splitter.py +oblique_forests/tree/tests/test_sporf.py +oblique_forests/tree/tests/test_sporf_tree.py diff --git a/oblique_forests/morf.py b/oblique_forests/morf.py index 74f6f52..33106f4 100644 --- a/oblique_forests/morf.py +++ b/oblique_forests/morf.py @@ -206,14 +206,16 @@ def feature_importances_(self): """ check_is_fitted(self) - all_importances = Parallel(n_jobs=self.n_jobs, - **_joblib_parallel_args(prefer='threads'))( - delayed(getattr)(tree, 'feature_importances_') - for tree in self.estimators_ if tree.tree.node_count > 1) + all_importances = Parallel( + n_jobs=self.n_jobs, **_joblib_parallel_args(prefer="threads") + )( + delayed(getattr)(tree, "feature_importances_") + for tree in self.estimators_ + if tree.tree_.node_count > 1 + ) if not all_importances: return np.zeros(self.n_features_, dtype=np.float64) - all_importances = np.mean(all_importances, - axis=0, dtype=np.float64) + all_importances = np.mean(all_importances, axis=0, dtype=np.float64) return all_importances / np.sum(all_importances) diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index 9d6411c..3bcd1b3 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -118,16 +118,18 @@ def feature_importances_(self): """ check_is_fitted(self) - all_importances = Parallel(n_jobs=self.n_jobs, - **_joblib_parallel_args(prefer='threads'))( - delayed(getattr)(tree, 'feature_importances_') - for tree in self.estimators_ if tree.tree.node_count > 1) + all_importances = Parallel( + n_jobs=self.n_jobs, **_joblib_parallel_args(prefer="threads") + )( + delayed(getattr)(tree, "feature_importances_") + for tree in self.estimators_ + if tree.tree_.node_count > 1 + ) if not all_importances: return np.zeros(self.n_features_, dtype=np.float64) - all_importances = np.mean(all_importances, - axis=0, dtype=np.float64) + all_importances = np.mean(all_importances, axis=0, dtype=np.float64) return all_importances / np.sum(all_importances) @property @@ -149,16 +151,22 @@ def feature_importances2_(self): # TODO: Parallelize this and see if there is an equivalent way to express this better # 1. Find all unique atoms in the forest # 2. Compute number of times each atom appears across all trees - forest_projections = [node.proj_vec - for tree in self.estimators_ if tree.tree.node_count > 0 - for node in tree.tree.nodes if node.proj_vec is not None] - unique_projections, counts = np.unique(forest_projections, axis=0, return_counts=True) - + forest_projections = [ + node.proj_vec + for tree in self.estimators_ + if tree.tree_.node_count > 0 + for node in tree.tree.nodes + if node.proj_vec is not None + ] + unique_projections, counts = np.unique( + forest_projections, axis=0, return_counts=True + ) + # 3. An atom assigns importance to each feature based on count of atom usage importances = np.zeros(self.n_features_, dtype=np.float64) for atom, count in zip(unique_projections, counts): importances[np.nonzero(atom)] += count - + # 4. Average across atoms if len(unique_projections) > 0: importances /= len(unique_projections) diff --git a/oblique_forests/tree/morf_tree.py b/oblique_forests/tree/morf_tree.py index 936cb9a..4dc31aa 100644 --- a/oblique_forests/tree/morf_tree.py +++ b/oblique_forests/tree/morf_tree.py @@ -265,7 +265,7 @@ def fit(self, X, y, sample_weight=None, check_input=True, X_idx_sorted=None): splitter = self._set_splitter(X, y) # create the Oblique tree - self.tree = ObliqueTree( + self.tree_ = ObliqueTree( splitter, self.min_samples_split, self.min_samples_leaf, @@ -273,7 +273,7 @@ def fit(self, X, y, sample_weight=None, check_input=True, X_idx_sorted=None): self.min_impurity_split, self.min_impurity_decrease, ) - self.tree.build() + self.tree_.build() return self diff --git a/oblique_forests/tree/oblique_tree.py b/oblique_forests/tree/oblique_tree.py index 9ebdaca..e25c397 100644 --- a/oblique_forests/tree/oblique_tree.py +++ b/oblique_forests/tree/oblique_tree.py @@ -538,10 +538,8 @@ def compute_feature_importances(self, normalize=True): feature_importances_ : ndarray of shape (n_features,) Normalized importance (counts) of each feature. """ - # XXX: Still raises error even when OTC instance is fitted - # check_is_fitted(self) importances = np.zeros((self.splitter.n_features,)) - + # Count number of times a feature is used in a projection across all nodes for node in self.nodes: importances[np.nonzero(node.proj_vec)] += 1 @@ -667,7 +665,7 @@ def fit(self, X, y, sample_weight=None, check_input=True, X_idx_sorted=None): tree_func = self._tree_class() # instantiate the tree and build it - self.tree = tree_func( + self.tree_ = tree_func( splitter, self.min_samples_split, self.min_samples_leaf, @@ -675,7 +673,7 @@ def fit(self, X, y, sample_weight=None, check_input=True, X_idx_sorted=None): self.min_impurity_split, self.min_impurity_decrease, ) - self.tree.build() + self.tree_.build() return self @@ -693,7 +691,7 @@ def apply(self, X): pred_nodes : array of shape[n_samples] The indices for each test sample's final node in the oblique tree. """ - pred_nodes = self.tree.predict(X).astype(int) + pred_nodes = self.tree_.predict(X).astype(int) return pred_nodes def predict(self, X, check_input=True): @@ -716,7 +714,7 @@ def predict(self, X, check_input=True): pred_nodes = self.apply(X) for k in range(len(pred_nodes)): id = pred_nodes[k] - preds[k] = self.tree.nodes[id].label + preds[k] = self.tree_.nodes[id].label return preds @@ -740,7 +738,7 @@ def predict_proba(self, X, check_input=True): pred_nodes = self.apply(X) for k in range(len(preds)): id = pred_nodes[k] - preds[k] = self.tree.nodes[id].proba + preds[k] = self.tree_.nodes[id].proba return preds @@ -778,6 +776,6 @@ def feature_importances_(self): Array of count-based feature importances. """ # XXX: check_is_fitted raises error even when OTC instance is fitted - # check_is_fitted(self) + check_is_fitted(self) - return self.tree.compute_feature_importances() + return self.tree_.compute_feature_importances() diff --git a/oblique_forests/tree/tests/test_splitter.py b/oblique_forests/tree/tests/test_splitter.py index 4ef97e9..30b2767 100644 --- a/oblique_forests/tree/tests/test_splitter.py +++ b/oblique_forests/tree/tests/test_splitter.py @@ -34,16 +34,16 @@ def test_argmin(self): assert 4 == j def test_matmul(self): - + b = BOS() A = np.zeros((3, 3), dtype=np.float64) B = np.ones((3, 3), dtype=np.float64) - + for i in range(3): for j in range(3): - A[i, j] = 3*i + j + 1 - + A[i, j] = 3 * i + j + 1 + res = b.test_matmul(A, B) C = np.ones((3, 3), dtype=np.float64) @@ -53,7 +53,6 @@ def test_matmul(self): assert_allclose(C, res) - def test_impurity(self): """ diff --git a/oblique_forests/tree/tests/test_sporf.py b/oblique_forests/tree/tests/test_sporf.py index a751040..4c39c18 100644 --- a/oblique_forests/tree/tests/test_sporf.py +++ b/oblique_forests/tree/tests/test_sporf.py @@ -1,11 +1,10 @@ - import numpy as np from numpy.testing import ( - assert_almost_equal, - assert_allclose, - assert_array_equal, - assert_array_almost_equal - ) + assert_almost_equal, + assert_allclose, + assert_array_equal, + assert_array_almost_equal, +) import pytest from oblique_forests.tree.oblique_tree import ObliqueTreeClassifier as OTC @@ -17,35 +16,405 @@ """ Sklearn test_tree.py stuff """ -X_small = np.array([ - [0, 0, 4, 0, 0, 0, 1, -14, 0, -4, 0, 0, 0, 0, ], - [0, 0, 5, 3, 0, -4, 0, 0, 1, -5, 0.2, 0, 4, 1, ], - [-1, -1, 0, 0, -4.5, 0, 0, 2.1, 1, 0, 0, -4.5, 0, 1, ], - [-1, -1, 0, -1.2, 0, 0, 0, 0, 0, 0, 0.2, 0, 0, 1, ], - [-1, -1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, ], - [-1, -2, 0, 4, -3, 10, 4, 0, -3.2, 0, 4, 3, -4, 1, ], - [2.11, 0, -6, -0.5, 0, 11, 0, 0, -3.2, 6, 0.5, 0, -3, 1, ], - [2.11, 0, -6, -0.5, 0, 11, 0, 0, -3.2, 6, 0, 0, -2, 1, ], - [2.11, 8, -6, -0.5, 0, 11, 0, 0, -3.2, 6, 0, 0, -2, 1, ], - [2.11, 8, -6, -0.5, 0, 11, 0, 0, -3.2, 6, 0.5, 0, -1, 0, ], - [2, 8, 5, 1, 0.5, -4, 10, 0, 1, -5, 3, 0, 2, 0, ], - [2, 0, 1, 1, 1, -1, 1, 0, 0, -2, 3, 0, 1, 0, ], - [2, 0, 1, 2, 3, -1, 10, 2, 0, -1, 1, 2, 2, 0, ], - [1, 1, 0, 2, 2, -1, 1, 2, 0, -5, 1, 2, 3, 0, ], - [3, 1, 0, 3, 0, -4, 10, 0, 1, -5, 3, 0, 3, 1, ], - [2.11, 8, -6, -0.5, 0, 1, 0, 0, -3.2, 6, 0.5, 0, -3, 1, ], - [2.11, 8, -6, -0.5, 0, 1, 0, 0, -3.2, 6, 1.5, 1, -1, -1, ], - [2.11, 8, -6, -0.5, 0, 10, 0, 0, -3.2, 6, 0.5, 0, -1, -1, ], - [2, 0, 5, 1, 0.5, -2, 10, 0, 1, -5, 3, 1, 0, -1, ], - [2, 0, 1, 1, 1, -2, 1, 0, 0, -2, 0, 0, 0, 1, ], - [2, 1, 1, 1, 2, -1, 10, 2, 0, -1, 0, 2, 1, 1, ], - [1, 1, 0, 0, 1, -3, 1, 2, 0, -5, 1, 2, 1, 1, ], - [3, 1, 0, 1, 0, -4, 1, 0, 1, -2, 0, 0, 1, 0, ]]) - -y_small = [1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, - 0, 0] -y_small_reg = [1.0, 2.1, 1.2, 0.05, 10, 2.4, 3.1, 1.01, 0.01, 2.98, 3.1, 1.1, - 0.0, 1.2, 2, 11, 0, 0, 4.5, 0.201, 1.06, 0.9, 0] +X_small = np.array( + [ + [ + 0, + 0, + 4, + 0, + 0, + 0, + 1, + -14, + 0, + -4, + 0, + 0, + 0, + 0, + ], + [ + 0, + 0, + 5, + 3, + 0, + -4, + 0, + 0, + 1, + -5, + 0.2, + 0, + 4, + 1, + ], + [ + -1, + -1, + 0, + 0, + -4.5, + 0, + 0, + 2.1, + 1, + 0, + 0, + -4.5, + 0, + 1, + ], + [ + -1, + -1, + 0, + -1.2, + 0, + 0, + 0, + 0, + 0, + 0, + 0.2, + 0, + 0, + 1, + ], + [ + -1, + -1, + 0, + 0, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 1, + ], + [ + -1, + -2, + 0, + 4, + -3, + 10, + 4, + 0, + -3.2, + 0, + 4, + 3, + -4, + 1, + ], + [ + 2.11, + 0, + -6, + -0.5, + 0, + 11, + 0, + 0, + -3.2, + 6, + 0.5, + 0, + -3, + 1, + ], + [ + 2.11, + 0, + -6, + -0.5, + 0, + 11, + 0, + 0, + -3.2, + 6, + 0, + 0, + -2, + 1, + ], + [ + 2.11, + 8, + -6, + -0.5, + 0, + 11, + 0, + 0, + -3.2, + 6, + 0, + 0, + -2, + 1, + ], + [ + 2.11, + 8, + -6, + -0.5, + 0, + 11, + 0, + 0, + -3.2, + 6, + 0.5, + 0, + -1, + 0, + ], + [ + 2, + 8, + 5, + 1, + 0.5, + -4, + 10, + 0, + 1, + -5, + 3, + 0, + 2, + 0, + ], + [ + 2, + 0, + 1, + 1, + 1, + -1, + 1, + 0, + 0, + -2, + 3, + 0, + 1, + 0, + ], + [ + 2, + 0, + 1, + 2, + 3, + -1, + 10, + 2, + 0, + -1, + 1, + 2, + 2, + 0, + ], + [ + 1, + 1, + 0, + 2, + 2, + -1, + 1, + 2, + 0, + -5, + 1, + 2, + 3, + 0, + ], + [ + 3, + 1, + 0, + 3, + 0, + -4, + 10, + 0, + 1, + -5, + 3, + 0, + 3, + 1, + ], + [ + 2.11, + 8, + -6, + -0.5, + 0, + 1, + 0, + 0, + -3.2, + 6, + 0.5, + 0, + -3, + 1, + ], + [ + 2.11, + 8, + -6, + -0.5, + 0, + 1, + 0, + 0, + -3.2, + 6, + 1.5, + 1, + -1, + -1, + ], + [ + 2.11, + 8, + -6, + -0.5, + 0, + 10, + 0, + 0, + -3.2, + 6, + 0.5, + 0, + -1, + -1, + ], + [ + 2, + 0, + 5, + 1, + 0.5, + -2, + 10, + 0, + 1, + -5, + 3, + 1, + 0, + -1, + ], + [ + 2, + 0, + 1, + 1, + 1, + -2, + 1, + 0, + 0, + -2, + 0, + 0, + 0, + 1, + ], + [ + 2, + 1, + 1, + 1, + 2, + -1, + 10, + 2, + 0, + -1, + 0, + 2, + 1, + 1, + ], + [ + 1, + 1, + 0, + 0, + 1, + -3, + 1, + 2, + 0, + -5, + 1, + 2, + 1, + 1, + ], + [ + 3, + 1, + 0, + 1, + 0, + -4, + 1, + 0, + 1, + -2, + 0, + 0, + 1, + 0, + ], + ] +) + +y_small = [1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0] +y_small_reg = [ + 1.0, + 2.1, + 1.2, + 0.05, + 10, + 2.4, + 3.1, + 1.01, + 0.01, + 2.98, + 3.1, + 1.1, + 0.0, + 1.2, + 2, + 11, + 0, + 0, + 4.5, + 0.201, + 1.06, + 0.9, + 0, +] # toy sample X = [[-2, -1], [-1, -1], [-1, -2], [1, 1], [1, 2], [2, 1]] @@ -70,6 +439,7 @@ # Ignoring digits dataset cause it takes a minute + def test_classification_toy(): # Check classification on a toy dataset. clf = OTC(random_state=0) @@ -83,8 +453,9 @@ def test_classification_toy(): assert_array_equal(clf.predict(T), true_result) """ + def test_xor(): - + # Check on a XOR problem y = np.zeros((10, 10)) y[:5, :5] = 1 @@ -101,6 +472,7 @@ def test_xor(): assert accuracy_score(clf.predict(X), y) == 1 + def test_iris(): clf = OTC(random_state=0) @@ -108,9 +480,10 @@ def test_iris(): clf.fit(iris.data, iris.target) score = accuracy_score(clf.predict(iris.data), iris.target) assert score > 0.9 - + + def test_diabetes(): - + """ Diabetes should overfit with MSE = 0 for normal trees. idk if this applies to sporf, so this is just a placeholder @@ -122,7 +495,8 @@ def test_diabetes(): clf.fit(diabetes.data, diabetes.target) score = accuracy_score(clf.predict(diabetes.data), diabetes.target) assert score > 0.9 - + + def test_probability(): clf = OTC(random_state=0) @@ -130,14 +504,14 @@ def test_probability(): clf.fit(iris.data, iris.target) p = clf.predict_proba(iris.data) - assert_array_almost_equal(np.sum(p, 1), - np.ones(iris.data.shape[0])) + assert_array_almost_equal(np.sum(p, 1), np.ones(iris.data.shape[0])) + + assert_array_equal(np.argmax(p, 1), clf.predict(iris.data)) + + assert_almost_equal( + clf.predict_proba(iris.data), np.exp(clf.predict_log_proba(iris.data)) + ) - assert_array_equal(np.argmax(p, 1), - clf.predict(iris.data)) - - assert_almost_equal(clf.predict_proba(iris.data), - np.exp(clf.predict_log_proba(iris.data))) def test_pure_set(): @@ -149,15 +523,18 @@ def test_pure_set(): clf.fit(X, y) assert_array_equal(clf.predict(X), y) + def test_importances(): # Check variable importances. - X, y = datasets.make_classification(n_samples=5000, - n_features=10, - n_informative=3, - n_redundant=0, - n_repeated=0, - shuffle=False, - random_state=0) + X, y = datasets.make_classification( + n_samples=5000, + n_features=10, + n_informative=3, + n_redundant=0, + n_repeated=0, + shuffle=False, + random_state=0, + ) clf = OTC(random_state=0) @@ -174,27 +551,29 @@ def test_importances(): clf2 = OTC(random_state=0, max_leaf_nodes=len(iris.data)) clf2.fit(iris.data, iris.target) - assert_array_equal(clf.feature_importances_, - clf2.feature_importances_) + assert_array_equal(clf.feature_importances_, clf2.feature_importances_) + def test_importances_raises(): # XXX: check_is_fitted does not work for our trees yet # Check if variable importance before fit raises ValueError. clf = OTC(random_state=0) with pytest.raises(ValueError): - getattr(clf, 'feature_importances_') + getattr(clf, "feature_importances_") def test_importances2(): # XXX: Print-based checks - X, y = datasets.make_classification(n_samples=500, - n_features=10, - n_informative=3, - n_redundant=0, - n_repeated=0, - shuffle=False, - random_state=0) - + X, y = datasets.make_classification( + n_samples=500, + n_features=10, + n_informative=3, + n_redundant=0, + n_repeated=0, + shuffle=False, + random_state=0, + ) + clf = OFC(random_state=0) clf.fit(X, y) From b8d8788bb63a503bda53bb0ad295127fff539750 Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Wed, 21 Apr 2021 03:58:59 -0400 Subject: [PATCH 09/11] Implement feature importances to match R code --- MANIFEST | 34 --------- docs/tutorials/test_feature_importance.ipynb | 78 ++++++++++---------- oblique_forests/morf.py | 32 +++++--- oblique_forests/sporf.py | 47 +++--------- oblique_forests/tree/oblique_tree.py | 67 +++++++++++++---- oblique_forests/tree/tests/test_morf_tree.py | 62 +++++++++++++++- oblique_forests/tree/tests/test_sporf.py | 9 +-- 7 files changed, 188 insertions(+), 141 deletions(-) delete mode 100644 MANIFEST diff --git a/MANIFEST b/MANIFEST deleted file mode 100644 index f986d3b..0000000 --- a/MANIFEST +++ /dev/null @@ -1,34 +0,0 @@ -# file GENERATED by distutils, do NOT edit -MANIFEST.in -Pipfile -Pipfile.lock -README.md -requirements.txt -setup.cfg -setup.py -setup_old.py -data/orthant_test.npy -data/orthant_train_400.npy -data/sparse_parity_test.npy -data/sparse_parity_train_1000.npy -oblique_forests/__init__.py -oblique_forests/morf.py -oblique_forests/setup.py -oblique_forests/sporf.py -oblique_forests/_build_utils/__init__.py -oblique_forests/_build_utils/deprecated_modules.py -oblique_forests/_build_utils/openmp_helpers.py -oblique_forests/tests/test_sporf_forest.py -oblique_forests/tree/__init__.py -oblique_forests/tree/_split.cpp -oblique_forests/tree/_split.pyx -oblique_forests/tree/conv.py -oblique_forests/tree/morf_split.py -oblique_forests/tree/morf_tree.py -oblique_forests/tree/oblique_base.py -oblique_forests/tree/oblique_tree.py -oblique_forests/tree/setup.py -oblique_forests/tree/tests/test_morf_tree.py -oblique_forests/tree/tests/test_splitter.py -oblique_forests/tree/tests/test_sporf.py -oblique_forests/tree/tests/test_sporf_tree.py diff --git a/docs/tutorials/test_feature_importance.ipynb b/docs/tutorials/test_feature_importance.ipynb index 91cc1e0..db90ff5 100644 --- a/docs/tutorials/test_feature_importance.ipynb +++ b/docs/tutorials/test_feature_importance.ipynb @@ -116,7 +116,7 @@ "output_type": "display_data", "data": { "text/plain": "
", - "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-19T23:33:49.858551\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-21T03:14:56.804734\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "image/png": "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\n" }, "metadata": {} @@ -184,15 +184,17 @@ "metadata": {}, "outputs": [ { - "output_type": "display_data", - "data": { - "text/plain": "
", - "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-19T23:42:06.515360\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "image/png": "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\n" - }, - "metadata": { - "needs_background": "light" - } + "output_type": "error", + "ename": "AttributeError", + "evalue": "'Conv2DObliqueTreeClassifier' object has no attribute 'tree_'", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mclf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0max\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mclfs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mimportances\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mclf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfeature_importances_\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0msns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mheatmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimportances\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m8\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m8\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcmap\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'inferno'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msquare\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0max\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m ax.tick_params(\n", + "\u001b[0;32m/opt/anaconda3/envs/ProgLearn/lib/python3.8/site-packages/oblique_forests/morf.py\u001b[0m in \u001b[0;36mfeature_importances_\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 208\u001b[0m \u001b[0;31m# 1. Find all unique atoms in the forest\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[0;31m# 2. Compute number of times each atom appears across all trees\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 210\u001b[0;31m forest_projections = [\n\u001b[0m\u001b[1;32m 211\u001b[0m \u001b[0mnode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mproj_vec\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 212\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mtree\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mestimators_\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/anaconda3/envs/ProgLearn/lib/python3.8/site-packages/oblique_forests/morf.py\u001b[0m in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 211\u001b[0m \u001b[0mnode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mproj_vec\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 212\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mtree\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mestimators_\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 213\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mtree\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtree_\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnode_count\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 214\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mnode\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtree\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtree_\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnodes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 215\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mproj_vec\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mAttributeError\u001b[0m: 'Conv2DObliqueTreeClassifier' object has no attribute 'tree_'" + ] } ], "source": [ @@ -223,7 +225,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 17, "metadata": { "scrolled": true }, @@ -246,7 +248,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -283,14 +285,14 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 19, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "
", - "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-19T23:45:39.120271\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-21T03:26:15.950727\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "image/png": "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\n" }, "metadata": {} @@ -324,17 +326,7 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# morf = MORF(random_state=0, image_height=28, image_width=28)\n", - "# morf.fit(X, y)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -345,7 +337,7 @@ ] }, "metadata": {}, - "execution_count": 21 + "execution_count": 20 } ], "source": [ @@ -355,7 +347,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -370,15 +362,15 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 22, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "
", - "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-20T02:19:29.789968\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "image/png": "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\n" + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-21T03:26:17.992359\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" }, "metadata": { "needs_background": "light" @@ -403,7 +395,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 25, "metadata": { "scrolled": true }, @@ -412,29 +404,29 @@ "output_type": "execute_result", "data": { "text/plain": [ - "ObliqueForestClassifier(n_estimators=500, random_state=0)" + "ObliqueForestClassifier(random_state=0)" ] }, "metadata": {}, - "execution_count": 28 + "execution_count": 25 } ], "source": [ - "clf = SPORF(n_estimators=500, random_state=0)\n", + "clf = SPORF(n_estimators=100, random_state=0)\n", "clf.fit(Xtrain.reshape(Xtrain.shape[0], -1), ytrain)" ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 26, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "
", - "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-20T02:31:06.856520\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "image/png": "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\n" + "image/svg+xml": "\n\n\n \n \n \n \n 2021-04-21T03:28:42.502439\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" }, "metadata": { "needs_background": "light" @@ -457,6 +449,16 @@ "fig.tight_layout();" ] }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "# morf = MORF(random_state=0, image_height=28, image_width=28)\n", + "# morf.fit(X, y)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -519,7 +521,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.0-final" + "version": "3.8.0" } }, "nbformat": 4, diff --git a/oblique_forests/morf.py b/oblique_forests/morf.py index 33106f4..b2f8fdd 100644 --- a/oblique_forests/morf.py +++ b/oblique_forests/morf.py @@ -204,18 +204,30 @@ def feature_importances_(self): importances : array of shape [n_features] Array of count-based feature importances. """ - check_is_fitted(self) - - all_importances = Parallel( - n_jobs=self.n_jobs, **_joblib_parallel_args(prefer="threads") - )( - delayed(getattr)(tree, "feature_importances_") + # TODO: Parallelize this and see if there is an equivalent way to express this better + # 1. Find all unique atoms in the forest + # 2. Compute number of times each atom appears across all trees + forest_projections = [ + node.proj_vec for tree in self.estimators_ - if tree.tree_.node_count > 1 + if tree.tree_.node_count > 0 + for node in tree.tree_.nodes + if node.proj_vec is not None + ] + unique_projections, counts = np.unique( + forest_projections, axis=0, return_counts=True ) - if not all_importances: + if counts.sum() == 0: return np.zeros(self.n_features_, dtype=np.float64) - all_importances = np.mean(all_importances, axis=0, dtype=np.float64) - return all_importances / np.sum(all_importances) + # 3. Count how many times each feature gets nonzero weight in unique projections + importances = np.zeros(self.n_features_) + for proj_vec, count in zip(unique_projections, counts): + importances[np.nonzero(proj_vec)] += count + + # 4. Normalize by number of unique projections + if len(unique_projections) > 0: + importances /= len(unique_projections) + + return importances diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index 3bcd1b3..ce37161 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -106,38 +106,6 @@ def feature_importances_(self): Computes the importance of every unique feature used to make a split in each tree of the forest. - Parameters - ---------- - normalize : bool, default=True - A boolean to indicate whether to normalize feature importances. - - Returns - ------- - importances : array of shape [n_features] - Array of count-based feature importances. - """ - check_is_fitted(self) - - all_importances = Parallel( - n_jobs=self.n_jobs, **_joblib_parallel_args(prefer="threads") - )( - delayed(getattr)(tree, "feature_importances_") - for tree in self.estimators_ - if tree.tree_.node_count > 1 - ) - - if not all_importances: - return np.zeros(self.n_features_, dtype=np.float64) - - all_importances = np.mean(all_importances, axis=0, dtype=np.float64) - return all_importances / np.sum(all_importances) - - @property - def feature_importances2_(self): - """ - Computes the importance of every unique feature used to make a split - in each tree of the forest. - Parameters ---------- normalize : bool, default=True @@ -155,19 +123,22 @@ def feature_importances2_(self): node.proj_vec for tree in self.estimators_ if tree.tree_.node_count > 0 - for node in tree.tree.nodes + for node in tree.tree_.nodes if node.proj_vec is not None ] unique_projections, counts = np.unique( forest_projections, axis=0, return_counts=True ) - # 3. An atom assigns importance to each feature based on count of atom usage - importances = np.zeros(self.n_features_, dtype=np.float64) - for atom, count in zip(unique_projections, counts): - importances[np.nonzero(atom)] += count + if counts.sum() == 0: + return np.zeros((self.n_features_), dtype=np.float64) - # 4. Average across atoms + # 3. Count how many times each feature gets nonzero weight in unique projections + importances = np.zeros((self.n_features_), dtype=np.float64) + for proj_vec, count in zip(unique_projections, counts): + importances[np.nonzero(proj_vec)] += count + + # 4. Normalize by number of unique projections if len(unique_projections) > 0: importances /= len(unique_projections) diff --git a/oblique_forests/tree/oblique_tree.py b/oblique_forests/tree/oblique_tree.py index e25c397..d439cab 100644 --- a/oblique_forests/tree/oblique_tree.py +++ b/oblique_forests/tree/oblique_tree.py @@ -529,26 +529,34 @@ def predict(self, X, check_input=True): return predictions - def compute_feature_importances(self, normalize=True): + def compute_feature_importances(self): """ Computes the importance of each feature (aka variable). + Parameters + ---------- + unique_projections : ndarray of shape (n_proj, n_features) + Array of unique sampling projection vectors. + Returns ------- - feature_importances_ : ndarray of shape (n_features,) - Normalized importance (counts) of each feature. + importances : ndarray of shape (n_features,) + Normalized importance of each feature of the data matrix. """ - importances = np.zeros((self.splitter.n_features,)) + projections = [ + node.proj_vec for node in self.nodes if node.proj_vec is not None + ] + unique_projections, counts = np.unique(projections, axis=0, return_counts=True) - # Count number of times a feature is used in a projection across all nodes - for node in self.nodes: - importances[np.nonzero(node.proj_vec)] += 1 + if counts.sum() == 0: + return np.zeros((self.splitter.n_features,)) - if normalize: - normalizer = np.sum(importances) - if normalizer > 0.0: - # Avoid dividing by zero (e.g., when root is pure) - importances /= normalizer + importances = np.zeros((self.splitter.n_features,)) + for proj_vec, count in zip(unique_projections, counts): + importances[np.nonzero(proj_vec)] += count + + if len(unique_projections) > 0: + importances /= len(unique_projections) return importances @@ -775,7 +783,40 @@ def feature_importances_(self): feature_importances_ : ndarray of shape (n_features,) Array of count-based feature importances. """ - # XXX: check_is_fitted raises error even when OTC instance is fitted check_is_fitted(self) return self.tree_.compute_feature_importances() + + def compute_projection_counts(self, unique_projections=None): + """ + Counts the number of times each unique projection in the tree appears. + + Parameters + ---------- + unique_projections : ndarray of shape (n_proj,), optional + Array of unique projections to count, by default None + + Returns + ------- + projection_counts : ndarray of shape (n_proj,) + Counts of each unique projection used in this tree. + """ + check_is_fitted(self) + + if unique_projections is None: + projections = [ + node.proj_vec + for node in self.tree_.nodes + if node.proj_vec is not None + ] + unique_projections, counts = np.unique(projections, axis=0, return_counts=True) + return counts, unique_projections + + # TODO: see if joblib will speed up at all for this for loop + n_proj = len(unique_projections) + counts = np.zeros(n_proj) + for node in self.tree_.nodes: + projection_idx = np.where((unique_projections == node.proj_vec).all(axis=1)) + counts[projection_idx] += 1 + + return counts, unique_projections \ No newline at end of file diff --git a/oblique_forests/tree/tests/test_morf_tree.py b/oblique_forests/tree/tests/test_morf_tree.py index 9cbd12c..32c1bf0 100644 --- a/oblique_forests/tree/tests/test_morf_tree.py +++ b/oblique_forests/tree/tests/test_morf_tree.py @@ -10,6 +10,10 @@ from sklearn.utils.validation import check_random_state from oblique_forests.tree.morf_split import Conv2DSplitter +from oblique_forests.sporf import ObliqueForestClassifier as SPORF +from oblique_forests.tree.oblique_tree import ObliqueTreeClassifier as OTC +from oblique_forests.morf import Conv2DObliqueForestClassifier as MORF +from oblique_forests.tree.morf_tree import Conv2DObliqueTreeClassifier # toy sample X = [[-2, -1], [-1, -1], [-1, -2], [1, 1], [1, 2], [2, 1]] @@ -43,7 +47,7 @@ def test_convolutional_splitter(): y[:25] = 0 splitter = Conv2DSplitter( - X, + X.reshape(n, -1), y, max_features=1, feature_combinations=1.5, @@ -52,4 +56,60 @@ def test_convolutional_splitter(): image_width=d, patch_height_max=2, patch_height_min=2, + patch_width_max=3, + patch_width_min=3, ) + + splitter.sample_proj_mat(splitter.indices) + + +if __name__ == "__main__": + + test_convolutional_splitter() + + # from sklearn.datasets import fetch_openml + from keras.datasets import mnist + import time + + (X_train, y_train), (X_test, y_test) = mnist.load_data() + + # Get 100 samples of 3s and 5s + num = 100 + threes = np.where(y_train == 3)[0][:num] + fives = np.where(y_train == 5)[0][:num] + train_idx = np.concatenate((threes, fives)) + + # Subset train data + Xtrain = X_train[train_idx] + ytrain = y_train[train_idx] + + # Apply random shuffling + permuted_idx = np.random.permutation(len(train_idx)) + Xtrain = Xtrain[permuted_idx] + ytrain = ytrain[permuted_idx] + + # Subset test data + test_idx = np.where(y_test == 3)[0] + Xtest = X_test[test_idx] + ytest = y_test[test_idx] + + print(f"-----{2 * num} samples") + + clf = OTC(random_state=0) + start = time.time() + clf.fit(Xtrain.reshape(Xtrain.shape[0], -1), ytrain) + elapsed = time.time() - start + print(elapsed) + print(f"SPORF Tree: {elapsed} sec") + + clf = Conv2DObliqueTreeClassifier(image_height=28, image_width=28, random_state=0) + start = time.time() + clf.fit(Xtrain.reshape(Xtrain.shape[0], -1), ytrain) + elapsed = time.time() - start + print(f"MORF Tree: {elapsed} sec") + + clf = SPORF(n_estimators=100, random_state=0) + start = time.time() + clf.fit(Xtrain.reshape(Xtrain.shape[0], -1), ytrain) + elapsed = time.time() - start + print(f"SPORF: {elapsed} sec") \ No newline at end of file diff --git a/oblique_forests/tree/tests/test_sporf.py b/oblique_forests/tree/tests/test_sporf.py index 4c39c18..e97cafe 100644 --- a/oblique_forests/tree/tests/test_sporf.py +++ b/oblique_forests/tree/tests/test_sporf.py @@ -555,14 +555,14 @@ def test_importances(): def test_importances_raises(): - # XXX: check_is_fitted does not work for our trees yet # Check if variable importance before fit raises ValueError. clf = OTC(random_state=0) with pytest.raises(ValueError): getattr(clf, "feature_importances_") -def test_importances2(): +# def test_importances2(): +if __name__ == "__main__": # XXX: Print-based checks X, y = datasets.make_classification( n_samples=500, @@ -577,10 +577,5 @@ def test_importances2(): clf = OFC(random_state=0) clf.fit(X, y) - # Test ArXiv paper implementation imps = clf.feature_importances_ print(imps) - - # Test Ronan's pseudocode implementation - imps2 = clf.feature_importances2_ - print(imps2) From c331f68354cc8f08e06abb7c0615d3cbae7eb653 Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Thu, 22 Apr 2021 02:05:25 -0400 Subject: [PATCH 10/11] Adjust tests for feature importance scaling --- oblique_forests/sporf.py | 4 ++-- oblique_forests/tree/tests/test_sporf.py | 26 +++--------------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/oblique_forests/sporf.py b/oblique_forests/sporf.py index ce37161..515ad4e 100644 --- a/oblique_forests/sporf.py +++ b/oblique_forests/sporf.py @@ -137,9 +137,9 @@ def feature_importances_(self): importances = np.zeros((self.n_features_), dtype=np.float64) for proj_vec, count in zip(unique_projections, counts): importances[np.nonzero(proj_vec)] += count - + # 4. Normalize by number of unique projections if len(unique_projections) > 0: importances /= len(unique_projections) - return importances + return importances \ No newline at end of file diff --git a/oblique_forests/tree/tests/test_sporf.py b/oblique_forests/tree/tests/test_sporf.py index e97cafe..921fecd 100644 --- a/oblique_forests/tree/tests/test_sporf.py +++ b/oblique_forests/tree/tests/test_sporf.py @@ -540,7 +540,7 @@ def test_importances(): clf.fit(X, y) importances = clf.feature_importances_ - n_important = np.sum(importances > 0.1) + n_important = np.sum(importances > 0.4) assert importances.shape[0] == 10, "Failed with SPORF" assert n_important == 3, "Failed with SPORF" @@ -548,7 +548,7 @@ def test_importances(): # Check on iris that importances are the same for all builders clf = OTC(random_state=0) clf.fit(iris.data, iris.target) - clf2 = OTC(random_state=0, max_leaf_nodes=len(iris.data)) + clf2 = OTC(random_state=0, max_depth=len(iris.data)) clf2.fit(iris.data, iris.target) assert_array_equal(clf.feature_importances_, clf2.feature_importances_) @@ -558,24 +558,4 @@ def test_importances_raises(): # Check if variable importance before fit raises ValueError. clf = OTC(random_state=0) with pytest.raises(ValueError): - getattr(clf, "feature_importances_") - - -# def test_importances2(): -if __name__ == "__main__": - # XXX: Print-based checks - X, y = datasets.make_classification( - n_samples=500, - n_features=10, - n_informative=3, - n_redundant=0, - n_repeated=0, - shuffle=False, - random_state=0, - ) - - clf = OFC(random_state=0) - clf.fit(X, y) - - imps = clf.feature_importances_ - print(imps) + getattr(clf, "feature_importances_") \ No newline at end of file From b4de02acbb80cce5b9c334093b84008fb8fc0c53 Mon Sep 17 00:00:00 2001 From: ChesterHuynh Date: Tue, 4 May 2021 18:08:08 -0400 Subject: [PATCH 11/11] Add runtime comparison --- docs/tutorials/runtime_comparison.ipynb | 404 ++++++++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100644 docs/tutorials/runtime_comparison.ipynb diff --git a/docs/tutorials/runtime_comparison.ipynb b/docs/tutorials/runtime_comparison.ipynb new file mode 100644 index 0000000..38d1021 --- /dev/null +++ b/docs/tutorials/runtime_comparison.ipynb @@ -0,0 +1,404 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import seaborn as sns\n", + "import time\n", + "\n", + "from sklearn.datasets import load_digits, fetch_openml\n", + "from sklearn.utils import check_random_state\n", + "\n", + "from sklearn.ensemble import RandomForestClassifier as RF\n", + "from oblique_forests.sporf import ObliqueForestClassifier as SPORF\n", + "from oblique_forests.morf import Conv2DObliqueForestClassifier as MORF\n", + "\n", + "sns.set_palette('Set1')\n", + "mpl.rcParams.update({\n", + " \"axes.titlesize\": \"xx-large\",\n", + " \"axes.spines.top\": False,\n", + " \"axes.spines.right\": False,\n", + " \"xtick.bottom\": False,\n", + " \"ytick.left\": False,\n", + " \"image.cmap\": \"inferno\",\n", + "})\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Digits Dataset\n", + "These are 8x8 images of handwritten digits from `sklearn.datasets`" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "(100, 64) (100,)\n" + ] + } + ], + "source": [ + "from sklearn.datasets import load_digits\n", + "\n", + "images, labels = load_digits(return_X_y=True)\n", + "\n", + "# Get 100 samples of 3s and 5s\n", + "n = 100\n", + "threes = np.where(labels == 3)[0][:(n // 2)]\n", + "fives = np.where(labels == 5)[0][:(n // 2)]\n", + "idx = np.concatenate((threes, fives))\n", + "\n", + "# Subset train data\n", + "X = images[idx]\n", + "y = labels[idx]\n", + "\n", + "# Apply random shuffling\n", + "permuted_idx = np.random.permutation(len(idx))\n", + "X = X[permuted_idx]\n", + "y = y[permuted_idx]\n", + "\n", + "print(X.shape, y.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-05-04T17:54:42.347403\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": {} + } + ], + "source": [ + "fig, axs = plt.subplots(1, 3, figsize=(12, 4))\n", + "avg_3 = images[threes].mean(axis=0).reshape(8, 8)\n", + "avg_5 = images[fives].mean(axis=0).reshape(8, 8)\n", + "diff = np.abs(avg_3 - avg_5)\n", + "\n", + "axs[0].imshow(avg_3)\n", + "axs[0].set_title(\"Average 3\")\n", + "\n", + "axs[1].imshow(avg_5)\n", + "axs[1].set_title(\"Average 5\")\n", + "\n", + "axs[2].imshow(diff)\n", + "axs[2].set_title(\"Absolute Difference\")\n", + "for ax in axs:\n", + " ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + " )\n", + "fig.tight_layout()" + ] + }, + { + "source": [ + "## `RF` vs `SPORF` runtimes" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def time_clf_digits(clf, ns, random_state=None):\n", + " runtimes = np.empty(len(ns))\n", + " rng = check_random_state(random_state)\n", + " images, labels = load_digits(return_X_y=True)\n", + " for i, n in enumerate(ns):\n", + " # Get only 3s and 5s\n", + " threes = np.where(labels == 3)[0][:(n // 2)]\n", + " fives = np.where(labels == 5)[0][:(n // 2)]\n", + " idx = np.concatenate((threes, fives))\n", + " X = images[idx]\n", + " y = labels[idx]\n", + "\n", + " # Shuffle samples\n", + " permuted_idx = rng.permutation(len(idx))\n", + " X = X[permuted_idx].reshape(n, -1)\n", + " y = y[permuted_idx].reshape(n)\n", + "\n", + " # Begin timing\n", + " start = time.time()\n", + " clf.fit(X, y)\n", + " runtimes[i] = time.time() - start\n", + " return runtimes" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def rename_clf(clf):\n", + " if isinstance(clf, RF):\n", + " return \"RF\"\n", + " elif isinstance(clf, SPORF):\n", + " return \"SPORF\"\n", + " elif isinstance(clf, MORF):\n", + " return \"MORF\"" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "ns = [10, 20, 40, 50, 100, 150, 200, 300]\n", + "\n", + "clfs = [\n", + " RF(random_state=0, n_jobs=1),\n", + " SPORF(random_state=0, n_jobs=1),\n", + " # MORF(random_state=0, image_height=8, image_width=8, n_jobs=1) # Too slow\n", + "]\n", + "\n", + "runtimes = []\n", + "for clf in clfs:\n", + " runtimes.append(time_clf_digits(clf, ns, random_state=0))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-05-04T17:54:56.738210\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "fig, ax = plt.subplots()\n", + "for runtime, clf in zip(runtimes, clfs):\n", + " ax.plot(ns, runtime, label=rename_clf(clf))\n", + "ax.legend()\n", + "fig.tight_layout();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## MNIST Dataset\n", + "These are 28x28 images of handwritten digits from `keras.datasets`" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "(100, 784) (100,)\n" + ] + } + ], + "source": [ + "from sklearn.datasets import fetch_openml\n", + "\n", + "images, labels = fetch_openml('mnist_784', version=1, return_X_y=True, as_frame=False)\n", + "\n", + "n = 100\n", + "threes = np.where(labels == '3')[0][:(n // 2)]\n", + "fives = np.where(labels == '5')[0][:(n // 2)]\n", + "idx = np.concatenate((threes, fives))\n", + "\n", + "# Subset train data\n", + "X = images[idx]\n", + "y = labels[idx]\n", + "\n", + "# Apply random shuffling\n", + "permuted_idx = np.random.permutation(len(idx))\n", + "X = X[permuted_idx]\n", + "y = y[permuted_idx]\n", + "\n", + "print(X.shape, y.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-05-04T17:55:20.302682\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": {} + } + ], + "source": [ + "fig, axs = plt.subplots(1, 3, figsize=(12, 4))\n", + "avg_3 = images[threes].mean(axis=0).reshape(28, 28)\n", + "avg_5 = images[fives].mean(axis=0).reshape(28, 28)\n", + "diff = np.abs(avg_3 - avg_5)\n", + "\n", + "axs[0].imshow(avg_3)\n", + "axs[0].set_title(\"Average 3\")\n", + "\n", + "axs[1].imshow(avg_5)\n", + "axs[1].set_title(\"Average 5\")\n", + "\n", + "axs[2].imshow(diff)\n", + "axs[2].set_title(\"Absolute Difference\")\n", + "for ax in axs:\n", + " ax.tick_params(\n", + " axis=\"both\",\n", + " which=\"both\",\n", + " bottom=False,\n", + " left=False,\n", + " labelbottom=False,\n", + " labelleft=False,\n", + " )\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def time_clf_mnist(clf, ns, random_state=None):\n", + " runtimes = np.empty(len(ns))\n", + " rng = check_random_state(random_state)\n", + " images, labels = fetch_openml('mnist_784', version=1, return_X_y=True, as_frame=False)\n", + " for i, n in enumerate(ns):\n", + " # Get only 3s and 5s\n", + " threes = np.where(labels == '3')[0][:(n // 2)]\n", + " fives = np.where(labels == '5')[0][:(n // 2)]\n", + " idx = np.concatenate((threes, fives))\n", + " X = images[idx]\n", + " y = labels[idx]\n", + "\n", + " # Shuffle samples\n", + " permuted_idx = rng.permutation(len(idx))\n", + " X = X[permuted_idx]\n", + " y = y[permuted_idx]\n", + "\n", + " # Begin timing\n", + " start = time.time()\n", + " clf.fit(X, y)\n", + " runtimes[i] = time.time() - start\n", + " return runtimes" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "ns = [10, 20, 40, 50, 100, 150, 200, 300, 500]\n", + "\n", + "clfs = [\n", + " RF(random_state=0, n_jobs=1),\n", + " SPORF(random_state=0, n_jobs=1),\n", + " # MORF(random_state=0, image_height=8, image_width=8, n_jobs=1) # Too slow\n", + "]\n", + "\n", + "runtimes = []\n", + "for clf in clfs:\n", + " runtimes.append(time_clf_mnist(clf, ns, random_state=0))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/svg+xml": "\n\n\n \n \n \n \n 2021-05-04T18:07:35.981486\n image/svg+xml\n \n \n Matplotlib v3.4.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAqw0lEQVR4nO3deXiU5b3G8e+PEJIQEiDsJOyGJWwBAi644IKigrhWWqtobU/rUo92c+sR1INaa7VVqba2Kh61VEUFcamAuCOrLAkhJECAQCAhQEgg+zznj4w22ggBMnlnMvfnunLNzJNZ7nlIcvPOPPO+5pxDREQk2LTwOoCIiEh9VFAiIhKUVFAiIhKUVFAiIhKUVFAiIhKUWnodAGDChAnuvffe8zqGiIh4w+obDIotqD179ngdQUREgkxQFJSIiMi3qaBERCQoHbGgzCzazJaZ2RozyzCze/3jCWa2wMyy/aft69zmTjPLMbMsMzsvkE9ARESap4YskqgAznLOlZpZJPCpmb0LXAoscs49ZGZ3AHcAt5tZCjAFGAx0BxaaWX/nXM3RBKuqqiIvL4/y8vKjekLNVXR0NElJSURGRnodRUSkSRyxoFztzvpK/Rcj/V8OmAyM84/PAj4EbvePz3bOVQBbzCwHGAMsOZpgeXl5xMXF0bt3b8zqXeARNpxzFBUVkZeXR58+fbyOIyLSJBr0HpSZRZjZaqAAWOCcWwp0cc7lA/hPO/uvnghsr3PzPP/YUSkvL6dDhw5hX04AZkaHDh20NSkiYaVBBeWcq3HOpQJJwBgzG3KYq9fXKMe0y3SV079pLkQk3BzVKj7n3H5qX8qbAOw2s24A/tMC/9XygB51bpYE7DzeoCIiEl4asoqvk5m185+PAc4BNgDzgKn+q00F5vrPzwOmmFmUmfUBkoFljZy7SURERJCamsqQIUOYNGkS+/fvByA3N5eYmBhSU1O//qqsrPQ2rIhIE/L5HHtKKgL6GA3ZguoGLDaztcByat+Dmg88BIw3s2xgvP8yzrkM4BVgPfAecNPRruALFjExMaxevZr09HQSEhKYOXPm19/r168fq1ev/vqrVatWHiYVEWk6BQfKueX/VnDjc8sorwrcn/eGrOJbC4yoZ7wIOPs7bjMDmHHc6YLIySefzNq1a72OISLiqQ8zd/PA3Awqq33cOmEAUS0Dt7+HoNhZ7JHsv2c6VeszGvU+I1MG0+6+6Q26bk1NDYsWLeL666//emzTpk2kpqYCMHbs2G9sXYmINDeHKqr543sbmLdqBwO7x3PvZcPo1TE2oI8ZEgXllbKyMlJTU8nNzWXUqFGMHz/+6+999RKfiEhzt35HMdPmrCVv7yGuObUPPznzBCIDuOX0lZAoqIZu6TS2r96DKi4uZuLEicycOZNbbrnFkywiIk2txud48dMt/HVxDh3aRPHk1NGM6pPQZI8fEgXltbZt2/L4448zefJkbrjhBq/jiIgE3K79Zdz7+jq+3LqPswd34fZJg4mPadpdramgGmjEiBEMHz6c2bNnc9ppp3kdR0QkYBak5/O7t9bj8zn+55IhXDC8uyc7C1BBHUZpaek3Lr/11ltfn09PT2/qOCIiAXWwvJo/vJPJO2t2MjipLfdeNoykhNae5VFBiYgI67bvZ/qcteTvL+P6M/px3Rl9aRnh7SEDVVAiImGsusbHrE828+xHm+kcH81TPxrD8J7tj3zDJqCCEhEJUzv3HWLanHWs276fCcO68asLB9EmOniOOaeCEhEJM8453lubz+/fXo9h3HvZUM4b1t3rWP9BBSUiEkZKyqp4eP56FqTvYnjPdky7dBjd28d4HateKigRkTDxZe5e7n19HYUlFfz0rBO45rS+RLQI3mPNebtEIwTMmDGDwYMHM2zYMFJTU1m6dCnjxo1jwIABDB8+nLFjx5KVlQVAZWUlt956K/369SM5OZnJkyeTl5f39X3p8B0i4oXqGh9PLczmxueX0zLC+Mv1Y7jujH5BXU6ggjqsJUuWMH/+fFatWsXatWtZuHAhPXrUHovxpZdeYs2aNUydOpVf//rXANx1112UlJSwceNGsrOzufjii7n00ktxrvaAwjp8h4g0tW1FB/mvvy9l1iebmZiayKyfncKQpHZex2oQFdRh5Ofn07FjR6KiogDo2LEj3bt/843E008/nZycHA4dOsRzzz3HY489RkREBADXXXcdUVFRfPDBB/9x3yeffDI7duwI/JMQkbDknGPeyjymPr2EvL2HeOB7w7n74iHERoXOOzshkfSxdzPZuKukUe+zf9c4bjt/0GGvc+6553LffffRv39/zjnnHK688krOOOOMb1znrbfeYujQoeTk5NCzZ0/i4+O/8f20tDQyMjI4++x/HzpLh+8QkUAqPlTJg/My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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "fig, ax = plt.subplots()\n", + "for runtime, clf in zip(runtimes, clfs):\n", + " ax.plot(ns, runtime, label=rename_clf(clf))\n", + "ax.legend()\n", + "fig.tight_layout();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "name": "python380jvsc74a57bd039ca1c7a169e56d6a333ccd59f8c6786beb2b8f5c3cc68b80d4610822621472b", + "display_name": "Python 3.8.0 64-bit ('ProgLearn': conda)" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file