{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "cell_id": "21658c23-2ef7-42e3-bf53-75fba223fcdd", "deepnote_cell_height": 202, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 1891, "execution_start": 1665161862284, "source_hash": "9500ca25" }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "\n", "from odtlearn.flow_oct import FlowOCT, BendersOCT\n", "from odtlearn.utils.binarize import Binarizer" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "22bfbe5ce3fb479c900abc4c0443c38a", "deepnote_cell_height": 84, "deepnote_cell_type": "markdown", "tags": [] }, "source": [ "# `FlowOCT` Examples" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "1d288c39a9ae485b822dbf5eccbd89e3", "deepnote_cell_height": 108, "deepnote_cell_type": "markdown", "tags": [] }, "source": [ "## Example 0: Binarization\n", "\n", "The following example shows how to binarize a dataset with categorical, integer, and continuous features using the built-in `Binarizer` class. This class follows the scikit-learn fit-transform paradigm, making it easy to integrate into your preprocessing pipeline.\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "cell_id": "4ed40d742b8d40c697c0ab3d765eaf45", "deepnote_cell_height": 166, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 2, "execution_start": 1665161870277, "source_hash": "c7737b5a", "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " sex race num_child age income\n", "0 M Black 1 10 50000\n", "1 F White 2 20 75000\n", "2 M Hispanic 4 40 100000\n", "3 M Black 3 30 60000\n", "4 F White 1 10 80000\n", "5 M Black 2 20 55000\n", "6 F White 4 40 90000\n", "7 M Hispanic 3 30 70000\n", "8 M Black 2 20 85000\n", "9 F White 1 10 65000\n" ] } ], "source": [ "number_of_child_list = [1, 2, 4, 3, 1, 2, 4, 3, 2, 1]\n", "age_list = [10, 20, 40, 30, 10, 20, 40, 30, 20, 10]\n", "race_list = [\n", " \"Black\",\n", " \"White\",\n", " \"Hispanic\",\n", " \"Black\",\n", " \"White\",\n", " \"Black\",\n", " \"White\",\n", " \"Hispanic\",\n", " \"Black\",\n", " \"White\",\n", "]\n", "sex_list = [\"M\", \"F\", \"M\", \"M\", \"F\", \"M\", \"F\", \"M\", \"M\", \"F\"]\n", "income_list = [50000, 75000, 100000, 60000, 80000, 55000, 90000, 70000, 85000, 65000]\n", "\n", "df = pd.DataFrame(\n", " list(zip(sex_list, race_list, number_of_child_list, age_list, income_list)),\n", " columns=[\"sex\", \"race\", \"num_child\", \"age\", \"income\"],\n", ")\n", "\n", "print(df)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "cell_id": "7abc1f79d5044501a954f66ddda8a2d7", "deepnote_cell_height": 628, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 67, "execution_start": 1664770046804, "source_hash": "10849c45", "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " sex_M race_Black race_Hispanic race_White num_child_1 num_child_2 \\\n", "0 1.0 1.0 0.0 0.0 1.0 1.0 \n", "1 0.0 0.0 0.0 1.0 0.0 1.0 \n", "2 1.0 0.0 1.0 0.0 0.0 0.0 \n", "3 1.0 1.0 0.0 0.0 0.0 0.0 \n", "4 0.0 0.0 0.0 1.0 1.0 1.0 \n", "5 1.0 1.0 0.0 0.0 0.0 1.0 \n", "6 0.0 0.0 0.0 1.0 0.0 0.0 \n", "7 1.0 0.0 1.0 0.0 0.0 0.0 \n", "8 1.0 1.0 0.0 0.0 0.0 1.0 \n", "9 0.0 0.0 0.0 1.0 1.0 1.0 \n", "\n", " num_child_3 num_child_4 age_10 age_20 age_30 age_40 income_0 \\\n", "0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 \n", "1 1.0 1.0 0.0 1.0 1.0 1.0 0.0 \n", "2 0.0 1.0 0.0 0.0 0.0 1.0 0.0 \n", "3 1.0 1.0 0.0 0.0 1.0 1.0 0.0 \n", "4 1.0 1.0 1.0 1.0 1.0 1.0 0.0 \n", "5 1.0 1.0 0.0 1.0 1.0 1.0 1.0 \n", "6 0.0 1.0 0.0 0.0 0.0 1.0 0.0 \n", "7 1.0 1.0 0.0 0.0 1.0 1.0 0.0 \n", "8 1.0 1.0 0.0 1.0 1.0 1.0 0.0 \n", "9 1.0 1.0 1.0 1.0 1.0 1.0 0.0 \n", "\n", " income_1 income_2 income_3 income_4 \n", "0 1.0 1.0 1.0 1.0 \n", "1 0.0 1.0 1.0 1.0 \n", "2 0.0 0.0 0.0 1.0 \n", "3 1.0 1.0 1.0 1.0 \n", "4 0.0 0.0 1.0 1.0 \n", "5 1.0 1.0 1.0 1.0 \n", "6 0.0 0.0 0.0 1.0 \n", "7 0.0 1.0 1.0 1.0 \n", "8 0.0 0.0 1.0 1.0 \n", "9 1.0 1.0 1.0 1.0 \n" ] } ], "source": [ "binarizer = Binarizer(\n", " categorical_cols=[\"sex\", \"race\"],\n", " integer_cols=[\"num_child\", \"age\"],\n", " real_cols=[\"income\"],\n", " n_bins=5 # Number of bins for continuous features\n", ")\n", "\n", "# Fit and transform the data\n", "df_enc = binarizer.fit_transform(df)\n", "\n", "print(df_enc)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `Binarizer` class follows the scikit-learn fit-transform paradigm:\n", "\n", "We initialize the `Binarizer` with our desired parameters, specifying which columns are categorical, integer, and real-valued.\n", "We call the fit_transform method, which first fits the binarizer to our data (learning the necessary encoding schemes) and then transforms the data using those learned encodings.\n", "\n", "The resulting `df_enc` DataFrame contains the binarized version of our original data:\n", "\n", "Categorical columns (sex, race) are one-hot encoded.\n", "Integer columns (num_child, age) are binary encoded, where each column represents \"greater than or equal to\" a certain value.\n", "The continuous column (income) is first discretized into 5 bins, then binary encoded similar to the integer columns." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Index(['sex_M', 'race_Black', 'race_Hispanic', 'race_White', 'num_child_1',\n", " 'num_child_2', 'num_child_3', 'num_child_4', 'age_10', 'age_20',\n", " 'age_30', 'age_40', 'income_0', 'income_1', 'income_2', 'income_3',\n", " 'income_4'],\n", " dtype='object')\n" ] } ], "source": [ "print(df_enc.columns)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This binarized data is now ready to be used with any of the models in ODTlearn, which require binary input features.\n", "If you need to transform new data using the same encoding scheme, you can use the transform method of the fitted binarizer:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " sex_M race_Black race_Hispanic race_White num_child_1 num_child_2 \\\n", "0 0.0 0.0 1.0 0.0 0.0 1.0 \n", "1 1.0 0.0 0.0 1.0 0.0 0.0 \n", "\n", " num_child_3 num_child_4 age_10 age_20 age_30 age_40 income_0 \\\n", "0 1.0 1.0 0.0 1.0 1.0 1.0 0 \n", "1 1.0 1.0 0.0 0.0 1.0 1.0 0 \n", "\n", " income_1 income_2 income_3 income_4 \n", "0 0 1.0 1.0 0 \n", "1 0 0.0 1.0 0 \n" ] } ], "source": [ "new_data = pd.DataFrame({\n", " \"sex\": [\"F\", \"M\"],\n", " \"race\": [\"Hispanic\", \"White\"],\n", " \"num_child\": [2, 3],\n", " \"age\": [20, 30],\n", " \"income\": [70000, 80000]\n", "})\n", "\n", "new_data_enc = binarizer.transform(new_data)\n", "print(new_data_enc)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that for categorical features, if the new data contains categories not seen during fitting, the transform method will raise an error. In such cases, you might need to refit the binarizer on a dataset that includes all possible categories." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00002-e9b87ac4-673e-49e4-9b9e-b65b2cea9708", "deepnote_cell_height": 188, "deepnote_cell_type": "markdown" }, "source": [ "## Example 1: Varying `depth` and `_lambda`\n", "In this part, we study a simple example and investigate different parameter combinations to provide intuition on how they affect the structure of the tree.\n", "\n", "First we generate the data for our example. The diagram within the code block shows the training dataset. Our dataset has two binary features (X1 and X2) and two class labels (+1 and -1)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "cell_id": "00003-848cadcc-11d1-4e7f-b476-6b0aa6fc5b44", "deepnote_cell_height": 310, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 3, "execution_start": 1665161893704, "owner_user_id": "fe086183-1334-4d34-b4e4-e2e52f4c0652", "source_hash": "75060998" }, "outputs": [], "source": [ "from odtlearn.datasets import flow_oct_example\n", "\n", "\"\"\"\n", " X2\n", " | |\n", " | |\n", " 1 + + | -\n", " | | \n", " |---------------|-------------\n", " | |\n", " 0 - - - - | + + +\n", " | - - - |\n", " |______0________|_______1_______X1\n", "\"\"\"\n", "\n", "\n", "X, y = flow_oct_example()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00004-08d3e617-af87-4be1-ae2d-e7894cfe2beb", "deepnote_cell_height": 101, "deepnote_cell_type": "markdown" }, "source": [ "### Tree with `depth = 1`\n", "\n", "In the following, we fit a classification tree of depth 1, i.e., a tree with a single branching node and two leaf nodes." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "cell_id": "00005-3fdf503d-31bf-499d-a332-db805ec8b030", "deepnote_cell_height": 230, "deepnote_cell_type": "code", "deepnote_output_heights": [ null, 20 ], "deepnote_to_be_reexecuted": false, "execution_millis": 773, "execution_start": 1665161919210, "source_hash": "9ef0a950" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 100\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 110 rows, 89 columns and 250 nonzeros\n", "Model fingerprint: 0x5e9209d1\n", "Variable types: 84 continuous, 5 integer (5 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Presolve removed 102 rows and 82 columns\n", "Presolve time: 0.00s\n", "Presolved: 8 rows, 7 columns, 16 nonzeros\n", "Variable types: 6 continuous, 1 integer (1 binary)\n", "Found heuristic solution: objective 9.0000000\n", "\n", "Root relaxation: objective 1.000000e+01, 2 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", "* 0 0 0 10.0000000 10.00000 0.00% - 0s\n", "\n", "Explored 1 nodes (2 simplex iterations) in 0.00 seconds (0.00 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 2: 10 9 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.000000000000e+01, best bound 1.000000000000e+01, gap 0.0000%\n", "\n", "User-callback calls 573, time in user-callback 0.00 sec\n" ] }, { "data": { "text/plain": [ "FlowOCT(solver=gurobi,depth=1,time_limit=100,num_threads=None,verbose=False)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stcl = FlowOCT(depth=1, solver=\"gurobi\", time_limit=100)\n", "stcl.store_search_progress_log = True\n", "stcl.fit(X, y)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "cell_id": "00006-3528e5a2-503d-41bd-b914-933e4b53d8a4", "deepnote_cell_height": 163, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 928, "execution_start": 1665161928297, "source_hash": "ab843413" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimality gap is 0.0\n", "In-sample accuracy is 0.7692307692307693\n" ] } ], "source": [ "predictions = stcl.predict(X)\n", "print(f'Optimality gap is {stcl.optim_gap}')\n", "print(f\"In-sample accuracy is {np.sum(predictions==y)/y.shape[0]}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Users can access statistics from the optimization run such as optimality gap, number of nodes, number of constraints, etc. Directly as properties of the initialized class or through the `_solver` object. For example, one can access the optimality gap and the number of solutions after fitting the optimal decision tree through the `optim_gap` and `num_solutions` properties." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimality gap is 0.0\n", "Number of solutions 2\n" ] } ], "source": [ "print(f'Optimality gap is {stcl.optim_gap}')\n", "print(f'Number of solutions {stcl.num_solutions}')" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00007-ff875aa5-d595-4038-9c0c-db76394cb64e", "deepnote_cell_height": 110, "deepnote_cell_type": "markdown" }, "source": [ "As we can see above, we find the optimal tree and the in-sample accuracy is 76%.\n", "\n", "ODTlearn provides two different ways of visualizing the structure of the tree. The first method prints the structure of the tree in the console:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "cell_id": "00008-7810b10f-28cc-4cfa-bcce-b3c6fe18be24", "deepnote_cell_height": 207, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 3, "execution_start": 1665161943547, "source_hash": "2f43d041" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#########node 1\n", "branch on X_0\n", "#########node 2\n", "leaf 0\n", "#########node 3\n", "leaf 1\n" ] } ], "source": [ "stcl.print_tree()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00009-90bfb8df-67ac-4e97-abe9-8076249db2b8", "deepnote_cell_height": 52, "deepnote_cell_type": "markdown" }, "source": [ "The second method plots the structure of the tree using `matplotlib`:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "cell_id": "00010-c3d86f40-82ba-45c3-aa11-b8fddb6bead1", "deepnote_cell_height": 534, "deepnote_cell_type": "code", "deepnote_output_heights": [ 406 ], "deepnote_to_be_reexecuted": false, "execution_millis": 270, "execution_start": 1665161948808, "source_hash": "d2159fb3" }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(5, 5))\n", "stcl.plot_tree(ax=ax)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We also provide a simple function allowing users to plot the search progress log over time. Note that you must set the attribute `store_search_progress_log` to `True` before calling the `fit` method to ensure that the bound information is stored. " ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 100\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 110 rows, 89 columns and 250 nonzeros\n", "Model fingerprint: 0x5e9209d1\n", "Variable types: 84 continuous, 5 integer (5 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Presolve removed 102 rows and 82 columns\n", "Presolve time: 0.00s\n", "Presolved: 8 rows, 7 columns, 16 nonzeros\n", "Variable types: 6 continuous, 1 integer (1 binary)\n", "Found heuristic solution: objective 9.0000000\n", "\n", "Root relaxation: objective 1.000000e+01, 2 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", "* 0 0 0 10.0000000 10.00000 0.00% - 0s\n", "\n", "Explored 1 nodes (2 simplex iterations) in 0.01 seconds (0.00 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 2: 10 9 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.000000000000e+01, best bound 1.000000000000e+01, gap 0.0000%\n", "\n", "User-callback calls 573, time in user-callback 0.00 sec\n" ] }, { "data": { "text/plain": [ "FlowOCT(solver=gurobi,depth=1,time_limit=100,num_threads=None,verbose=False)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stcl_progress_log = FlowOCT(depth=1, solver=\"gurobi\", time_limit=100)\n", "stcl_progress_log.store_search_progress_log = True\n", "stcl_progress_log.fit(X, y)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "stcl.plot_search_progress()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00011-8ac47211-d4df-494b-9423-fccb70be09ca", "deepnote_cell_height": 101, "deepnote_cell_type": "markdown" }, "source": [ "### Tree with `depth = 2`\n", "\n", "Now we increase the depth of the tree to achieve higher accuracy." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "cell_id": "00012-6fd1f710-63dc-45bc-aea9-fb6544a3e13d", "deepnote_cell_height": 184, "deepnote_cell_type": "code", "deepnote_output_heights": [ 20 ], "deepnote_to_be_reexecuted": false, "execution_millis": 7, "execution_start": 1665161961681, "source_hash": "1c3c8b1c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 60\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 274 rows, 209 columns and 642 nonzeros\n", "Model fingerprint: 0x51470803\n", "Variable types: 196 continuous, 13 integer (13 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Found heuristic solution: objective -0.0000000\n", "Presolve removed 250 rows and 187 columns\n", "Presolve time: 0.00s\n", "Presolved: 24 rows, 22 columns, 76 nonzeros\n", "Found heuristic solution: objective 8.0000000\n", "Variable types: 16 continuous, 6 integer (6 binary)\n", "\n", "Root relaxation: objective 1.300000e+01, 14 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", "* 0 0 0 13.0000000 13.00000 0.00% - 0s\n", "\n", "Explored 1 nodes (14 simplex iterations) in 0.00 seconds (0.00 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 3: 13 8 -0 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.300000000000e+01, best bound 1.300000000000e+01, gap 0.0000%\n" ] }, { "data": { "text/plain": [ "FlowOCT(solver=gurobi,depth=2,time_limit=60,num_threads=None,verbose=False)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stcl = FlowOCT(depth=2, solver=\"gurobi\")\n", "stcl.fit(X, y)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "cell_id": "00013-c3674981-c2c8-4b4b-b429-57a230ae5e93", "deepnote_cell_height": 163, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 619, "execution_start": 1665161968547, "source_hash": "6b45f8a6" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In-sample accuracy is 1.0\n" ] } ], "source": [ "predictions = stcl.predict(X)\n", "print(f\"In-sample accuracy is {np.sum(predictions==y)/y.shape[0]}\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "9ee768479e2a4cbd84a0fa6352d26365", "deepnote_cell_height": 52, "deepnote_cell_type": "markdown", "tags": [] }, "source": [ "As we can see, with depth 2, we can achieve 100% in-sample accuracy." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "cell_id": "a9fba11c28df4a56a1a0a3102d2b0314", "deepnote_cell_height": 534, "deepnote_cell_type": "code", "deepnote_output_heights": [ 406 ], "deepnote_to_be_reexecuted": false, "execution_millis": 366, "execution_start": 1665161976627, "source_hash": "702243f5", "tags": [] }, "outputs": [ { "data": { "image/png": "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n+/NmjXzyZMn++uvv+533nmnt2rVys8+++zKz9xyyy3evHlznzp1qs+cOdOnTZvmN910k7/44ot7bzroYz6o78vdfdKkSQ543759/Y477vDXX3/dr776agf8gQcecHf3NWvWeHZ2tnfr1s0feeQRnzZtmp9++umekJDg06dPD8v3oUlTXSaVOwfwXbmrzAnbFHgATXRy98iPKSMjwwsKCvbM8vHjx3tmZqYXFhb6rFmzHPCHH37Y9/boo4864HPnznV39xEjRvioUaO8BkEfc718X3sXNHv069fPTz31VHd3v/baaz0xMdHz8vIql5eVlXnPnj19wIABYfk+NGmqy+TuKncO9LtSmROeSY+0AnTFFVdQWFjIE088AUBxcTEPP/wwl1xyCenp6cyYMYOUlBTOPfdcysrKKqfTTjsNgFmzZgEwaNAgpk+fzo033sjs2bMpKSkJ7Jgaw4gRI6r83a9fP1auXAlEvpPBgwfTo0ePyuWJiYmMHj2aTz/9lB07djRqrCKxRuXOgVOZEw5KeAKUm5vLyJEjueeeewB45pln2LJlC2PGjAFgw4YNlJSU0Lx5c5KTkyundu3aAbB582YAfv3rXzN58mSmTZvGSSedRFZWFpdddhmbNm0K5sAaWJs2bar8nZqaWtm2YMuWLXTo0KHaZ3JycnB3tm7d2igxisQqlTsHTmVOOOht6QG76qqrGD58OHPmzOHee+/lpJNOok+fPgBkZWWRlpbGO++8s9/P5ubmApCcnMzEiROZOHEi+fn5vPzyy0yYMIHCwkKeeuqpRjuWWNCmTRvy8/Orzc/Pz8fMaN1agzSLqNypPypz4kjQz9Sa6FRFr169fOjQoQ74Y489Vjn/7bffdsDfeOONfT9So1GjRnmfPn32nhX0MR/097XneXppaWmVY/3Rj37kXbp0cXf36667zpOSkvyrr76qXF5WVua9evXygQMHhuX70KSpLlMVKndq/q5U5oRrUg1PDBg7dizjxo0jOzubc845p3L+sGHDGD16NOeeey4TJkzg2GOPJSEhgeXLlzN9+nSmTJlCz549GTlyJEceeSQDBw6kdevWzJ07lxkzZlRWUTcl48eP56GHHuLUU09l8uTJZGRkcNddd7FkyRJeeeWVoMMTiRkqd+qHypw4EnTG1USnKtauXeuAX3fddfsu8vLycp86dar379/fU1NT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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(10, 5))\n", "stcl.plot_tree(ax=ax, fontsize=20)\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00015-cea69e08-5d82-438f-804e-422f3dfe1528", "deepnote_cell_height": 167, "deepnote_cell_type": "markdown" }, "source": [ "### Tree with `depth=2` and Positive `_lambda`\n", "\n", "As we saw in the above example, with depth 2, we can fully classify the training data. However if we add a regularization term with a high enough value of `_lambda`, we can justify pruning one of the branching nodes to get a sparser tree. In the following, we observe that as we increase `_lambda` from 0 to 0.51, one of the branching nodes gets pruned and as a result, the in-sample accuracy drops to 92%." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "cell_id": "00016-9718d2e8-23aa-4565-b40a-373802ebc9ec", "deepnote_cell_height": 202, "deepnote_cell_type": "code", "deepnote_output_heights": [ 20 ], "deepnote_to_be_reexecuted": false, "execution_millis": 205, "execution_start": 1664770189871, "source_hash": "346b639f" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 60\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 274 rows, 209 columns and 642 nonzeros\n", "Model fingerprint: 0x3e3f455b\n", "Variable types: 196 continuous, 13 integer (13 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [5e-01, 5e-01]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Found heuristic solution: objective -0.0000000\n", "Presolve removed 250 rows and 187 columns\n", "Presolve time: 0.00s\n", "Presolved: 24 rows, 22 columns, 76 nonzeros\n", "Found heuristic solution: objective 3.9200000\n", "Variable types: 16 continuous, 6 integer (6 binary)\n", "\n", "Root relaxation: objective 5.105000e+00, 14 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 5.10500 0 2 3.92000 5.10500 30.2% - 0s\n", "H 0 0 4.8600000 5.10500 5.04% - 0s\n", "\n", "Explored 1 nodes (14 simplex iterations) in 0.00 seconds (0.00 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 3: 4.86 3.92 -0 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 4.860000000000e+00, best bound 4.860000000000e+00, gap 0.0000%\n" ] }, { "data": { "text/plain": [ "FlowOCT(solver=gurobi,depth=2,time_limit=60,num_threads=None,verbose=False)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stcl = FlowOCT(solver=\"gurobi\", depth=2, _lambda=0.51)\n", "stcl.fit(X, y)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "cell_id": "00017-b7172e7a-d5a1-471a-9f16-51ef1e101a81", "deepnote_cell_height": 125, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 899, "execution_start": 1664770192379, "source_hash": "f3e73368" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In-sample accuracy is 0.9230769230769231\n" ] } ], "source": [ "predictions = stcl.predict(X)\n", "print(f\"In-sample accuracy is {np.sum(predictions==y)/y.shape[0]}\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "allow_embed": false, "cell_id": "914dac0037c14b73a80834a07cc31dc5", "deepnote_cell_height": 534, "deepnote_cell_type": "code", "deepnote_output_heights": [ 406 ], "deepnote_to_be_reexecuted": false, "execution_millis": 419, "execution_start": 1664770193471, "source_hash": "702243f5" }, "outputs": [ { "data": { "image/png": "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xjS31u6s7oet5scTqTIVHhE5HSo87lbd76/eP3GM5vCIiIiI66nwiMhpmTVrFsYY1qxZU2ndwIED6du3LwDFxcU89dRTdOzYEX9/f2JjY3nwwQfJz//tCOji4mL++te/0rZtWwICAoiKiqJfv34sWrSo1l6PVPbYY49hjCExMZGhQ4cSEhJCXFwcf//73ykt/W16z+bNmxkxYgTh4eEEBgbSt29f5s2b52Bykd+o8IjIaRk2bBixsbFMnTq1wvJNmzbx/fffc/fddwNw44038vjjj3P99dczZ84cJkyYwJtvvskNN9xQfp/Jkyfz/PPPc//99/Pll1/y1ltvMXjwYDIyMmr1NcnRjRgxgkGDBvHpp58yfPhwJk6cyDvvvAPA7t276devH2vWrOGll15ixowZhIeHM3ToUL744guHk4sA1lrddNNNt1O9WWutnThxog0LC7M5OTmHF9mxY8fa8PBwm5ubaxcuXGgB+84779gjTZ8+3QJ21apV1lprhw4dakeMGGGPw+nX29Bu1lrP+wvYadOmVXgzunTpYocMGWKttfbBBx+03t7eNjExsXx9cXGxTUhIsD169ND7p5vjN43wiMhpu/POO8nNzeWDDz4AID8/n3feeYebb76ZwMBA5s2bh5+fH1dddRXFxcXlt4suugiAhQsXAtCrVy/mzp3Lo48+yqJFiygsLHTsNUllQ4cOrfB1ly5d2L59O+B5D/v27Uu7du3K13t7ezNq1ChWr17NwYMHazWryO+p8IjIaYuNjWXYsGG89tprAMycOZOMjAzuuusuANLS0igsLCQ4OBhfX9/yW3R0NADp6ekAPPLII0yaNInZs2fTv39/IiMjufXWW9m/XxfzrgsiIiIqfO3v718+BysjI4NmzZpVuk9MTAzWWjIzM2slo8ix+DgdQETc4Z577mHw4MGsWLGCqVOn0r9/fzp37gxAZGQkAQEB/PDDD0e9b2xsLAC+vr6MHz+e8ePHk5qayueff864cePIzc3lo48+qrXXIicvIiKC1NTUSstTU1MxxtC4cWMHUon8RoVHRKrFoEGD6NixI+PGjWPx4sW899575esuueQSJk+eTFZWFoMHD67S48XExHDHHXcwd+5c1q9fX1OxpZqcf/75TJkyheTkZOLj4wEoKSnho48+okePHoSFhTkbUBo8FR4RqTajR49mzJgxREVF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tcuqaA6PSM1R4TlCWMtAut7VkjWv7eD7sZs95+GJ9acou5jMxFx8g7w57/Fj/ystoLEvzfuHs+uHA3w7dhPR3UMpyi1l35qDePl60ah1IFm//jZcXVpQyqIJiQQ38ye8bSCBTfwoLbKkrc4mZ2c+Mb0bEdrSM9KU+HEa+9dlE9k5hKCmfngHeJG9PZ+0lQfxDfEm/qKoGv/+nEjnG2PZvz6HpNn7yPo1j8YJwWTvyCd1WRb+jXzoemfLEz+IyDF0imzKlAuGc/+CTzjn/Rf4nzadaRseRUZ+Liv27iTMz595V915zPvHBIdydUI3Zm5ZQ9/3/snguPZkFeSzYPtWAnx86NqkGWv37SnfPq+4iMEzXqNteCQ9opvTKrQx+SVFLNi+lU0ZaQxt04mOZSNNzy3/nu93JnFubDzxjSII8fVjQ/pevkreQmP/QG47s3eNf39OZMmuZN5evwyAnCLPKG/SgfQKF1j918XXOJJNpDao8PxO/EVRhLUKZOune9n/Sw57lmXhF+pNo3jPmZZPpPu9cQQ19Wf3okx+/WI/fmE+xPRuRKdRzVg2+dcK23oHeNP55lj2r88mY9MhCpZm4RPoTXCMH13vbknc4N8mIre+NArfEG8yt+SSvjEHW+KZXB1/aRPaDYsuH11ykl+YDwMmJ5RdPPQA6RsP4RfqTavBEbp4qFSL287szRmRTZmyciE/7NzGf5M2EBkYRJeoZtzapdcJ7//qkJHEN4pg1pa1TF3zE1GBwQxt04m/njOE6z+fXmHbYF8/Hu93Kd/vSOKnPSn8N2kDoX7+tG4UwT8HDecPZ5xdvu2d3foSHhDI8tQd/Lg7meLSUpqHNuLObn0Z07N/+eiSk5IO7Gf6xpUVlqXl5lRYpsIjbmastU5ncIQxxg77tIfTMaTMZ8NXYa117toYUqcYY2zuA087HUPKBE15WJ9PqfeqNvFDREREpB5T4RERERHXU+ERERER11PhEREREddT4RERERHXU+ERERER11PhEREREddrsOfh8fb3Si0ttE1PvKXUBi8/s7ekoDTG6RxSNwT6+KbmlxTr81lHBHj77M0rLtLnU+q1Blt4REREpOHQLi0RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxPRUeERERcT0VHhEREXE9FR4RERFxvf8P957ZIKfj17wAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(10, 5))\n", "stcl.plot_tree(ax=ax, fontsize=20)\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00020-f0f1660b-8b7f-452c-99b7-0f8f23ac89ce", "deepnote_cell_height": 108, "deepnote_cell_type": "markdown" }, "source": [ "## Example 2: Different Objective Functions\n", "\n", "In the following, we have a toy example with an imbalanced data, with the positive class being the minority class." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "cell_id": "00021-8827aefe-7e77-4cfc-a85e-7273ca7b30e5", "deepnote_cell_height": 454, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 0, "execution_start": 1665162085607, "source_hash": "a00d4bf4" }, "outputs": [], "source": [ "'''\n", " X2\n", " | | \n", " | |\n", " 1 + - - | -\n", " | | \n", " |---------------|--------------\n", " | |\n", " 0 - - - + | - - -\n", " | - - - - |\n", " |______0________|_______1_______X1\n", "'''\n", "X = np.array([[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],\n", " [1,0],[1,0],[1,0],\n", " [1,1],\n", " [0,1],[0,1],[0,1]])\n", "y = np.array([0,0,0,0,0,0,0,1,\n", " 0,0,0,\n", " 0,\n", " 1,0,0])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00022-f6484385-2f43-43ba-83dc-4bec33baee04", "deepnote_cell_height": 62, "deepnote_cell_type": "markdown" }, "source": [ "### Tree with classification accuracy objective" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "cell_id": "00023-e2f878ab-966d-46dd-920e-f0de749caf1f", "deepnote_cell_height": 822, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 54, "execution_start": 1665162091305, "source_hash": "4a372af8" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 60\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 314 rows, 237 columns and 734 nonzeros\n", "Model fingerprint: 0xa5b9a46b\n", "Variable types: 224 continuous, 13 integer (13 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Found heuristic solution: objective -0.0000000\n", "Presolve removed 269 rows and 203 columns\n", "Presolve time: 0.00s\n", "Presolved: 45 rows, 34 columns, 134 nonzeros\n", "Found heuristic solution: objective 13.0000000\n", "Variable types: 27 continuous, 7 integer (7 binary)\n", "\n", "Root relaxation: objective 1.400000e+01, 32 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 14.00000 0 1 13.00000 14.00000 7.69% - 0s\n", "\n", "Cutting planes:\n", " MIR: 1\n", " Flow cover: 1\n", "\n", "Explored 1 nodes (32 simplex iterations) in 0.00 seconds (0.00 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 2: 13 -0 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.300000000000e+01, best bound 1.300000000000e+01, gap 0.0000%\n" ] }, { "data": { "text/plain": [ "FlowOCT(solver=gurobi,depth=2,time_limit=60,num_threads=None,verbose=False)" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stcl_acc = FlowOCT(solver=\"gurobi\", depth=2, obj_mode=\"acc\")\n", "stcl_acc.fit(X, y)\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In-sample accuracy is 0.8666666666666667\n" ] } ], "source": [ "predictions = stcl_acc.predict(X)\n", "print(f\"In-sample accuracy is {np.sum(predictions==y)/y.shape[0]}\")" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "cell_id": "09c53f1895bb455e9794f92c03c45ae6", "deepnote_cell_height": 367, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 4, "execution_start": 1665162109464, "source_hash": "a6f4f17", "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#########node 1\n", "leaf 0\n", "#########node 2\n", "pruned\n", "#########node 3\n", "pruned\n", "#########node 4\n", "pruned\n", "#########node 5\n", "pruned\n", "#########node 6\n", "pruned\n", "#########node 7\n", "pruned\n" ] } ], "source": [ "stcl_acc.print_tree()" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "cell_id": "00025-de161a83-c201-4c2f-9a41-b2c0051b1834", "deepnote_cell_height": 534, "deepnote_cell_type": "code", "deepnote_output_heights": [ 406 ], "deepnote_to_be_reexecuted": false, "execution_millis": 611, "execution_start": 1665162118253, "source_hash": "84dfb7f3" }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(10, 5)) \n", "stcl_acc.plot_tree(ax=ax, fontsize=20)\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00026-9028f384-3bb7-4a5a-bf50-d97ddb984dd3", "deepnote_cell_height": 62, "deepnote_cell_type": "markdown" }, "source": [ "### Tree with Balanced Classification Accuracy Objective" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "cell_id": "00027-d4bdf0ac-d06e-4c2a-a8f1-e85669bce65a", "deepnote_cell_height": 840, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 41, "execution_start": 1665162304727, "source_hash": "ea7a2823" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 60\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 314 rows, 237 columns and 734 nonzeros\n", "Model fingerprint: 0x3bc6df12\n", "Variable types: 224 continuous, 13 integer (13 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [4e-02, 2e-01]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Found heuristic solution: objective -0.0000000\n", "Presolve removed 269 rows and 203 columns\n", "Presolve time: 0.01s\n", "Presolved: 45 rows, 34 columns, 134 nonzeros\n", "Found heuristic solution: objective 0.5000000\n", "Variable types: 27 continuous, 7 integer (7 binary)\n", "\n", "Root relaxation: objective 7.500000e-01, 31 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 0.75000 0 1 0.50000 0.75000 50.0% - 0s\n", "H 0 0 0.5288462 0.75000 41.8% - 0s\n", "H 0 0 0.6730769 0.75000 11.4% - 0s\n", " 0 0 0.67308 0 4 0.67308 0.67308 0.00% - 0s\n", "\n", "Cutting planes:\n", " MIR: 1\n", " Flow cover: 1\n", "\n", "Explored 1 nodes (36 simplex iterations) in 0.01 seconds (0.00 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 3: 0.673077 0.5 -0 \n", "No other solutions better than 0.673077\n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 6.730769230769e-01, best bound 6.730769230769e-01, gap 0.0000%\n", "In-sample accuracy is 0.8\n" ] } ], "source": [ "stcl_balance = FlowOCT(\n", " solver=\"gurobi\",\n", " depth=2,\n", " obj_mode=\"balance\",\n", " _lambda=0,\n", " verbose=False,\n", ")\n", "stcl_balance.fit(X, y)\n", "predictions = stcl_balance.predict(X)\n", "print(f\"In-sample accuracy is {np.sum(predictions==y)/y.shape[0]}\")" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "cell_id": "00029-fcfc9499-cd0f-45a2-8fbb-dd0be6e2e6b2", "deepnote_cell_height": 534, "deepnote_cell_type": "code", "deepnote_output_heights": [ 406 ], "deepnote_to_be_reexecuted": false, "execution_millis": 339, "execution_start": 1665162313454, "source_hash": "172a869a" }, "outputs": [ { "data": { "image/png": "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8bouqZngFPYXCQxqbkJgUPMFHpclIkEKPCIec85FOeduAhYDy4ETzGyut1XJ0TKzHWZ2LXAD8IRz7hXnXAuPyxKp9zSGR6R6df0l0TRnnwiuzHwvgcUhQ7Fuj44VkRpS4BGpngKPHBPn3Alm9l0onjoEzyniSwo8ItVT4JHaEIrjSMeKSA1pDI9INd544w2ccyxevLjKtiFDhjBw4EAASktLefjhh+nWrRvx8fGkp6dz2223UVhYWLF/aWkp9957L506dSIhIYG0tDQGDRrE/Pnz6+z9iLfuv/9+nHNkZGQwfPhwGjZsSPv27XnggQcoLy+v2G/lypWMHDmSlJQUEhMTGThwILNnz/awcpHIpsAjUo0RI0aQnp7OtGnTKt3/ww8/8O9//5ubbroJgKuuuooHH3yQK6+8kvfff5/f//73PPPMM/ziF7+oeMzkyZN5/PHHueWWW/jwww959tlnGTp0KDk5moxV34wcOZKzzjqLt99+m4suuoiJEyfy/PPPA7B161YGDRrE4sWL+ctf/sJrr71GSkoKw4cP54MPPvC4cpEIZWa66abbj99s4sSJlpycbHl5ebbfuHHjLCUlxfLz823evHkG2PPPP28HmjFjhgG2aNEiMzMbPny4jRw50qrh9fvVLUTHkVngWAJs+vTpdqBevXrZsGHDzMzstttus+joaMvIyKjYXlpaal26dLG+ffse+DCv35NuukXMTT08IjVw4403kp+fz8svvwxAYWEhzz//PNdccw2JiYnMnj2buLg4Lr30UkpLSytu55xzDgDz5s0DoH///syaNYt77rmH+fPnU1xc7Nl7Em8NHz680t+9evVi48aNQOB4GThwIJ07d67YHh0dzahRo/juu+/Yu3dvndYq4gcKPCI1kJ6ezogRI5g6dSoAr7/+Ojk5OYwePRqA7OxsiouLSUpKIjY2tuLWvHlzAHbu3AnA3XffzaRJk5g5cyZnnHEGqampXHfddezYscObNyaeadq0aaW/4+PjK8Z75eTk0KpVqyqPadmyJWbGrl276qRGET+J8boAkUhx8803M3ToUBYsWMC0adM444wz6NGjBwCpqakkJCTw2WefHfKx6enpAMTGxjJhwgQmTJhAZmYm7733HuPHjyc/P59XX321zt6LhLemTZuSmZlZ5f7MzEycczRp0sSDqkQimwKPSA2dddZZdOvW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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(10, 5)) \n", "stcl_balance.plot_tree(ax=ax, fontsize=20)\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "865b4df0febc481c969fa433a07f1bce", "deepnote_cell_height": 96, "deepnote_cell_type": "markdown", "tags": [] }, "source": [ "As we can see, when we maximize accuracy, i.e., when `obj_mode = 'acc'`, the optimal tree is just a single node without branching, predicting the majority class for the whole dataset. But when we change the objective mode to balanced accuracy, we account for the minority class by sacrificing the overal accuracy." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "00030-39a05aae-4523-463e-9663-653630a031c9", "deepnote_cell_height": 130, "deepnote_cell_type": "markdown", "deepnote_to_be_reexecuted": false, "execution_millis": 4, "execution_start": 1652396285618, "source_hash": "55e6949" }, "source": [ "## Example 3: UCI Data Example\n", "\n", "In this section, we fit a tree of depth 3 on a real world dataset called the [`balance` dataset](https://archive.ics.uci.edu/ml/datasets/Balance+Scale) from the UCI Machine Learning repository. " ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "cell_id": "ae66c5fdc7fe4dee9509176ae7738b03", "deepnote_cell_height": 112, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 9, "execution_start": 1663084101706, "source_hash": "459cf272", "tags": [] }, "outputs": [], "source": [ "import pandas as pd\n", "from sklearn.model_selection import train_test_split\n", "from odtlearn.datasets import balance_scale_data" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "cell_id": "e586d484fc394bd6ae9e1c9c7423ad77", "deepnote_cell_height": 269, "deepnote_cell_type": "code", "deepnote_output_heights": [ null, 77 ], "deepnote_to_be_reexecuted": false, "execution_millis": 4, "execution_start": 1663084101759, "source_hash": "f97169ac", "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "shape(625, 21)\n" ] }, { "data": { "text/plain": [ "Index(['V2.1', 'V2.2', 'V2.3', 'V2.4', 'V2.5', 'V3.1', 'V3.2', 'V3.3', 'V3.4',\n", " 'V3.5', 'V4.1', 'V4.2', 'V4.3', 'V4.4', 'V4.5', 'V5.1', 'V5.2', 'V5.3',\n", " 'V5.4', 'V5.5', 'target'],\n", " dtype='object')" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# read data\n", "data = balance_scale_data()\n", "print(f\"shape{data.shape}\")\n", "data.columns" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "cell_id": "80dbfabf721c4008b103b519b2323c01", "deepnote_cell_height": 148, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 0, "execution_start": 1663084101760, "source_hash": "5e03a259", "tags": [] }, "outputs": [], "source": [ "y = data.pop(\"target\")\n", "\n", "X_train, X_test, y_train, y_test = train_test_split(\n", " data, y, test_size=0.33, random_state=42\n", ")" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "cell_id": "d4144975f0c94c40853a81dff20c53fa", "deepnote_cell_height": 256, "deepnote_cell_type": "code", "deepnote_output_heights": [ 20 ], "deepnote_to_be_reexecuted": false, "execution_millis": 60948, "execution_start": 1663084101761, "source_hash": "a44a256e", "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 200\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter LazyConstraints to value 1\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 30 rows, 618 columns and 249 nonzeros\n", "Model fingerprint: 0xaeff5467\n", "Variable types: 463 continuous, 155 integer (155 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Presolve removed 8 rows and 8 columns\n", "Presolve time: 0.00s\n", "Presolved: 22 rows, 610 columns, 233 nonzeros\n", "Variable types: 463 continuous, 147 integer (147 binary)\n", "Root relaxation presolved: 412 rows, 610 columns, 7100 nonzeros\n", "\n", "Concurrent LP optimizer: primal simplex, dual simplex, and barrier\n", "Showing barrier log only...\n", "\n", "Root barrier log...\n", "\n", "Ordering time: 0.00s\n", "\n", "Barrier performed 0 iterations in 0.18 seconds (0.00 work units)\n", "Barrier solve interrupted - model solved by another algorithm\n", "\n", "\n", "Solved with dual simplex\n", "\n", "Root relaxation: objective 4.180000e+02, 77 iterations, 0.01 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 418.00000 0 4 - 418.00000 - - 0s\n", "H 0 0 269.0000000 418.00000 55.4% - 0s\n", " 0 0 418.00000 0 4 269.00000 418.00000 55.4% - 0s\n", " 0 2 413.60000 0 9 269.00000 413.60000 53.8% - 0s\n", "H 308 294 272.0000000 413.60000 52.1% 75.5 1s\n", "H 483 460 274.0000000 413.60000 50.9% 75.6 1s\n", "* 533 475 54 290.0000000 413.60000 42.6% 73.6 1s\n", " 1143 887 cutoff 64 290.00000 412.40000 42.2% 78.6 5s\n", "H 1310 970 291.0000000 412.40000 41.7% 75.5 5s\n", " 1556 1132 316.00000 35 26 291.00000 409.65561 40.8% 70.5 10s\n", " 1629 1180 371.73684 22 25 291.00000 403.03327 38.5% 67.3 15s\n", " 1797 1290 367.57918 36 10 291.00000 402.21668 38.2% 92.8 20s\n", "H 2163 1398 293.0000000 400.54472 36.7% 92.9 21s\n", "* 2375 1361 111 296.0000000 399.64465 35.0% 91.6 22s\n", "H 3419 1561 299.0000000 398.14472 33.2% 86.5 24s\n", " 3861 1733 358.57143 67 20 299.00000 398.14472 33.2% 87.2 25s\n", "H 4454 1024 312.0000000 398.14472 27.6% 85.7 25s\n", " 8785 2721 cutoff 62 312.00000 358.67679 15.0% 82.5 30s\n", " 16715 6109 313.50000 67 16 312.00000 338.60887 8.53% 69.7 35s\n", "H17827 5595 314.0000000 338.16497 7.70% 67.8 35s\n", " 26793 9027 315.00000 77 8 314.00000 330.38947 5.22% 59.2 40s\n", "H31789 9084 315.0000000 329.54167 4.62% 57.5 43s\n", " 33926 9710 318.00000 71 8 315.00000 328.75000 4.37% 56.7 45s\n", "H35037 8771 316.0000000 328.02174 3.80% 56.5 45s\n", "H36500 6760 318.0000000 327.50000 2.99% 56.0 46s\n", " 42743 6716 322.50000 59 12 318.00000 325.00000 2.20% 54.1 50s\n", " 54532 4635 cutoff 48 318.00000 321.00000 0.94% 50.5 55s\n", " 65931 1611 cutoff 74 318.00000 319.48148 0.47% 47.7 60s\n", "\n", "Cutting planes:\n", " MIR: 120\n", " Flow cover: 193\n", " Lazy constraints: 236\n", "\n", "Explored 70775 nodes (3292092 simplex iterations) in 61.92 seconds (141.79 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 10: 318 316 315 ... 290\n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 3.180000000000e+02, best bound 3.180000000000e+02, gap 0.0000%\n", "\n", "User-callback calls 150674, time in user-callback 1.85 sec\n" ] }, { "data": { "text/plain": [ "BendersOCT(solver=gurobi,depth=3,time_limit=200,num_threads=None,verbose=True)" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stcl = BendersOCT(solver=\"gurobi\", depth=3, time_limit=200, obj_mode=\"acc\", verbose=True)\n", "\n", "stcl.fit(X_train, y_train)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "cell_id": "3d2dd737745047ee8dc047326a93975b", "deepnote_cell_height": 687, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 907, "execution_start": 1663084161863, "source_hash": "2f43d041", "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#########node 1\n", "branch on V3.2\n", "#########node 2\n", "branch on V3.1\n", "#########node 3\n", "branch on V5.1\n", "#########node 4\n", "branch on V2.1\n", "#########node 5\n", "branch on V5.1\n", "#########node 6\n", "branch on V4.1\n", "#########node 7\n", "branch on V2.1\n", "#########node 8\n", "leaf 2\n", "#########node 9\n", "leaf 3\n", "#########node 10\n", "leaf 3\n", "#########node 11\n", "leaf 2\n", "#########node 12\n", "leaf 3\n", "#########node 13\n", "leaf 2\n", "#########node 14\n", "leaf 2\n", "#########node 15\n", "leaf 3\n" ] } ], "source": [ "stcl.print_tree()" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "cell_id": "2e6ec3df59ad4d34894820b67bffa4a1", "deepnote_cell_height": 548.234375, "deepnote_cell_type": "code", "deepnote_output_heights": [ 420.234375 ], "deepnote_to_be_reexecuted": false, "execution_millis": 926, "execution_start": 1663084161864, "source_hash": "2b611b71", "tags": [] }, "outputs": [ { "data": { "image/png": "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6623HldccQVbbrklhxxyCGeddRYAb775JmuuuSZDhw7lhBNO4OKLL2aOOeZgwIABXHfddYWTS5KakT1qJEmtLaFyZPvvf/87b775JrPMMgsA++yzD2eccQZvvvkmDz74IGuvvTZnnXUWO+2008Qnn3feeey444488sgjLL/88my22WbMNNNMXH755VPan30kJE0cdw477DBOP/10dt1114l3LrPMMswzzzzceOON7Lfffhx77LE888wzLLLIIgB88cUXLLXUUswyyyw8/PDDE57m2CJJahOeUSNJahM//elPGTlyJBdccAEAo0ePnliU6dKlC9dffz0zzTQT22yzDePGjZu4bbjhhgDcfvvtAKyyyioMHjyYgw46iDvvvJMxY8YUe0+S6sOAAQMm+XefPn149dVXgcrY0rdv34lFGoD27duz/fbb8+ijj/Lxxx+3aVZJkizUSJLaRO/evRk4cCAnn3wyAJdccgkjRoxgt912A+Cdd95hzJgxzDLLLHTs2HHiNtdccwHw/vvvA3DggQdy2GGHcdVVV7HWWmvRo0cPdt11V957770yb0xSzevevfsk/+7UqdPE3lcjRoxgnnnm+cpzevXqRWbywQcftElGSZIm6FA6gCSpeeyxxx7079+fhx56iFNOOYW11lqLpZZaCoAePXrQuXNn7rjjjsk+t3fv3gB07NiR/fffn/3335/hw4dzzTXXsM8++zBy5EguuuiiNnsvkhpD9+7dGT58+FduHz58OBFBt27dCqSSJDUzCzWSpDaz3nrrscQSS7DPPvtw1113cd555028b+ONN+boo4/mo48+on///lP1er169eLHP/4xgwcP5oknnmit2JIa2DrrrMOxxx7Lyy+/zAILLABUetRcdNFFrLDCCnTt2rVsQElS07FQI0lqU7vvvjt77bUXPXv2ZOutt554e79+/dh+++3ZZptt2GeffVh11VVp164dL7/8MoMHD+boo49mscUWY+DAgSy33HKsuOKKdOvWjUceeYTrr79+4iVUkjQt9t57b84880w22GADDjvsMLp27cpJJ53Ec889x7XXXls6niSpCVmokSS1qW233Za99tqLXXbZhU6dOk1y37nnnsvxxx/P6aefzpFHHkmnTp1YYIEF2GijjZh77rkBWHvttbnkkks48cQTGTlyJPPNNx+/+c1vOOigg0q8HUl1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0UYbZbt27XLw4MH5JaXfk5ubm5tb/W2Z2aZzmtLv162Vfn6cz7i5td1WPICbW41umVn5g9OhQ4c89dRTMzNz1KhR2b1799xzzz0zM/PAAw/MmWaaKT/77LMcO3bsxO2dd95JIP/xj39kZuahhx6anTp1ygMPPDDvuOOO/Pzzz3MySr9nt1b4GZowsZkwiZmgT58+ucEGG2Rm5r777pvt27fPYcOGTbx/3Lhxudhii+UKK6zw5aeVfk9ubm5ubvW3ZWabzmlKv1+3Vvj5cT7j5ta2m5c+SV+jd+/eDBw4kJNPPhmASy65hBEjRrDbbrsB8M477zBmzBhmmWUWOnbsOHGba665AHj//fcBOPDAAznssMO46qqrWGuttejRowe77ror7733Xpk3pjY3YMCASf7dp08fXn31VQBuv/12+vbtyyKLLDLx/vbt27P99tvz6KOP8vHHH7dpVklS43FOo5bgfEZqGx1KB5Bq3R577EH//v156KGHOOWUU1hrrbVYaqmlAOjRowedO3fmjjvumOxze/fuDUDHjh3Zf//92X///Rk+fDjXXHMN++yzDyNHjuSiiy5qs/eicrp37z7Jvzt16jSxOeOIESNYYYUVvvKcXr16kZl88MEHdO3atU1ySpIal3MazSjnM1LbsFAjfYP11luPJZZYgn322Ye77rqL8847b+J9G2+8MUcffTQfffQR/fv3n6rX69WrFz/+8Y8ZPHgwTzzxRGvFVh3p3r07w4cP/8rtw4cPJyLo1q1bgVSSpEbjnEatyfmM1HIs1EhTYffdd2evvfaiZ8+ebL311hNv79evH9tvvz3bbLMN++yzD6uuuirt2rXj5ZdfZvDgwRx99NEstthiDBw4kOWWW44VV1yRbt268cgjj3D99ddPPN1YzW2dddbh2GOP5eWXX2aBBRYA4IsvvuCiiy5ihRVW8OiTJKnFOKdRa3E+I7UcCzXSVNh2223Za6+92GWXXejUqdMk95177rkcf/zxnH766Rx55JF06tSJBRZYgI022oi5554bgLXXXptLLrmEE088kZEjRzLffPPxm9/8hoMOOqjE21GN2XvvvTnzzDPZYIMNOOyww+jatSsnnXQSzz33HNdee23peJKkBuKcRq3F+YzUcizUSFPhmmuuISIme7SoXbt27LXXXuy1115TfP6+++7Lvvvu25oRVcd69+7N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PLh0ltYUEZ2A54DvZeY9pfNIzSQi9gA2z8xNSmdpbRFxNXBTZh5XOoumj4WaOhYRfwNmysxflM7S2qqXXjwA/CkzLy2dR2oWEbE98Cugb6OeIvxlEXEy8FFm7l86i9QsImIJ4A4qR38/LByn1UXEj4AdMnO90lmkZhERM1O59HCLzHyodJ7WFhHLA9dRuaT7s8JxNB0s1NSpiPg2lcuBls7Mt0rnaQsRsTHwNypNBl1yTmpl1YZ7TwF7ZObNpfO0herYOhTo0yxjq1RaRFwEPJqZR5XO0ha+NLbunpm3lM4jNYOI2A/4TmZuXTpLW6mOrY9k5p9KZ9G0s1BTp6pHfT/OzN+UztJWqmfV3A6cmplnl84jNbrqUd8dgfWa4WyaCapnK3bMzF+WziI1umY96ls9W3EvKl8cm2Z8lUqIiK5UzqZZLzOfLJ2nrTTb2YqNxkJN2yvxgUeBfbaE1vis6vWzkKZVW4819fq75TgjTT/HmanjOCNNP787TR3HmQbTrnQASZIkSZIkVViokSRJkiRJqhEWagq47LLLiAiGDh36lfv69etH3759ARg3bhxHHXUUSyyxBJ06daJ3797su+++jB49euLjx40bx8EHH8zCCy9M586d6dmzJ2uuuSZ33nlnm72f1nbooYcSEQwbNowBAwYw66yzMv/883P44Yczfvz/r9T97LPPMmjQIOaYYw66dOlC3759uf766wsml8pxnJk2jjPS9HGsmXqOM9L0cZyZeo4zDSQz3dp2y7Fjx2bv3r1z9913zy97+umnE8gzzjgjMzO32267nHnmmfOwww7Lm266KY877ricffbZc6uttpr4nCOOOCJnmWWWPPbYY/O2227Lq666Kn//+9/nlVde+eWXLv2ep/uzysw85JBDEsill146jznmmLzppptyzz33TCBPP/30zMx84403smfPnrngggvmOeeck1dddVVutNFG2a5duxw8eHAjfBZubtO0Oc5M9ZaZjjNubtO5tfWcpvT7ne7PKdNxxs1tOje/O03l55TpONNIW/EATbhlZuWXqGvXrvnpp59OuCn33nvvnGOOOXLkyJF5++23J5BnnXVWftm5556bQD7yyCOZmTlgwIAcNGhQfoPS73mGP6svDy4T9OnTJzfYYIPMzNx3332zffv2OWzYsIn3jxs3LhdbbLFcYYUVGuGzcHOb1s1xZio/pwmfleOMm9s0b5nZpmNN6fc7w5+T44yb2zRvmemcZlo+J8eZxti89KmQn/70p4wcOZILLrgAgNGjR3PWWWex00470aVLF66//npmmmkmttlmG8aNGzdx23DDDQG4/fbbAVhllVUYPHgwBx10EHfeeSdjxowp9p5a24ABAyb5d58+fXj11VeByufRt29fFllkkYn3t2/fnu23355HH32Ujz/+uE2zSrXAcWbaOc5I086xZto4zkjTznFm2jjO1D8LNYX07t2bgQMHcvLJJwNwySWXMGLECHbbbTcA3nnnHcaMGcMss8xCx44dJ25zzTUXAO+//z4ABx54IIcddhhXXXUVa621Fj169GDXXXflvffeK/PGWlH37t0n+XenTp0mXnM6YsQI5plnnq88p1evXmQmH3zwQZtklGqJ48y0c5yRpp1jzbRxnJGmnePMtHGcqX8dSgdoZnvssQf9+/fnoYce4pRTTmGttdZiqaWWAqBHjx507tyZO+64Y7LP7d27NwAdO3Zk//33Z//992f48OFcc8017LPPPowcOZKLLrqozd5Lad27d2f48OFfuX348OFEBN26dSuQSirPcablOM5IU+ZY0zIcZ6Qpc5xpGY4zdaL0tVdNuE1iiSWWyLXXXjuBPO+88ybefuuttyaQN9988/8+5RsNGjQol1pqqS/fVPo9z9BnNeFay7Fjx07yPnfeeeecf/75MzNzv/32yw4dOuRLL7008f5x48blEksskSuuuGIjfBZubtO6TeQ4882fk+OMm9t0bZNog7Gm9Pudoc/JccbNbbq2STin+frPyXGmcTbPqCls9913Z6+99qJnz55svfXWE2/v168f22+/Pdtssw377LMPq666Ku3atePll19m8ODBHH300Sy22GIMHDiQ5ZZbjhVXXJFu3brxyCOPcP311088DbBZ7L333px55plssMEGHHbYYXTt2pWTTjqJ5557jmuvvbZ0PKkox5mW4TgjfT3HmhnnOCN9PceZGec4UydKV4qacJvEm2++mUDut99+/3tXfvHFF3nsscfmsssum506dcquXbvmsssum7/+9a/zww8/zMzMY445JldbbbXs3r17du7cORdbbLE85JBDcsyYMV9+qdLveYY+q6mpDGdmPvPMMzlw4MDs2rVrdurUKVdbbbW87rrr/vdjLf2e3NzaapvIceab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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(20, 10))\n", "stcl.plot_tree(ax=ax, fontsize=20, color_dict={\"node\": None, \"leaves\": []})\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "cell_id": "bea1c5b861094c5fa731c1b08beb4bd2", "deepnote_cell_height": 125, "deepnote_cell_type": "code", "deepnote_to_be_reexecuted": false, "execution_millis": 371, "execution_start": 1663084162420, "source_hash": "73804030", "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The out-of-sample accuracy is 0.6859903381642513\n" ] } ], "source": [ "test_pred = stcl.predict(X_test)\n", "print('The out-of-sample accuracy is {}'.format(np.sum(test_pred==y_test)/y_test.shape[0]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example 4: User-defined Weights\n", "\n", "In this example, we'll demonstrate how to use user-defined weights with FlowOCT and BendersOCT. We'll use a small binary classification dataset and show how user-defined weights can affect the learned tree.\n", "\n", "First, let's create our small binary classification dataset:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dataset shape: (20, 5)\n", "Class distribution: [ 6 14]\n" ] } ], "source": [ "np.random.seed(42)\n", "X = np.random.randint(0, 2, size=(20, 5))\n", "y = np.random.randint(0, 2, size=20)\n", "\n", "print(\"Dataset shape:\", X.shape)\n", "print(\"Class distribution:\", np.bincount(y))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's create weights that heavily favor class 1:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Weight distribution:\n", "Class 0: 1.0\n", "Class 1: 10.0\n" ] } ], "source": [ "weights = np.ones_like(y)\n", "weights[y == 1] = 10\n", "\n", "print(\"Weight distribution:\")\n", "print(\"Class 0:\", weights[y == 0].mean())\n", "print(\"Class 1:\", weights[y == 1].mean())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### FlowOCT with User-defined Weights\n", "Let's fit a FlowOCT model with user-defined weights and compare it to a model without the accuracy objective:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 10\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 414 rows, 316 columns and 1153 nonzeros\n", "Model fingerprint: 0x1ad65f5a\n", "Variable types: 294 continuous, 22 integer (22 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Found heuristic solution: objective -0.0000000\n", "Presolve removed 205 rows and 186 columns\n", "Presolve time: 0.00s\n", "Presolved: 209 rows, 130 columns, 660 nonzeros\n", "Found heuristic solution: objective 14.0000000\n", "Variable types: 112 continuous, 18 integer (18 binary)\n", "\n", "Root relaxation: objective 1.966667e+01, 166 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 19.66667 0 7 14.00000 19.66667 40.5% - 0s\n", "H 0 0 16.0000000 19.66667 22.9% - 0s\n", "H 0 0 17.0000000 19.00000 11.8% - 0s\n", " 0 0 18.50000 0 9 17.00000 18.50000 8.82% - 0s\n", "\n", "Cutting planes:\n", " Gomory: 13\n", " MIR: 6\n", " RLT: 20\n", "\n", "Explored 1 nodes (198 simplex iterations) in 0.01 seconds (0.01 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 4: 17 16 14 -0 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.700000000000e+01, best bound 1.700000000000e+01, gap 0.0000%\n", "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 10\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 414 rows, 316 columns and 1153 nonzeros\n", "Model fingerprint: 0xf6c20781\n", "Variable types: 294 continuous, 22 integer (22 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+01]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Found heuristic solution: objective -0.0000000\n", "Presolve removed 205 rows and 186 columns\n", "Presolve time: 0.00s\n", "Presolved: 209 rows, 130 columns, 660 nonzeros\n", "Found heuristic solution: objective 140.0000000\n", "Variable types: 112 continuous, 18 integer (18 binary)\n", "\n", "Root relaxation: objective 1.456667e+02, 173 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 145.66667 0 7 140.00000 145.66667 4.05% - 0s\n", "H 0 0 143.0000000 144.66667 1.17% - 0s\n", " 0 0 144.00000 0 11 143.00000 144.00000 0.70% - 0s\n", " 0 0 143.00000 0 6 143.00000 143.00000 0.00% - 0s\n", "\n", "Cutting planes:\n", " Gomory: 1\n", " MIR: 1\n", " RLT: 7\n", "\n", "Explored 1 nodes (233 simplex iterations) in 0.01 seconds (0.01 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 3: 143 140 -0 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.430000000000e+02, best bound 1.430000000000e+02, gap 0.0000%\n", "Default FlowOCT predictions: [1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 0]\n", "Custom weights FlowOCT predictions: [1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 0]\n", "\n", "Default FlowOCT accuracy: 0.85\n", "Custom weights FlowOCT accuracy: 0.85\n", "Custom weights FlowOCT weighted accuracy: 0.9794520547945206\n" ] } ], "source": [ "# FlowOCT without custom weights\n", "flow_oct_default = FlowOCT(solver=\"gurobi\", obj_mode=\"acc\", depth=2, time_limit=10)\n", "flow_oct_default.fit(X, y)\n", "\n", "# FlowOCT with custom weights\n", "flow_oct_custom = FlowOCT(solver=\"gurobi\", obj_mode=\"weighted\", depth=2, time_limit=10)\n", "flow_oct_custom.fit(X, y, weights=weights)\n", "\n", "print(\"Default FlowOCT predictions:\", flow_oct_default.predict(X))\n", "print(\"User-defined weights FlowOCT predictions:\", flow_oct_custom.predict(X))\n", "\n", "print(\"Default FlowOCT accuracy:\", (flow_oct_default.predict(X) == y).mean())\n", "print(\"User-defined weights FlowOCT accuracy:\", (flow_oct_custom.predict(X) == y).mean())\n", "print(\"User-defined weights FlowOCT weighted accuracy:\", np.average(flow_oct_custom.predict(X) == y, weights=weights))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's visualize both trees:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "\n", "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))\n", "\n", "flow_oct_default.plot_tree(ax=ax1, fontsize=10)\n", "ax1.set_title(\"Default FlowOCT\")\n", "\n", "flow_oct_custom.plot_tree(ax=ax2, fontsize=10)\n", "ax2.set_title(\"User-defined Weights FlowOCT\")\n", "\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### BendersOCT with User-defined Weights\n", "Now let's do the same with BendersOCT:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 10\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter LazyConstraints to value 1\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 14 rows, 56 columns and 53 nonzeros\n", "Model fingerprint: 0x28902962\n", "Variable types: 34 continuous, 22 integer (22 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Presolve removed 4 rows and 4 columns\n", "Presolve time: 0.00s\n", "Presolved: 10 rows, 52 columns, 45 nonzeros\n", "Variable types: 34 continuous, 18 integer (18 binary)\n", "Root relaxation presolved: 22 rows, 50 columns, 140 nonzeros\n", "\n", "\n", "Root relaxation: objective 2.000000e+01, 2 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 20.00000 0 - - 20.00000 - - 0s\n", " 0 0 20.00000 0 - - 20.00000 - - 0s\n", " 0 0 20.00000 0 - - 20.00000 - - 0s\n", " 0 0 20.00000 0 7 - 20.00000 - - 0s\n", "H 0 0 14.0000000 20.00000 42.9% - 0s\n", "H 0 0 16.0000000 20.00000 25.0% - 0s\n", " 0 0 19.50000 0 2 16.00000 19.50000 21.9% - 0s\n", " 0 0 19.26563 0 9 16.00000 19.26563 20.4% - 0s\n", "H 0 0 17.0000000 19.26563 13.3% - 0s\n", " 0 0 19.00000 0 8 17.00000 19.00000 11.8% - 0s\n", " 0 0 18.96429 0 9 17.00000 18.96429 11.6% - 0s\n", " 0 0 18.95833 0 9 17.00000 18.95833 11.5% - 0s\n", " 0 0 18.85000 0 9 17.00000 18.85000 10.9% - 0s\n", " 0 0 18.85000 0 9 17.00000 18.85000 10.9% - 0s\n", " 0 0 18.76563 0 11 17.00000 18.76563 10.4% - 0s\n", " 0 0 18.74194 0 10 17.00000 18.74194 10.2% - 0s\n", " 0 0 18.73913 0 9 17.00000 18.73913 10.2% - 0s\n", " 0 0 18.59091 0 9 17.00000 18.59091 9.36% - 0s\n", " 0 0 18.50000 0 9 17.00000 18.50000 8.82% - 0s\n", " 0 0 18.50000 0 9 17.00000 18.50000 8.82% - 0s\n", " 0 0 18.37500 0 8 17.00000 18.37500 8.09% - 0s\n", " 0 0 18.33333 0 8 17.00000 18.33333 7.84% - 0s\n", " 0 0 18.33333 0 9 17.00000 18.33333 7.84% - 0s\n", " 0 0 18.31250 0 7 17.00000 18.31250 7.72% - 0s\n", " 0 0 18.30000 0 7 17.00000 18.30000 7.65% - 0s\n", " 0 0 18.16667 0 7 17.00000 18.16667 6.86% - 0s\n", " 0 0 18.14706 0 8 17.00000 18.14706 6.75% - 0s\n", " 0 0 18.09524 0 10 17.00000 18.09524 6.44% - 0s\n", " 0 0 18.07059 0 10 17.00000 18.07059 6.30% - 0s\n", " 0 0 18.03478 0 10 17.00000 18.03478 6.09% - 0s\n", " 0 0 18.01765 0 11 17.00000 18.01765 5.99% - 0s\n", " 0 0 18.01333 0 11 17.00000 18.01333 5.96% - 0s\n", " 0 0 18.00532 0 12 17.00000 18.00532 5.91% - 0s\n", " 0 0 18.00463 0 12 17.00000 18.00463 5.91% - 0s\n", " 0 0 17.95833 0 9 17.00000 17.95833 5.64% - 0s\n", " 0 0 17.91304 0 8 17.00000 17.91304 5.37% - 0s\n", " 0 0 17.91304 0 8 17.00000 17.91304 5.37% - 0s\n", " 0 0 17.90909 0 8 17.00000 17.90909 5.35% - 0s\n", " 0 0 17.90909 0 11 17.00000 17.90909 5.35% - 0s\n", " 0 0 17.89873 0 11 17.00000 17.89873 5.29% - 0s\n", " 0 0 17.89873 0 10 17.00000 17.89873 5.29% - 0s\n", " 0 2 17.89873 0 10 17.00000 17.89873 5.29% - 0s\n", "\n", "Cutting planes:\n", " Gomory: 1\n", " MIR: 11\n", " Flow cover: 5\n", " Lazy constraints: 46\n", "\n", "Explored 16 nodes (312 simplex iterations) in 0.05 seconds (0.02 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 3: 17 16 14 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.700000000000e+01, best bound 1.700000000000e+01, gap 0.0000%\n", "\n", "User-callback calls 366, time in user-callback 0.02 sec\n", "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-06-28\n", "Set parameter TimeLimit to value 10\n", "Set parameter NodeLimit to value 1073741824\n", "Set parameter SolutionLimit to value 1073741824\n", "Set parameter LazyConstraints to value 1\n", "Set parameter IntFeasTol to value 1e-06\n", "Set parameter Method to value 3\n", "Gurobi Optimizer version 10.0.2 build v10.0.2rc0 (mac64[arm])\n", "\n", "CPU model: Apple M1 Pro\n", "Thread count: 8 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 14 rows, 56 columns and 53 nonzeros\n", "Model fingerprint: 0x75b5cba0\n", "Variable types: 34 continuous, 22 integer (22 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+01]\n", " Bounds range [1e+00, 1e+00]\n", " RHS range [1e+00, 1e+00]\n", "Presolve removed 4 rows and 4 columns\n", "Presolve time: 0.00s\n", "Presolved: 10 rows, 52 columns, 45 nonzeros\n", "Variable types: 34 continuous, 18 integer (18 binary)\n", "Root relaxation presolved: 22 rows, 50 columns, 140 nonzeros\n", "\n", "\n", "Root relaxation: objective 1.460000e+02, 2 iterations, 0.00 seconds (0.00 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 146.00000 0 - - 146.00000 - - 0s\n", " 0 0 146.00000 0 - - 146.00000 - - 0s\n", " 0 0 146.00000 0 - - 146.00000 - - 0s\n", " 0 0 146.00000 0 7 - 146.00000 - - 0s\n", "H 0 0 140.0000000 146.00000 4.29% - 0s\n", " 0 0 145.50000 0 4 140.00000 145.50000 3.93% - 0s\n", " 0 0 145.37500 0 7 140.00000 145.37500 3.84% - 0s\n", "H 0 0 143.0000000 145.37500 1.66% - 0s\n", " 0 0 144.88542 0 10 143.00000 144.88542 1.32% - 0s\n", " 0 0 144.88194 0 10 143.00000 144.88194 1.32% - 0s\n", " 0 0 144.33333 0 7 143.00000 144.33333 0.93% - 0s\n", " 0 0 144.30000 0 7 143.00000 144.30000 0.91% - 0s\n", " 0 0 144.16667 0 7 143.00000 144.16667 0.82% - 0s\n", " 0 0 144.12500 0 9 143.00000 144.12500 0.79% - 0s\n", " 0 0 144.12500 0 9 143.00000 144.12500 0.79% - 0s\n", " 0 0 144.08333 0 11 143.00000 144.08333 0.76% - 0s\n", " 0 0 144.08036 0 11 143.00000 144.08036 0.76% - 0s\n", " 0 0 144.08036 0 11 143.00000 144.08036 0.76% - 0s\n", " 0 0 144.02737 0 10 143.00000 144.02737 0.72% - 0s\n", " 0 0 144.02737 0 11 143.00000 144.02737 0.72% - 0s\n", " 0 0 144.02632 0 11 143.00000 144.02632 0.72% - 0s\n", " 0 0 144.02632 0 10 143.00000 144.02632 0.72% - 0s\n", " 0 2 144.02632 0 9 143.00000 144.02632 0.72% - 0s\n", "\n", "Cutting planes:\n", " Gomory: 1\n", " MIR: 3\n", " Flow cover: 9\n", " Lazy constraints: 47\n", "\n", "Explored 14 nodes (157 simplex iterations) in 0.03 seconds (0.01 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 2: 143 140 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", "Best objective 1.430000000000e+02, best bound 1.430000000000e+02, gap 0.0000%\n", "Default BendersOCT predictions: [1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 0]\n", "Custom weights BendersOCT predictions: [1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 0]\n", "\n", "Default BendersOCT accuracy: 0.85\n", "Custom weights BendersOCT accuracy: 0.85\n", "\n", "User-callback calls 283, time in user-callback 0.01 sec\n", "Custom weights BendersOCT weighted accuracy: 0.9794520547945206\n" ] } ], "source": [ "# BendersOCT without custom weights\n", "benders_oct_default = BendersOCT(solver=\"gurobi\", obj_mode=\"acc\", depth=2, time_limit=10)\n", "benders_oct_default.fit(X, y)\n", "\n", "# BendersOCT with custom weights\n", "benders_oct_custom = BendersOCT(solver=\"gurobi\", obj_mode=\"weighted\", depth=2, time_limit=10, verbose=False)\n", "benders_oct_custom.fit(X, y, weights=weights)\n", "\n", "print(\"Default BendersOCT predictions:\", benders_oct_default.predict(X))\n", "print(\"User-defined weights BendersOCT predictions:\", benders_oct_custom.predict(X))\n", "\n", "print(\"Default BendersOCT accuracy:\", (benders_oct_default.predict(X) == y).mean())\n", "print(\"User-defined weights BendersOCT accuracy:\", (benders_oct_custom.predict(X) == y).mean())\n", "print(\"User-defined weights BendersOCT weighted accuracy:\", np.average(benders_oct_custom.predict(X) == y, weights=weights))" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "image/png": "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a1yv/rTFK5bX7nbQAtSobr3pi5Yvaxc7Dp3f3KrbsM60lUu95M5vnQY2fcWSldHPr9pv/uhc55bOb26pL84ttd+qZT1BFhEREREpZppiISIiIiKSogRZRERERCRFCbKIiIiISIoSZBERERGRFCXIIiIiIiIpSpBFRERERFKUIIuIiIiIpChBFhERERFJUYIsIiIiIpKiBFlEREREJEUJsoiIiIhIihJkEREREZEUJcgiIiIiIilKkEVEREREUpQgi4iIiIikKEEWEREREUlRgiwiIiIikqIEWUREREQkRQmyiIiIiEiKEmQRERERkRQlyCIiIiIiKUqQRURERERSlCCLiIiIiKQoQRYRERERSVGCLCIiIiKSogRZRERERCRFCbKIiIiISIoSZBERERGRFCXIIiIiIiIpSpBFRERERFKUIIuIiIiIpChBFhERERFJUYIsIiIiIpKiBFlEREREJEUJsoiIiIhIihJkEREREZEUJcgiIiIiIilKkEVEREREUpQgi4iIiIikKEEWEREREUlRgiwiIiIikqIEWUREREQkRQmyiIiIiEiKEmQRERERkRQlyCIiIiIiKUqQRURERERSlCCLiIiIiKQoQRYRERERSVGCLCIiIiKSogRZRERERCTl/wHFu7tW1cYXigAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))\n", "\n", "benders_oct_default.plot_tree(ax=ax1, fontsize=10)\n", "ax1.set_title(\"Default BendersOCT\")\n", "\n", "benders_oct_custom.plot_tree(ax=ax2, fontsize=10)\n", "ax2.set_title(\"User-defined Weights BendersOCT\")\n", "\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, we've demonstrated how to use user-defined weights with both FlowOCT and BendersOCT. By setting `obj_mode=\"weighted\"` and providing weights during the `fit` method call, we can influence the importance of different samples in the training process.\n", "The user-defined weights in this example heavily favor class 1, which may result in trees that are more likely to predict class 1, potentially at the cost of overall accuracy. However, this can be useful in scenarios where misclassifying one class is more costly than misclassifying the other, or when dealing with imbalanced datasets.\n", "Note that the actual results may vary due to the random nature of the dataset and the optimization process. You may want to run the code multiple times or with different random seeds to get a better understanding of the effects of user-defined weights." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "cell_id": "2181319eebc9479299ad724c6909ad78", "deepnote_cell_height": 203, "deepnote_cell_type": "markdown", "tags": [] }, "source": [ "## References\n", "* Dua, D. and Graff, C. (2019). [UCI Machine Learning Repository](http://archive.ics.uci.edu/ml). Irvine, CA: University of California, School of Information and Computer Science.\n", "* Aghaei, S., Gómez, A., & Vayanos, P. (2021). Strong optimal classification trees. arXiv preprint arXiv:2103.15965. https://arxiv.org/abs/2103.15965." ] } ], "metadata": { "deepnote": {}, "deepnote_execution_queue": [], "deepnote_notebook_id": "a83b9a97-2562-44d2-acd9-6ff55c94ce73", "interpreter": { "hash": "dfaf93ad87348b32221474fd3c800e01f580d105683f49be3d64b58d8896a56c" }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "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.9.13" } }, "nbformat": 4, "nbformat_minor": 4 }