{"id":37072493,"url":"https://github.com/egonmedhatten/beta-kde","last_synced_at":"2026-01-14T08:30:41.105Z","repository":{"id":325115976,"uuid":"1099895073","full_name":"egonmedhatten/beta-kde","owner":"egonmedhatten","description":"Beta Kernel Density Estimation compatible with Scikit-learn","archived":false,"fork":false,"pushed_at":"2025-12-03T20:45:50.000Z","size":4269,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-27T10:47:06.858Z","etag":null,"topics":["beta-kernel","boundary-bias","kde","kernel-density-estimation"],"latest_commit_sha":null,"homepage":"https://egonmedhatten.github.io/beta-kde/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/egonmedhatten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-19T15:23:02.000Z","updated_at":"2025-12-03T20:45:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/egonmedhatten/beta-kde","commit_stats":null,"previous_names":["egonmedhatten/beta-kde"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/egonmedhatten/beta-kde","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egonmedhatten%2Fbeta-kde","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egonmedhatten%2Fbeta-kde/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egonmedhatten%2Fbeta-kde/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egonmedhatten%2Fbeta-kde/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/egonmedhatten","download_url":"https://codeload.github.com/egonmedhatten/beta-kde/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egonmedhatten%2Fbeta-kde/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28414141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T08:16:59.381Z","status":"ssl_error","status_checked_at":"2026-01-14T08:13:45.490Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beta-kernel","boundary-bias","kde","kernel-density-estimation"],"created_at":"2026-01-14T08:30:40.489Z","updated_at":"2026-01-14T08:30:41.091Z","avatar_url":"https://github.com/egonmedhatten.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# beta-kde: Boundary-Corrected Kernel Density Estimation\n\n[![PyPI version](https://badge.fury.io/py/beta-kde.svg)](https://badge.fury.io/py/beta-kde)\n[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)\n[![Tests](https://github.com/egonmedhatten/beta-kde/actions/workflows/tests.yml/badge.svg)](https://github.com/egonmedhatten/beta-kde/actions)\n[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/egonmedhatten/beta-kde/HEAD?urlpath=%2Fdoc%2Ftree%2Fexamples%2Ftutorial.ipynb)\n\n**Fast, finite-sample boundary correction for data strictly bounded in [0, 1].**\n\n`beta-kde` is a Scikit-learn compatible library for Kernel Density Estimation (KDE) using the Beta kernel approach (Chen, 1999). It fixes the **Boundary Bias** problem inherent in standard Gaussian KDEs, where probability mass \"leaks\" past the edges of the data (e.g., below 0 or above 1).\n\n\u003c!-- This package is the official implementation of the paper:\n\u003e **A Fast, Closed-Form Bandwidth Selector for the Beta Kernel Density Estimator**\n\u003e *Johan Hallberg Szabadváry (2025)*\n\u003e Submitted to Journal of Computational and Graphical Statistics. --\u003e\n\n## 📊 The Problem vs. The Solution\n\nStandard KDEs smooth data blindly, ignoring bounds. `beta-kde` uses asymmetric Beta kernels that naturally adapt their shape near boundaries to prevent leakage.\n\n![Boundary Bias Comparison](https://raw.githubusercontent.com/egonmedhatten/beta-kde/main/assets/comparison.png)\n\n## 🚀 Key Features\n\n* **Boundary Correction:** Zero leakage. Probability mass stays strictly within the defined bounds.\n* **Fast Bandwidth Selection:** Implements the **Beta Reference Rule**, a closed-form $\\mathcal{O}(1)$ selector.\n \u003c!-- proposed in Szabadváry (2025).  --\u003e\nIt matches the accuracy of expensive Cross-Validation but is **orders of magnitude faster**.\n* **Multivariate Support:** Models multivariate bounded data using a **Non-Parametric Beta Copula**.\n* **Scikit-learn API:** Drop-in replacement for `KernelDensity`. Fully compatible with `GridSearchCV`, `Pipeline`, and `cross_val_score`.\n\n## 📦 Installation\n\n```bash\npip install beta-kde\n```\n\n## ⚡ Quick Start\n💡 **See the [Tutorial Notebook](https://github.com/egonmedhatten/beta-kde/blob/main/examples/tutorial.ipynb) for detailed examples, including visualization and classification.**\n1. Univariate Data (The Standard Case)\nBetaKDE enforces Scikit-learn's 2D input standard (n_samples, n_features).\n\n```python\nimport numpy as np\nfrom beta_kde import BetaKDE\nimport matplotlib.pyplot as plt\n\n# 1. Generate bounded data (e.g., ratios or probabilities)\nnp.random.seed(42)\nX = np.random.beta(2, 5, size=(100, 1))  # Must be 2D column vector\n\n# 2. Fit the estimator\n# 'beta-reference' is the fast, default rule-of-thumb from the paper\nkde = BetaKDE(bandwidth='beta-reference', bounds=(0, 1))\nkde.fit(X)\n\nprint(f\"Selected Bandwidth: {kde.bandwidth_:.4f}\")\n\n# 3. Score samples\n# Use normalized=True to get exact log-likelihoods (integrates to 1.0).\n# Default is False for speed (returns raw kernel density values).\nlog_density = kde.score_samples(np.array([[0.1], [0.5], [0.9]]), normalized=True)\n\n# 4. Plotting convenience\nfig, ax = kde.plot()\nplt.show()\n```\n2. Multivariate Data (Copula)\nFor multidimensional data, BetaKDE fits marginals independently and models dependence using a Copula.\n![2D Copula Plot](https://raw.githubusercontent.com/egonmedhatten/beta-kde/main/assets/2d_copula.png)\n```python\n# Generate correlated 2D data\nX_2d = np.random.rand(200, 2) \n\n# Fit (automatically uses Copula for n_features \u003e 1)\nkde_multi = BetaKDE(bandwidth='beta-reference')\nkde_multi.fit(X_2d)\n\n# Returns log-likelihood of the joint distribution\nscores = kde_multi.score_samples(X_2d)\n\n# Plotting convenience (in the multi-variate case, this plots the marginal densities)\nfig, ax = kde.plot()\nplt.show()\n```\n### 3. Scikit-learn Compatibility (e.g. Hyperparameter Tuning)\n`beta-kde` is a fully compliant Scikit-learn estimator. You can use it in Pipelines or with `GridSearchCV` to find the optimal bandwidth.\n\n*Note: The estimator automatically handles normalization during scoring to ensure valid statistical comparisons.*\n\n```python\nfrom sklearn.model_selection import GridSearchCV\n\n# Define a grid of bandwidths to test\nparam_grid = {\n    'bandwidth': [0.01, 0.05, 0.1, 'beta-reference']\n}\n\n# Run Grid Search\n# n_jobs=-1 is recommended to parallelize the numerical integration\ngrid = GridSearchCV(\n    BetaKDE(),\n    param_grid,\n    cv=5,\n    n_jobs=-1\n)\n\ngrid.fit(X)\n\nprint(f\"Best Bandwidth: {grid.best_params_['bandwidth']}\")\nprint(f\"Best Log-Likelihood: {grid.best_score_:.4f}\")\n```\n\n## ⚡ Performance \u0026 Normalization\nUnlike Gaussian KDEs, Beta KDEs do not integrate to 1.0 analytically. Normalization requires numerical integration, which can be computationally expensive. beta-kde handles this smartly:\n* **Lazy Loading:** fit(X) is fast and does not compute the normalization constant.\n* **On-Demand:** The integral is computed and cached only when you strictly need it (e.g., calling kde.score(X) or kde.pdf(X, normalized=True)).\n* **Flexible Scoring:**\n  * score_samples(X, normalized=False) (Default): Fast. Best for clustering, relative density comparisons, or plotting shape.\n  * score(X): Accurate. Always returns the normalized total log-likelihood. Safe for use in GridSearchCV.\n\n## 🆚 Why use beta-kde?\nIf your data represents percentages, probabilities, or physical constraints (e.g., $x \\in [0, 1]$), standard KDEs are mathematically incorrect at the edges.\n\n| Feature | `sklearn.neighbors.KernelDensity` | `beta-kde` |\n| :--- | :--- | :--- |\n| **Kernel** | Gaussian (Symmetric) | Beta (Asymmetric) |\n| **Boundary Handling** | **Biased** (Leaks mass \u003c 0) | **Correct** (Strictly $\\ge 0$) |\n| **Bandwidth Selection** | Gaussian Reference Rule | **Beta Reference Rule** |\n| **Multivariate** | Symmetric Gaussian Blob | Flexible Non-Parametric Copula |\n| **Speed (Prediction)** | Fast (Tree-based) | Moderate (Exact summation) |\n\n### ⚠️ Important Usage Notes\n1. **Strict Input Shapes:** Input X must be 2D. Use X.reshape(-1, 1) for 1D arrays. This constraint prevents accidental application of univariate estimators to multivariate data.\n2. **Computational Complexity:** This is an exact kernel method.\n    * Raw density (normalized=False) is fast.\n    * Exact probabilities (normalized=True) require a one-time integration cost per fitted model.\n    * Recommended for datasets with $N \u003c 50,000$.\n3. **Bounds:** You must specify bounds if your data is not in $[0, 1]$. The estimator handles scaling internally.\n\n### 📚 References\n1. Chen, S. X. (1999). Beta kernel estimators for density functions. Computational Statistics \u0026 Data Analysis, 31(2), 131-145.\n\u003c!-- 2. Szabadváry, J. H. (2025). A Fast, Closed-Form Bandwidth Selector for the Beta Kernel Density Estimator. Journal of Computational and Graphical Statistics (Submitted). --\u003e\n\n\u003c!-- ### Citation\nIf you use this package in your research, please cite:\n```bibtex\n@article{szabadvary2025beta,\n  title={A Fast, Closed-Form Bandwidth Selector for the Beta Kernel Density Estimator},\n  author={Szabadv{\\'a}ry, Johan Hallberg},\n  journal={Preprint},\n  year={2025}\n}\n``` --\u003e\n### License\nBSD 3-Clause License","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fegonmedhatten%2Fbeta-kde","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fegonmedhatten%2Fbeta-kde","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fegonmedhatten%2Fbeta-kde/lists"}