Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/python-compatibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Python compatibility

on:
push:
branches: [master]
pull_request:

permissions:
contents: read

jobs:
cpu:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.13", "3.14"]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
- name: Build distributions
run: |
python -m pip install --upgrade pip build
python -m build
- name: Install wheel and test dependencies
run: python -m pip install dist/*.whl pytest
- name: Run test suite
working-directory: ${{ runner.temp }}
run: python -m pytest -q -rs "$GITHUB_WORKSPACE/tests"
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ see [Tutorial_2_Advanced_multioutput](https://github.com/AILab-MLTools/Py-Boost/

## Installation

Before installing py-boost via pip, you should have cupy installed. You can use:
Py-Boost supports Python 3.8–3.14. Install the CuPy distribution compatible
with your Python and CUDA versions before installing Py-Boost.

`pip install -U cupy-cuda110 py-boost`
On Python 3.14, use Numba 0.63 or later and CuPy 14 or later. For example,
with CUDA 12.x:

**Note**: replace with your cuda version! For details, see [this guide](https://docs.cupy.dev/en/stable/install.html).
`pip install -U "cupy-cuda12x>=14" py-boost`

For other Python or CUDA versions, choose the appropriate CuPy package from the
[CuPy installation guide](https://docs.cupy.dev/en/stable/install.html).

## Quick tour

Expand Down
2 changes: 1 addition & 1 deletion build_package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ source ./py_boost_venv/bin/activate

pip install -U pip
pip install -U poetry
pip install -U cupy-cuda110
pip install -U "${CUPY_PACKAGE:-cupy-cuda12x}"

poetry lock
poetry install
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Operating System :: OS Independent",
"Intended Audience :: Science/Research",
"Development Status :: 3 - Alpha",
Expand All @@ -29,7 +30,7 @@ classifiers = [

[tool.poetry.dependencies]

python = ">=3.8, <3.14"
python = ">=3.8, <3.15"

scikit-learn = ">=1"
numpy = "*"
Expand Down
38 changes: 38 additions & 0 deletions tests/test_quantization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""CPU coverage for the Numba kernels used by all training paths."""

import numpy as np
import pytest

from py_boost.quantization.base import (
QuantileQuantizer,
UniformQuantizer,
UniquantQuantizer,
)


@pytest.mark.parametrize("dtype", [np.float32, np.float64])
@pytest.mark.parametrize("quantizer_cls", [
QuantileQuantizer, UniformQuantizer, UniquantQuantizer,
])
def test_quantization_matches_borders(quantizer_cls, dtype):
# More distinct values than bins exercises each quantizer's binning kernel.
X = np.linspace(-10, 10, 128, dtype=dtype).reshape(32, 4)
X[0] = np.nan
quantizer = quantizer_cls(max_bin=8)

encoded = quantizer.fit_transform(X)
borders = quantizer.get_borders()

assert encoded.dtype == np.uint8
assert encoded.shape == X.shape
assert quantizer.get_max_bin() <= 8
for column, column_borders in enumerate(borders):
assert np.isneginf(column_borders[0])
assert np.isposinf(column_borders[-1])
assert np.all(np.diff(column_borders) > 0)
valid = ~np.isnan(X[:, column])
expected = np.zeros(X.shape[0], dtype=np.uint8)
expected[valid] = np.searchsorted(column_borders, X[valid, column])
np.testing.assert_array_equal(encoded[:, column], expected)

np.testing.assert_array_equal(quantizer.transform(X), encoded)
Loading