pso-segmentation 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pso_segmentation-0.1.0/.github/ci.yml +37 -0
- pso_segmentation-0.1.0/.gitignore +141 -0
- pso_segmentation-0.1.0/CONTRIBUTING.md +143 -0
- pso_segmentation-0.1.0/LICENSE +21 -0
- pso_segmentation-0.1.0/PKG-INFO +181 -0
- pso_segmentation-0.1.0/README.md +136 -0
- pso_segmentation-0.1.0/docs/advanced.rst +409 -0
- pso_segmentation-0.1.0/docs/api/api_functional.rst +9 -0
- pso_segmentation-0.1.0/docs/api/index.rst +126 -0
- pso_segmentation-0.1.0/docs/api/io.rst +9 -0
- pso_segmentation-0.1.0/docs/api/objective.rst +11 -0
- pso_segmentation-0.1.0/docs/api/optimizer.rst +9 -0
- pso_segmentation-0.1.0/docs/api/pso_core.rst +10 -0
- pso_segmentation-0.1.0/docs/api/segmentation.rst +26 -0
- pso_segmentation-0.1.0/docs/conf.py +88 -0
- pso_segmentation-0.1.0/docs/contributing.rst +450 -0
- pso_segmentation-0.1.0/docs/core_concepts.rst +211 -0
- pso_segmentation-0.1.0/docs/examples.rst +333 -0
- pso_segmentation-0.1.0/docs/faq.rst +143 -0
- pso_segmentation-0.1.0/docs/getting_started.rst +228 -0
- pso_segmentation-0.1.0/docs/index.rst +152 -0
- pso_segmentation-0.1.0/pyproject.toml +119 -0
- pso_segmentation-0.1.0/src/pso_segmentation/__init__.py +73 -0
- pso_segmentation-0.1.0/src/pso_segmentation/api.py +112 -0
- pso_segmentation-0.1.0/src/pso_segmentation/core/__init__.py +8 -0
- pso_segmentation-0.1.0/src/pso_segmentation/core/pso.py +290 -0
- pso_segmentation-0.1.0/src/pso_segmentation/io.py +354 -0
- pso_segmentation-0.1.0/src/pso_segmentation/objective.py +156 -0
- pso_segmentation-0.1.0/src/pso_segmentation/objective_functions_examples.py +397 -0
- pso_segmentation-0.1.0/src/pso_segmentation/optimizer/__init__.py +5 -0
- pso_segmentation-0.1.0/src/pso_segmentation/optimizer/optimizer.py +405 -0
- pso_segmentation-0.1.0/src/pso_segmentation/segmentation/__init__.py +28 -0
- pso_segmentation-0.1.0/src/pso_segmentation/segmentation/computation.py +187 -0
- pso_segmentation-0.1.0/src/pso_segmentation/segmentation/metrics.py +144 -0
- pso_segmentation-0.1.0/src/pso_segmentation/segmentation/validation.py +104 -0
- pso_segmentation-0.1.0/src/pso_segmentation/selection.py +234 -0
- pso_segmentation-0.1.0/tests/__init__.py +1 -0
- pso_segmentation-0.1.0/tests/test_api.py +303 -0
- pso_segmentation-0.1.0/tests/test_examples.py +388 -0
- pso_segmentation-0.1.0/tests/test_io.py +367 -0
- pso_segmentation-0.1.0/tests/test_objective.py +198 -0
- pso_segmentation-0.1.0/tests/test_optimizer.py +400 -0
- pso_segmentation-0.1.0/tests/test_pso.py +337 -0
- pso_segmentation-0.1.0/tests/test_segmentation.py +390 -0
- pso_segmentation-0.1.0/tests/test_selection.py +187 -0
- pso_segmentation-0.1.0/uv.lock +1352 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- master
|
|
8
|
+
pull_request:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- name: Check out repository
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
|
|
23
|
+
- name: Install package and dev dependencies
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip
|
|
26
|
+
pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: Lint
|
|
29
|
+
run: |
|
|
30
|
+
ruff check .
|
|
31
|
+
ruff format --check .
|
|
32
|
+
|
|
33
|
+
- name: Type check
|
|
34
|
+
run: mypy src/
|
|
35
|
+
|
|
36
|
+
- name: Test
|
|
37
|
+
run: pytest
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
pip-wheel-metadata/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
*.manifest
|
|
32
|
+
*.spec
|
|
33
|
+
|
|
34
|
+
# Installer logs
|
|
35
|
+
pip-log.txt
|
|
36
|
+
pip-delete-this-directory.txt
|
|
37
|
+
|
|
38
|
+
# Unit test / coverage reports
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.nox/
|
|
42
|
+
.coverage
|
|
43
|
+
.coverage.*
|
|
44
|
+
.cache
|
|
45
|
+
nosetests.xml
|
|
46
|
+
coverage.xml
|
|
47
|
+
*.cover
|
|
48
|
+
*.py,cover
|
|
49
|
+
.hypothesis/
|
|
50
|
+
.pytest_cache/
|
|
51
|
+
|
|
52
|
+
# Translations
|
|
53
|
+
*.mo
|
|
54
|
+
*.pot
|
|
55
|
+
|
|
56
|
+
# Django stuff:
|
|
57
|
+
*.log
|
|
58
|
+
local_settings.py
|
|
59
|
+
db.sqlite3
|
|
60
|
+
db.sqlite3-journal
|
|
61
|
+
|
|
62
|
+
# Flask stuff:
|
|
63
|
+
instance/
|
|
64
|
+
.webassets-cache
|
|
65
|
+
|
|
66
|
+
# Scrapy stuff:
|
|
67
|
+
.scrapy
|
|
68
|
+
|
|
69
|
+
# Sphinx documentation
|
|
70
|
+
docs/_build/
|
|
71
|
+
docs/build/
|
|
72
|
+
|
|
73
|
+
# PyBuilder
|
|
74
|
+
target/
|
|
75
|
+
|
|
76
|
+
# Jupyter Notebook
|
|
77
|
+
.ipynb_checkpoints
|
|
78
|
+
|
|
79
|
+
# IPython
|
|
80
|
+
profile_default/
|
|
81
|
+
ipython_config.py
|
|
82
|
+
|
|
83
|
+
# pyenv
|
|
84
|
+
.python-version
|
|
85
|
+
|
|
86
|
+
# pipenv
|
|
87
|
+
Pipfile.lock
|
|
88
|
+
|
|
89
|
+
# PEP 582
|
|
90
|
+
__pypackages__/
|
|
91
|
+
|
|
92
|
+
# Celery stuff
|
|
93
|
+
celerybeat-schedule
|
|
94
|
+
celerybeat.pid
|
|
95
|
+
|
|
96
|
+
# SageMath parsed files
|
|
97
|
+
*.sage.py
|
|
98
|
+
|
|
99
|
+
# Environments
|
|
100
|
+
.env
|
|
101
|
+
.venv
|
|
102
|
+
env/
|
|
103
|
+
venv/
|
|
104
|
+
ENV/
|
|
105
|
+
env.bak/
|
|
106
|
+
venv.bak/
|
|
107
|
+
|
|
108
|
+
# Spyder project settings
|
|
109
|
+
.spyderproject
|
|
110
|
+
.spyproject
|
|
111
|
+
|
|
112
|
+
# Rope project settings
|
|
113
|
+
.ropeproject
|
|
114
|
+
|
|
115
|
+
# mkdocs documentation
|
|
116
|
+
/site
|
|
117
|
+
|
|
118
|
+
# mypy
|
|
119
|
+
.mypy_cache/
|
|
120
|
+
.dmypy.json
|
|
121
|
+
dmypy.json
|
|
122
|
+
|
|
123
|
+
# Pyre type checker
|
|
124
|
+
.pyre/
|
|
125
|
+
|
|
126
|
+
# IDE
|
|
127
|
+
.vscode/
|
|
128
|
+
.idea/
|
|
129
|
+
*.swp
|
|
130
|
+
*.swo
|
|
131
|
+
*~
|
|
132
|
+
.DS_Store
|
|
133
|
+
|
|
134
|
+
# Project specific
|
|
135
|
+
.readthedocs.yml
|
|
136
|
+
|
|
137
|
+
# Specs and documentation drafts
|
|
138
|
+
specs/
|
|
139
|
+
|
|
140
|
+
#old notebooks
|
|
141
|
+
notebooks/old/
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Contributing to pso-segmentation
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing! We welcome contributions from the community.
|
|
4
|
+
|
|
5
|
+
## Code of Conduct
|
|
6
|
+
|
|
7
|
+
This project adheres to a code of conduct. By participating, you are expected to uphold this code.
|
|
8
|
+
|
|
9
|
+
## Getting Started
|
|
10
|
+
|
|
11
|
+
### Prerequisites
|
|
12
|
+
|
|
13
|
+
- Python 3.12 or higher
|
|
14
|
+
- Git
|
|
15
|
+
|
|
16
|
+
### Development Setup
|
|
17
|
+
|
|
18
|
+
1. Fork the repository
|
|
19
|
+
2. Clone your fork:
|
|
20
|
+
```bash
|
|
21
|
+
git clone <repository-url>
|
|
22
|
+
cd pso-segmentation
|
|
23
|
+
```
|
|
24
|
+
3. Create a virtual environment:
|
|
25
|
+
```bash
|
|
26
|
+
python -m venv venv
|
|
27
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
28
|
+
```
|
|
29
|
+
4. Install in development mode with all dependencies:
|
|
30
|
+
```bash
|
|
31
|
+
pip install -e ".[all]"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Making Changes
|
|
35
|
+
|
|
36
|
+
### Code Style
|
|
37
|
+
|
|
38
|
+
We use strict code quality standards:
|
|
39
|
+
|
|
40
|
+
- **Formatting**: `ruff format` (enforced)
|
|
41
|
+
- **Linting**: `ruff check` (enforced)
|
|
42
|
+
- **Type Checking**: `mypy --strict` (enforced)
|
|
43
|
+
|
|
44
|
+
Before committing, run:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
ruff format .
|
|
48
|
+
ruff check .
|
|
49
|
+
mypy src/
|
|
50
|
+
pytest
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Testing
|
|
54
|
+
|
|
55
|
+
All new features must include tests. Run tests with:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pytest
|
|
59
|
+
pytest --cov=src/pso_segmentation # With coverage
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Aim for coverage > 80% on core modules.
|
|
63
|
+
|
|
64
|
+
### Commits
|
|
65
|
+
|
|
66
|
+
Use clear, descriptive commit messages:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Add feature: Brief description
|
|
70
|
+
|
|
71
|
+
Longer explanation if needed.
|
|
72
|
+
- Point 1
|
|
73
|
+
- Point 2
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Avoid:
|
|
77
|
+
- ❌ `fix bug`
|
|
78
|
+
- ❌ `update code`
|
|
79
|
+
- ✅ `Fix convergence issue in PSO when pop_size < 2`
|
|
80
|
+
|
|
81
|
+
## Pull Request Process
|
|
82
|
+
|
|
83
|
+
1. Create a feature branch: `git checkout -b feature/my-feature`
|
|
84
|
+
2. Make your changes
|
|
85
|
+
3. Run all checks: `ruff format . && ruff check . && mypy src/ && pytest`
|
|
86
|
+
4. Commit with clear messages
|
|
87
|
+
5. Push to your fork
|
|
88
|
+
6. Create a Pull Request with:
|
|
89
|
+
- Clear title and description
|
|
90
|
+
- Reference to any related issues
|
|
91
|
+
- Summary of changes
|
|
92
|
+
|
|
93
|
+
## Documentation
|
|
94
|
+
|
|
95
|
+
- Update docstrings for public APIs (Google style)
|
|
96
|
+
- Add/update Sphinx docs for new features
|
|
97
|
+
- Include examples in docstrings
|
|
98
|
+
|
|
99
|
+
Example:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
def segment_scores(scores: np.ndarray, labels: np.ndarray, objective_func: Callable) -> np.ndarray:
|
|
103
|
+
"""
|
|
104
|
+
Optimize segmentation of continuous scores.
|
|
105
|
+
|
|
106
|
+
Parameters
|
|
107
|
+
----------
|
|
108
|
+
scores : np.ndarray
|
|
109
|
+
Continuous scores to segment (shape: (n_samples,))
|
|
110
|
+
labels : np.ndarray
|
|
111
|
+
Binary labels (0/1) (shape: (n_samples,))
|
|
112
|
+
objective_func : Callable
|
|
113
|
+
Custom fitness function
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
np.ndarray
|
|
118
|
+
Optimized segment boundaries
|
|
119
|
+
|
|
120
|
+
Examples
|
|
121
|
+
--------
|
|
122
|
+
>>> cuts = segment_scores(scores, labels, my_fitness_func)
|
|
123
|
+
"""
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Reporting Issues
|
|
127
|
+
|
|
128
|
+
Use GitHub Issues with:
|
|
129
|
+
|
|
130
|
+
- Clear title
|
|
131
|
+
- Steps to reproduce
|
|
132
|
+
- Expected vs actual behavior
|
|
133
|
+
- Python version and environment
|
|
134
|
+
- Minimal code example
|
|
135
|
+
|
|
136
|
+
## Questions?
|
|
137
|
+
|
|
138
|
+
- Open a GitHub Discussion
|
|
139
|
+
- Check existing documentation and issues first
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
Thank you for contributing! 🎉
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pso-segmentation contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pso-segmentation
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Robust package for segmentation optimization using Particle Swarm Optimization (PSO)
|
|
5
|
+
Author-email: Léo Colin <leocolin7002@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: PSO,data science,optimization,particle swarm optimization,segmentation
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Requires-Dist: build>=1.5.0
|
|
21
|
+
Requires-Dist: numpy>=1.20
|
|
22
|
+
Requires-Dist: pandas>=1.3
|
|
23
|
+
Requires-Dist: twine>=6.2.0
|
|
24
|
+
Provides-Extra: all
|
|
25
|
+
Requires-Dist: mypy; extra == 'all'
|
|
26
|
+
Requires-Dist: myst-parser; extra == 'all'
|
|
27
|
+
Requires-Dist: plotly>=6.0; extra == 'all'
|
|
28
|
+
Requires-Dist: pytest-cov; extra == 'all'
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == 'all'
|
|
30
|
+
Requires-Dist: ruff; extra == 'all'
|
|
31
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'all'
|
|
32
|
+
Requires-Dist: sphinx>=5.0; extra == 'all'
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
38
|
+
Provides-Extra: docs
|
|
39
|
+
Requires-Dist: myst-parser; extra == 'docs'
|
|
40
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
|
41
|
+
Requires-Dist: sphinx>=5.0; extra == 'docs'
|
|
42
|
+
Provides-Extra: viz
|
|
43
|
+
Requires-Dist: plotly>=6.0; extra == 'viz'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# pso-segmentation
|
|
47
|
+
|
|
48
|
+
[](https://www.python.org/)
|
|
49
|
+
[](https://github.com/astral-sh/ruff)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
|
|
52
|
+
`pso-segmentation` is a PSO-based package for building interpretable segmentations on any continuous variable.
|
|
53
|
+
|
|
54
|
+
## Overview
|
|
55
|
+
|
|
56
|
+
The package gives you a compact way to:
|
|
57
|
+
|
|
58
|
+
- optimize cut points on continuous variables
|
|
59
|
+
- encode business-specific constraints inside custom objective functions
|
|
60
|
+
- select the number of segments with a dedicated helper
|
|
61
|
+
- export results and persist optimizer state
|
|
62
|
+
- compare candidates with a business-specific selection function
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install pso-segmentation
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
For development and documentation work:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install -e ".[dev,docs]"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
### Functional API
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import numpy as np
|
|
82
|
+
from pso_segmentation import make_objective, segment_scores
|
|
83
|
+
|
|
84
|
+
scores = np.random.uniform(0, 100, 1000)
|
|
85
|
+
labels = np.random.binomial(1, 0.15, 1000) # target (binary here)
|
|
86
|
+
objective = make_objective(scores, labels, metric="r2")
|
|
87
|
+
|
|
88
|
+
result = segment_scores(scores, labels, objective)
|
|
89
|
+
|
|
90
|
+
print(f"R2: {result.r2:.3f}")
|
|
91
|
+
print(f"Segments: {result.n_segments}")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Object-Oriented API
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import numpy as np
|
|
98
|
+
from pso_segmentation import (
|
|
99
|
+
make_objective,
|
|
100
|
+
monotonic_penalty,
|
|
101
|
+
OptimizerConfig,
|
|
102
|
+
SegmentationOptimizer,
|
|
103
|
+
segment_size_penalty,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
scores = np.random.uniform(0, 100, 1000)
|
|
107
|
+
labels = np.random.binomial(1, 0.15, 1000) # target (binary here)
|
|
108
|
+
objective = make_objective(
|
|
109
|
+
scores,
|
|
110
|
+
labels,
|
|
111
|
+
metric="r2",
|
|
112
|
+
penalties=[
|
|
113
|
+
monotonic_penalty(weight=0.3),
|
|
114
|
+
segment_size_penalty(min_size=0.05, max_size=0.4, weight=0.2),
|
|
115
|
+
],
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
config = OptimizerConfig(n_segments=5, pop_size=50, max_iter=100, seed=42)
|
|
119
|
+
optimizer = SegmentationOptimizer(config)
|
|
120
|
+
optimizer.fit(scores, labels, objective)
|
|
121
|
+
|
|
122
|
+
print(optimizer.summary())
|
|
123
|
+
print(optimizer.get_metrics())
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Selecting the number of segments
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from pso_segmentation import make_objective, monotonic_penalty, select_n_segments
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def objective_factory(scores, labels, n_segments, params):
|
|
133
|
+
return make_objective(
|
|
134
|
+
scores,
|
|
135
|
+
labels,
|
|
136
|
+
metric="r2",
|
|
137
|
+
penalties=[monotonic_penalty(weight=params["monotonic_weight"])],
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
selection = select_n_segments(
|
|
141
|
+
scores,
|
|
142
|
+
labels,
|
|
143
|
+
segment_range=(3, 7),
|
|
144
|
+
objective_factory=objective_factory,
|
|
145
|
+
param_grid={"monotonic_weight": [0.0, 0.2, 0.5]},
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
print(selection.best_candidate.n_segments)
|
|
149
|
+
print(selection.best_candidate.cuts)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Documentation
|
|
153
|
+
|
|
154
|
+
The full user guide lives in the `docs/` folder. The notebooks are intentionally limited to:
|
|
155
|
+
|
|
156
|
+
- `notebooks/00_quick_start.ipynb` (generic segmentation + objective contract)
|
|
157
|
+
- `notebooks/01_business_use_case.ipynb` (PD segmentation with a custom objective)
|
|
158
|
+
|
|
159
|
+
## Development
|
|
160
|
+
|
|
161
|
+
Run the test and quality checks from the repository root:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
pytest
|
|
165
|
+
ruff check .
|
|
166
|
+
ruff format .
|
|
167
|
+
mypy src/
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT License - see [LICENSE](LICENSE).
|
|
173
|
+
|
|
174
|
+
## Contributing
|
|
175
|
+
|
|
176
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow and contribution rules.
|
|
177
|
+
|
|
178
|
+
## Status
|
|
179
|
+
|
|
180
|
+
Version 0.1.0 is the current alpha release line. The package API is stable enough for
|
|
181
|
+
experimentation, notebooks, and internal use, while production release work continues.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# pso-segmentation
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/)
|
|
4
|
+
[](https://github.com/astral-sh/ruff)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
`pso-segmentation` is a PSO-based package for building interpretable segmentations on any continuous variable.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
The package gives you a compact way to:
|
|
12
|
+
|
|
13
|
+
- optimize cut points on continuous variables
|
|
14
|
+
- encode business-specific constraints inside custom objective functions
|
|
15
|
+
- select the number of segments with a dedicated helper
|
|
16
|
+
- export results and persist optimizer state
|
|
17
|
+
- compare candidates with a business-specific selection function
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install pso-segmentation
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For development and documentation work:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install -e ".[dev,docs]"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### Functional API
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import numpy as np
|
|
37
|
+
from pso_segmentation import make_objective, segment_scores
|
|
38
|
+
|
|
39
|
+
scores = np.random.uniform(0, 100, 1000)
|
|
40
|
+
labels = np.random.binomial(1, 0.15, 1000) # target (binary here)
|
|
41
|
+
objective = make_objective(scores, labels, metric="r2")
|
|
42
|
+
|
|
43
|
+
result = segment_scores(scores, labels, objective)
|
|
44
|
+
|
|
45
|
+
print(f"R2: {result.r2:.3f}")
|
|
46
|
+
print(f"Segments: {result.n_segments}")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Object-Oriented API
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import numpy as np
|
|
53
|
+
from pso_segmentation import (
|
|
54
|
+
make_objective,
|
|
55
|
+
monotonic_penalty,
|
|
56
|
+
OptimizerConfig,
|
|
57
|
+
SegmentationOptimizer,
|
|
58
|
+
segment_size_penalty,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
scores = np.random.uniform(0, 100, 1000)
|
|
62
|
+
labels = np.random.binomial(1, 0.15, 1000) # target (binary here)
|
|
63
|
+
objective = make_objective(
|
|
64
|
+
scores,
|
|
65
|
+
labels,
|
|
66
|
+
metric="r2",
|
|
67
|
+
penalties=[
|
|
68
|
+
monotonic_penalty(weight=0.3),
|
|
69
|
+
segment_size_penalty(min_size=0.05, max_size=0.4, weight=0.2),
|
|
70
|
+
],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
config = OptimizerConfig(n_segments=5, pop_size=50, max_iter=100, seed=42)
|
|
74
|
+
optimizer = SegmentationOptimizer(config)
|
|
75
|
+
optimizer.fit(scores, labels, objective)
|
|
76
|
+
|
|
77
|
+
print(optimizer.summary())
|
|
78
|
+
print(optimizer.get_metrics())
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Selecting the number of segments
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from pso_segmentation import make_objective, monotonic_penalty, select_n_segments
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def objective_factory(scores, labels, n_segments, params):
|
|
88
|
+
return make_objective(
|
|
89
|
+
scores,
|
|
90
|
+
labels,
|
|
91
|
+
metric="r2",
|
|
92
|
+
penalties=[monotonic_penalty(weight=params["monotonic_weight"])],
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
selection = select_n_segments(
|
|
96
|
+
scores,
|
|
97
|
+
labels,
|
|
98
|
+
segment_range=(3, 7),
|
|
99
|
+
objective_factory=objective_factory,
|
|
100
|
+
param_grid={"monotonic_weight": [0.0, 0.2, 0.5]},
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
print(selection.best_candidate.n_segments)
|
|
104
|
+
print(selection.best_candidate.cuts)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Documentation
|
|
108
|
+
|
|
109
|
+
The full user guide lives in the `docs/` folder. The notebooks are intentionally limited to:
|
|
110
|
+
|
|
111
|
+
- `notebooks/00_quick_start.ipynb` (generic segmentation + objective contract)
|
|
112
|
+
- `notebooks/01_business_use_case.ipynb` (PD segmentation with a custom objective)
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
Run the test and quality checks from the repository root:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pytest
|
|
120
|
+
ruff check .
|
|
121
|
+
ruff format .
|
|
122
|
+
mypy src/
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT License - see [LICENSE](LICENSE).
|
|
128
|
+
|
|
129
|
+
## Contributing
|
|
130
|
+
|
|
131
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow and contribution rules.
|
|
132
|
+
|
|
133
|
+
## Status
|
|
134
|
+
|
|
135
|
+
Version 0.1.0 is the current alpha release line. The package API is stable enough for
|
|
136
|
+
experimentation, notebooks, and internal use, while production release work continues.
|