Metadata-Version: 2.4
Name: decision-boundary-plot
Version: 0.1.0
Summary: A universal visualization library for N-dimensional machine learning decision boundaries
Author-email: Yermachenkov Illia <ermakilyxa2@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/P3Lin0r/decision-boundary
Project-URL: Repository, https://github.com/P3Lin0r/decision-boundary
Project-URL: Bug Tracker, https://github.com/P3Lin0r/decision-boundary/issues
Keywords: decision-boundary,machine-learning,deep-learning,visualization,dimensionality-reduction,neural-network,DL,ML,pca,umap,tsne,matplotlib,plotly,scikit-learn,keras,pytorch,pytorch-lightning,classification,model-interpretability,explainable-ai,jupyter,colab,interactive-visualization,3d-visualization,data-science
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Education
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Framework :: Jupyter
Classifier: Framework :: Matplotlib
Classifier: Framework :: IPython
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24.0
Requires-Dist: scikit-learn>=1.3.0
Requires-Dist: matplotlib>=3.5.0
Requires-Dist: plotly>=5.0.0
Requires-Dist: ipython>=7.34.0
Requires-Dist: ipywidgets>=7.7.0
Requires-Dist: ipykernel>6.0.0
Requires-Dist: nbformat>=4.2.0
Provides-Extra: umap
Requires-Dist: umap-learn>=0.5.0; extra == "umap"
Provides-Extra: sklearn-callbacks
Requires-Dist: scikit-learn>=1.9.0; extra == "sklearn-callbacks"
Provides-Extra: keras
Requires-Dist: keras>=3.0.0; extra == "keras"
Provides-Extra: lightning
Requires-Dist: lightning>=2.0.0; extra == "lightning"
Requires-Dist: torch>=2.0.0; extra == "lightning"
Provides-Extra: export
Requires-Dist: kaleido>=0.2.1; extra == "export"
Provides-Extra: all
Requires-Dist: umap-learn>=0.5.0; extra == "all"
Requires-Dist: keras>=3.0.0; extra == "all"
Requires-Dist: lightning>=2.0.0; extra == "all"
Requires-Dist: torch>=2.1.0; extra == "all"
Requires-Dist: kaleido>=0.2.1; extra == "all"
Requires-Dist: scikit-learn>=1.9.0; extra == "all"
Provides-Extra: test
Requires-Dist: pytest>=7.0.0; extra == "test"
Requires-Dist: pytest-cov>=7.0.0; extra == "test"
Dynamic: license-file

<div align="center">

# Decision Boundary

**Effortless N-Dimensional Decision Boundary Visualization for Machine Learning**

[![PyPI version](https://img.shields.io/pypi/v/decision-boundary-plot.svg?color=blue)](https://pypi.org/project/decision-boundary-plot/)
[![Python versions](https://img.shields.io/pypi/pyversions/decision-boundary-plot.svg)](https://pypi.org/project/decision-boundary-plot/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/P3Lin0r/decision-boundary/blob/main/LICENSE)
![CI](https://github.com/P3Lin0r/decision-boundary/actions/workflows/ci.yml/badge.svg)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1Rq8JbdrS_EDjV8ue51jlOeSeqtrd6IvM)

_Bridge the gap between high-dimensional data and human intuition. Render beautiful, interactive 2D and 3D decision boundaries for any ML/DL model with a single line of code._

</div>

---

<div align="center">
  <table style="border-collapse: collapse; border: none;">
    <tr>
      <td align="center" width="50%" style="border: none; padding: 15px;">
        <img src="https://raw.githubusercontent.com/P3Lin0r/media-assets/refs/heads/main/decision-boundary/readme/hero_2d.png" alt="2D Matplotlib rendering" width="85%">
        <br><br><i>2D Matplotlib rendering</i>
      </td>
      <td align="center" width="50%" style="border: none; padding: 15px;">
        <img src="https://raw.githubusercontent.com/P3Lin0r/media-assets/refs/heads/main/decision-boundary/readme/hero_3d_360_30fps.gif" alt="3D Interactive Plotly visualization" width="100%">
        <br><br><i>3D Interactive Plotly visualization</i>
      </td>
    </tr>
  </table>
</div>

### Table of Contents

- [About](#about)
- [Interactive Examples & Tutorials](#-interactive-examples--tutorials)
- [How to Read the Plots](#how-to-read-the-plots)
- [Installation](#installation)
- [Quick Start & Basic Usage](#quick-start--basic-usage)
- [Dimensionality Reduction (N-D to 2D/3D)](#dimensionality-reduction-n-d-to-2d3d)
- [Live Training Callbacks](#live-training-callbacks-see-your-model-learn)
- [How It Works Under the Hood](#how-it-works-under-the-hood)
- [Academic Use](#academic-use)

## About

Visualizing how a Machine Learning model partitions feature space is crucial for debugging, presentation, and deeply understanding model behavior. However, standard plotting libraries fail when your dataset has more than 2 or 3 features.

**DecisionBoundary** solves this by providing a universal visualization pipeline. It automatically handles high-dimensional data reduction, builds prediction grids, gracefully manages model interfaces (Scikit-Learn, Keras, PyTorch Lightning), and renders stunning 2D (Matplotlib) or 3D (Plotly) maps.

### Key Features

| 🟢 Feature                        | Description                                                                                                                                                                                                    |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Universal Model Support**       | Works seamlessly with `scikit-learn` estimators, `tf.keras` neural networks, `PyTorch Lightning` modules, or _any_ custom object with a `.predict()` method.                                                   |
| **Auto Dimensionality Reduction** | Natively supports **PCA** and **UMAP**. Pass 10D, 50D, or 100D data — the library automatically projects it down to 2D or 3D while preserving decision topographies using a built-in `KNNInverseApproximator`. |
| **Live Training Callbacks**       | Watch your neural networks learn in real-time. Includes plug-and-play callbacks for Keras, Lightning, and Sklearn.                                                                                             |
| **Dual Rendering Backends**       | High-performance static 2D plots via **Matplotlib** and fully interactive, rotatable 3D isosurfaces via **Plotly**.                                                                                            |
| **Rich Customization**            | Effortlessly tweak colormaps, opacity, grid resolution, colorbars, and legend displays to make your charts presentation-ready.                                                                                 |

---

## 📘 Interactive Examples & Tutorials

Want to see it in action before writing code? Check out our interactive tutorials to explore basic plotting, styling, dimensionality reduction, and manual training loops:

- **Google Colab:** 👉 [Run the DecisionBoundary Tutorial in the Cloud](https://colab.research.google.com/drive/1Rq8JbdrS_EDjV8ue51jlOeSeqtrd6IvM) — _Best for a quick, zero-setup interactive demo._
- **Local Setup:** [Download the Tutorial Notebook (GitHub)](https://github.com/P3Lin0r/decision-boundary/blob/main/examples/tutorial.ipynb) — _Best if you want to clone the repo, install dependencies locally, and play with your own datasets._

---

## How to Read the Plots

<div align="center">
  <table style="border-collapse: collapse; border: none;">
    <tr>
      <td align="center" width="50%" style="border: none; padding: 15px;">
        <img src="https://raw.githubusercontent.com/P3Lin0r/media-assets/refs/heads/main/decision-boundary/readme/classification.png" alt="Classification visualization" width="93%">
        <br><i>Discrete decision regions</i>
      </td>
      <td align="center" width="50%" style="border: none; padding: 15px;">
        <img src="https://raw.githubusercontent.com/P3Lin0r/media-assets/refs/heads/main/decision-boundary/readme/regression.png" alt="Regression visualization" width="100%">
        <br><i>Continuous prediction surface</i>
      </td>
    </tr>
  </table>
</div>

When transitioning from native high-dimensional features to a reduced 2D/3D visual space, reading the boundary requires a specific intuition:

- **The Background (Gradient/Surface):** Represents the continuous prediction surface generated by your model across the compressed feature space.
- **The Scatter Points:** Represent the actual true labels ($y$) from your dataset.

**Evaluating Model Quality:** Ideally, the color of each individual scatter point should blend seamlessly with the background gradient directly beneath it.

> ⚠️ **The Projection Caveat:** If you see a stark contrast (e.g., a dark red point on a deep blue background), it _usually_ indicates a model error. However, remember that you are looking at a compressed manifold. Points that are perfectly separated in 50D space might visually overlap when flattened to 2D. Always verify visual anomalies with your actual evaluation metrics (Accuracy, F1, RMSE)!

---

## Installation

The core library is lightweight and easy to install via `pip`:

```bash
pip install decision-boundary-plot
```

**Optional Dependencies:**
DecisionBoundary uses a modular dependency system to keep the core package light. Install extras based on your needs:

```bash
# Recommended for complex, non-linear dimensionality reduction
pip install decision-boundary-plot[umap]

# Required to save 3D interactive Plotly graphs as static .png files
pip install decision-boundary-plot[export]

# Required for the experimental Scikit-Learn 1.9.0+ callback support
pip install decision-boundary-plot[sklearn-callbacks]

# Install everything (includes sklearn callbacks, Keras, Lightning, UMAP, and Kaleido)
pip install decision-boundary-plot[all]

```

_Alternatively, install the latest development version directly from GitHub:_

```bash
# Install core development version (lightweight)
pip install git+https://github.com/P3Lin0r/decision-boundary.git

# Install development version with ALL extras (UMAP, Keras, Lightning, etc.)
pip install "decision-boundary-plot[all] @ git+https://github.com/P3Lin0r/decision-boundary.git"
```

---

## Quick Start & Basic Usage

You don't need to manually create meshgrids, handle inverse transformations, or loop over predictions anymore. Just pass your data and a fitted model to the `DecisionBoundary` orchestrator.

### The Basics (2D Classification)

```python
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from decision_boundary import DecisionBoundary

# 1. Prepare your data and fit a model
X, y = make_classification(n_features=5, n_informative=3, random_state=42)
model = RandomForestClassifier().fit(X, y)

# 2. Initialize the visualizer
# The library detects X has 5 dimensions and automatically applies PCA to reduce it to 2D
visualizer = DecisionBoundary(X, y, model=model, plot_mode="2d")

# 3. Render!
visualizer.plot(
    show=True,
    title="Random Forest Decision Boundary (5D -> 2D)",
    grid_resolution="normal"
)

```

### Advanced Styling (`kwargs`)

The `.plot()` method accepts a rich set of styling arguments to make your charts presentation-ready. Whether you are doing classification or regression, you have full control over the aesthetics.

```python
visualizer.plot(
    show=True,
    grid_resolution="high",       # "low", "normal", "high" or int (e.g., 200)

    # --- Aesthetics ---
    cmap="coolwarm",              # Colormap for the background gradient
    alpha=0.6,                    # Transparency of the background surface
    levels=100,                   # Number of contour levels (increase for smooth regression)

    # --- Toggles ---
    show_decision_line=False,     # Turn off the 0.5 threshold line (ideal for Regression)
    show_colorbar=True,           # Display a scale bar for continuous predictions
    show_legend=True,             # Display a discrete legend for classification targets

    # --- Labels ---
    colorbar_label="Predicted House Price ($)",
    legend_title="Iris Species",
    xlabel="Principal Component 1",
    ylabel="Principal Component 2",
)

```

> _💡 **Tip:** For a complete list of styling options, check out the `Plot2DKwargs` and `Plot3DKwargs` definitions in the [types source code](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/common/types.py)._

## Dimensionality Reduction (N-D to 2D/3D)

Real-world datasets rarely have just 2 or 3 features. When you pass high-dimensional data (e.g., 10D or 100D), `DecisionBoundary` seamlessly projects it down to a visualizable space.

<div align="center">
  <img src="https://raw.githubusercontent.com/P3Lin0r/media-assets/refs/heads/main/decision-boundary/readme/dim_red_2d.png" alt="Comparison of Dimensionality Reduction Algorithms in 2D" width="950">
  <br>
  <img src="https://raw.githubusercontent.com/P3Lin0r/media-assets/refs/heads/main/decision-boundary/readme/dim_red_3d.png" alt="Comparison of Dimensionality Reduction Algorithms in 3D" width="950">
  <p><i>Comparing decision boundaries across different manifold learning algorithms.</i></p>
</div>

### Supported Algorithms

By default, the library uses `dim_reducer="auto"`, which smartly selects **PCA** for highly linear/small datasets and **UMAP** for complex, non-linear manifolds.

You can explicitly **force an algorithm** or pass your **own custom instantiated reducer** (like t-SNE, Isomap, or any object exposing a `.fit_transform()` method):

```python
from sklearn.manifold import TSNE

# 1. Using built-in string aliases: "pca", "umap", or "auto"
visualizer = DecisionBoundary(X, y, model, dim_reducer="umap")

# 2. Passing a custom configured instance
custom_tsne = TSNE(n_components=2, perplexity=15, random_state=42)

visualizer = DecisionBoundary(
    X, y, model,
    dim_reducer=custom_tsne,
    inverter_neighbors=15  # <--- Crucial for smooth backgrounds!
)
```

> ⚠️ **The Inverse Transform Problem:**
> To draw the background decision grid, the library must project 2D/3D screen coordinates _back_ into original N-D space. Algorithms like PCA support this natively. Algorithms like **t-SNE** or **Isomap** do not.
> _Solution:_ DecisionBoundary automatically injects a `KNNInverseApproximator` under the hood. Use the `inverter_neighbors` parameter to control the smoothness of your background grid when using non-invertible reducers.

---

## Live Training Callbacks (See your model learn!)

Static plots are great, but watching a model's decision boundary evolve epoch by epoch provides unparalleled intuition about its learning dynamics, overfitting, and activation function behaviors.

<div align="center">
  <img src="https://raw.githubusercontent.com/P3Lin0r/media-assets/refs/heads/main/decision-boundary/readme/comparison_learning.gif" alt="Use of Training Callback Comparison of Activation Functions">
</div>

`DecisionBoundary` provides plug-and-play callbacks for the most popular ML/DL frameworks. All callbacks inherit from the same base class, meaning **they share the exact same configuration parameters** (`plot_every`, `reuse`, `plotter_kwargs`, `save_dir`, etc.). They can automatically save snapshots to disk or render them inline in Jupyter/Colab notebooks without violating any of your training logs.

> _💡 For more information about callback parameters, see the [`BaseBoundaryCallback`](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/callbacks/base_callback.py)_

### 🧠 Keras / TensorFlow

Seamlessly integrates with `model.fit()`. It even detects `EarlyStopping` to appropriately label your final "Best Model" plot!

```python
from decision_boundary import KerasBoundaryCallback

callback = KerasBoundaryCallback(
    X_train, y_train,     # Tip: Pass validation X_val data for a more stable background representation
    plot_every=10,        # Render a plot every 10 epochs
    plot_mode="2d",       # Target dimension for the plot
    reuse=True            #
    reuse=True            # Update the same plot in Jupyter (prevents spam)
    save_dir="./plots",   # Automatically save plot in folder as PNG/HTML
    save_format="png",    # File format for saving the plot
)

model.fit(X_train, y_train, epochs=100, callbacks=[callback])

```

### ⚡ PyTorch Lightning

Monitors the `Trainer` lifecycle and triggers plot updates at the end of validation epochs.

```python
from decision_boundary import LightningBoundaryCallback
import lightning.pytorch as pl

callback = LightningBoundaryCallback(X_train, y_train, plot_every=5)

trainer = pl.Trainer(max_epochs=50, callbacks=[callback])

trainer.fit(model, dataloader)

```

### 📊 Scikit-Learn (New in v1.9.0+)

The library actively supports the brand new experimental **Callbacks API** introduced in Scikit-Learn 1.9.0!

```python
from sklearn.linear_model import LogisticRegression
from decision_boundary import SklearnBoundaryCallback

callback = SklearnBoundaryCallback(X_train, y_train, plot_every=5)

logreg = LogisticRegression(max_iter=100, solver='lbfgs')
logreg.set_callbacks(callback)
logreg.fit(X_train, y_train)

```

> **⚠️ Scikit-Learn Limitations:** > As per the official sklearn documentation, `set_callbacks` is currently only supported by models using the `solver='lbfgs'` backend (e.g., Logistic Regression). Passing callbacks to other solvers will trigger a warning and be ignored by sklearn.

### Custom Callbacks

Building your own training loop? Inherit from [`BaseBoundaryCallback`](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/callbacks/base_callback.py) to instantly get all the plotting orchestration, history caching, and file-saving logic for free!

## How It Works Under the Hood

Curious about how `DecisionBoundary` elegantly maps a 100-dimensional neural network to a 2D screen? Here is the internal pipeline:

1. **Validation & Sampling ([`validator.py`](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/validator.py)):** Checks inputs and safely downsamples massive datasets (e.g., 100k+ rows) via StratifiedSplit to maintain rendering performance without losing spatial distribution.
2. **Adapter Pattern ([`adapter.py`](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/adapter.py)):** Wraps your model (whether it's Keras, Torch, or Sklearn) to standardize the `.predict()` outputs into a flat 1D float array, abstracting away probabilities, logits, or class indices.
3. **Dimensionality Reduction ([`reducer.py`](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/reducer.py)):** Projects high-dimensional $X$ to 2D/3D. If the chosen algorithm lacks a native `inverse_transform` (like t-SNE), it seamlessly attaches the `KNNInverseApproximator` to map screen coordinates back to the model's feature space.
4. **Mesh Generation & Prediction ([`renderer.py`](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/renderer.py)):** Calculates an optimized coordinate grid, projects it to N-Dimensions, feeds it to the model, and builds the continuous probability surface.
5. **Rendering ([`renderer.py`](https://github.com/P3Lin0r/decision-boundary/blob/main/decision_boundary/renderer.py)):** Routes the resulting tensors to either the `matplotlib` backend for static 2D or the `plotly` backend for interactive 3D.

---

## 🎓 Academic Use

If you use this library for clustering analysis, computer vision research, or publish visualizations generated by `DecisionBoundary` in academic conferences, journals, or papers, please consider citing this repository:

```bibtex
@software{decision_boundary_2026,
  author = {Yermachenkov Illia},
  title = {Decision Boundary Visualizer: N-Dimensional ML Rendering},
  year = {2026},
  publisher = {GitHub},
  journal = {GitHub repository},
  url = {https://github.com/P3Lin0r/decision-boundary}
}
```

---

## 📄 License

Distributed under the **MIT License**. See [`LICENSE`](https://github.com/P3Lin0r/decision-boundary/blob/main/LICENSE) for more information. This means you are completely free to use this library in both open-source and closed-source commercial projects.

> **Enjoying the library?** Drop a ⭐ on [GitHub](https://github.com/P3Lin0r/decision-boundary) to show your support, it helps the project grow!
