featranker 0.1.1__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.
- featranker-0.1.1/LICENSE +21 -0
- featranker-0.1.1/MANIFEST.in +3 -0
- featranker-0.1.1/PKG-INFO +368 -0
- featranker-0.1.1/README.md +350 -0
- featranker-0.1.1/featranker/__init__.py +5 -0
- featranker-0.1.1/featranker/importance.py +415 -0
- featranker-0.1.1/featranker/importance_config.yaml +203 -0
- featranker-0.1.1/featranker.egg-info/PKG-INFO +368 -0
- featranker-0.1.1/featranker.egg-info/SOURCES.txt +13 -0
- featranker-0.1.1/featranker.egg-info/dependency_links.txt +1 -0
- featranker-0.1.1/featranker.egg-info/entry_points.txt +2 -0
- featranker-0.1.1/featranker.egg-info/requires.txt +7 -0
- featranker-0.1.1/featranker.egg-info/top_level.txt +1 -0
- featranker-0.1.1/pyproject.toml +31 -0
- featranker-0.1.1/setup.cfg +4 -0
featranker-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Count Zero
|
|
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,368 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: featranker
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Rank feature importance across multiple ML models.
|
|
5
|
+
Author: CountZero
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: numpy
|
|
11
|
+
Requires-Dist: scikit-learn
|
|
12
|
+
Requires-Dist: pyyaml
|
|
13
|
+
Requires-Dist: tqdm
|
|
14
|
+
Requires-Dist: xgboost
|
|
15
|
+
Requires-Dist: lightgbm
|
|
16
|
+
Requires-Dist: catboost
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# FeatRanker
|
|
20
|
+
|
|
21
|
+
Rank feature importance across multiple ML models using permutation importance.
|
|
22
|
+
|
|
23
|
+
FeatRanker trains a configurable set of scikit-learn, XGBoost, LightGBM, and
|
|
24
|
+
CatBoost models on your data, computes permutation importance for every trained
|
|
25
|
+
model, and returns per-model rankings plus an aggregated average ranking.
|
|
26
|
+
|
|
27
|
+
| Item | Value |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| Package name | `featranker` |
|
|
30
|
+
| Import module | `featranker` |
|
|
31
|
+
| CLI command | `featranker` |
|
|
32
|
+
| Model config | `featranker/importance_config.yaml` |
|
|
33
|
+
| Default prep file | `featureCalc.py` (project root) |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Table of Contents
|
|
38
|
+
|
|
39
|
+
- [Installation](#installation)
|
|
40
|
+
- [How It Works](#how-it-works)
|
|
41
|
+
- [Data Preparation](#data-preparation)
|
|
42
|
+
- [Quick Start](#quick-start)
|
|
43
|
+
- [CLI Reference](#cli-reference)
|
|
44
|
+
- [Python API](#python-api)
|
|
45
|
+
- [Model Configuration](#model-configuration)
|
|
46
|
+
- [Available Models](#available-models)
|
|
47
|
+
- [Output Format](#output-format)
|
|
48
|
+
- [Troubleshooting](#troubleshooting)
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
Install dependencies:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install -r requirements.txt
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Install the package in editable (development) mode:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install -e .
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Or install from PyPI:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install featranker
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Requirements
|
|
73
|
+
|
|
74
|
+
- Python ≥ 3.10
|
|
75
|
+
- numpy, scikit-learn, pyyaml, tqdm, xgboost, lightgbm, catboost
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## How It Works
|
|
80
|
+
|
|
81
|
+
1. **Load data** — A user-defined prep class returns a feature dict with a
|
|
82
|
+
`"label"` key.
|
|
83
|
+
2. **Initialize models** — Model definitions are read from
|
|
84
|
+
`importance_config.yaml` and instantiated for the requested task and group.
|
|
85
|
+
3. **Train models** — Every initialized model is fitted on the feature matrix.
|
|
86
|
+
4. **Rank features** — Permutation importance is computed per model, and an
|
|
87
|
+
overall average ranking is produced.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Data Preparation
|
|
92
|
+
|
|
93
|
+
Before running FeatRanker you need a **prep class** — a Python class with a
|
|
94
|
+
`_calc_features()` method that returns your data as a dict.
|
|
95
|
+
|
|
96
|
+
### Expected return format
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
{
|
|
100
|
+
"feature_1": [v1, v2, v3, ...],
|
|
101
|
+
"feature_2": [v1, v2, v3, ...],
|
|
102
|
+
...
|
|
103
|
+
"label": [y1, y2, y3, ...],
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- Every feature key maps to a list of numeric values.
|
|
108
|
+
- All lists (including `"label"`) must have the same length.
|
|
109
|
+
- The `"label"` key is required.
|
|
110
|
+
|
|
111
|
+
### Where to put it
|
|
112
|
+
|
|
113
|
+
**Option A — Edit the default file (simplest)**
|
|
114
|
+
|
|
115
|
+
Define your class in `featureCalc.py` at the project root. The default class
|
|
116
|
+
name is `prepFeature`, but you can name it anything and select it with
|
|
117
|
+
`--prep-class`.
|
|
118
|
+
|
|
119
|
+
**Option B — Use a separate file (no reinstall needed)**
|
|
120
|
+
|
|
121
|
+
Keep your prep logic in any Python file and point to it at runtime:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
featranker --prep-file ./my_features.py --prep-class MyPrepClass --task clf
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Example prep class
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from sklearn.datasets import load_iris
|
|
131
|
+
|
|
132
|
+
class IrisPrep:
|
|
133
|
+
def _calc_features(self):
|
|
134
|
+
data = load_iris()
|
|
135
|
+
features = {
|
|
136
|
+
data.feature_names[i]: data.data[:, i].tolist()
|
|
137
|
+
for i in range(data.data.shape[1])
|
|
138
|
+
}
|
|
139
|
+
features["label"] = data.target.tolist()
|
|
140
|
+
return features
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Quick Start
|
|
146
|
+
|
|
147
|
+
1. Implement `_calc_features()` in `featureCalc.py` (or your own file).
|
|
148
|
+
2. Run the CLI:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Classification with all model families, using the default prepFeature class
|
|
152
|
+
featranker --task clf --group all
|
|
153
|
+
|
|
154
|
+
# Regression with tree models only, custom prep file and class
|
|
155
|
+
featranker --task reg --group tree \
|
|
156
|
+
--prep-file ./my_features.py --prep-class DiabetesPrep
|
|
157
|
+
|
|
158
|
+
# Save results to a JSON file
|
|
159
|
+
featranker --task clf --group linear --output results
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## CLI Reference
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
featranker --task {clf,reg} [--group {linear,tree,all}]
|
|
168
|
+
[--prep-file PATH] [--prep-class NAME]
|
|
169
|
+
[--output PATH]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
| Flag | Description | Default |
|
|
173
|
+
| --- | --- | --- |
|
|
174
|
+
| `--task` | `clf` (classification) or `reg` (regression) | *required* |
|
|
175
|
+
| `--group` | `linear`, `tree`, or `all` (both) | `all` |
|
|
176
|
+
| `--prep-class` | Name of the prep class to instantiate | `prepFeature` |
|
|
177
|
+
| `--prep-file` | Path to the Python file containing the prep class | `featureCalc.py` in the current working directory |
|
|
178
|
+
| `--output` | File path for JSON output (`.json` appended if missing) | print to stdout |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Python API
|
|
183
|
+
|
|
184
|
+
### Using `FeatureRanker` directly (default prep file)
|
|
185
|
+
|
|
186
|
+
When your default `prepFeature` class lives in `featureCalc.py` at the project
|
|
187
|
+
root:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from featranker import FeatureRanker
|
|
191
|
+
|
|
192
|
+
ranker = FeatureRanker(task="clf", group="all")
|
|
193
|
+
results = ranker.rankFeatures()
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Using `build_ranker` with a custom prep file
|
|
197
|
+
|
|
198
|
+
`build_ranker` is a convenience factory that returns a fully initialized
|
|
199
|
+
`FeatureRanker` instance (features loaded, models trained, ready to rank):
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from featranker import build_ranker
|
|
203
|
+
|
|
204
|
+
ranker = build_ranker(
|
|
205
|
+
task="reg",
|
|
206
|
+
group="tree",
|
|
207
|
+
prep_file="./my_features.py",
|
|
208
|
+
prep_class="DiabetesPrep",
|
|
209
|
+
)
|
|
210
|
+
results = ranker.rankFeatures()
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Constructor parameters
|
|
214
|
+
|
|
215
|
+
| Parameter | Type | Description |
|
|
216
|
+
| --- | --- | --- |
|
|
217
|
+
| `task` | `"clf"` \| `"reg"` | Classification or regression |
|
|
218
|
+
| `group` | `"linear"` \| `"tree"` \| `"all"` | Which model family to use |
|
|
219
|
+
| `prep_file` | `str` or `None` | Path to prep file (defaults to `featureCalc.py`) |
|
|
220
|
+
| `prep_class` | `str` | Name of the prep class (defaults to `"prepFeature"`) |
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Model Configuration
|
|
225
|
+
|
|
226
|
+
Models are defined in `featranker/importance_config.yaml`, organized by task
|
|
227
|
+
and group:
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
classification:
|
|
231
|
+
linear:
|
|
232
|
+
- name: logistic_regression
|
|
233
|
+
import: sklearn.linear_model
|
|
234
|
+
class: LogisticRegression
|
|
235
|
+
params:
|
|
236
|
+
max_iter: 2000
|
|
237
|
+
tree:
|
|
238
|
+
- name: random_forest
|
|
239
|
+
import: sklearn.ensemble
|
|
240
|
+
class: RandomForestClassifier
|
|
241
|
+
params:
|
|
242
|
+
random_state: 42
|
|
243
|
+
|
|
244
|
+
regression:
|
|
245
|
+
linear:
|
|
246
|
+
- ...
|
|
247
|
+
tree:
|
|
248
|
+
- ...
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Each entry has four fields:
|
|
252
|
+
|
|
253
|
+
| Field | Description |
|
|
254
|
+
| --- | --- |
|
|
255
|
+
| `name` | Display name used in output |
|
|
256
|
+
| `import` | Python module to import (e.g., `sklearn.ensemble`) |
|
|
257
|
+
| `class` | Class name to instantiate from that module |
|
|
258
|
+
| `params` | Dict of keyword arguments passed to the constructor (optional) |
|
|
259
|
+
|
|
260
|
+
Edit this file to add, remove, or tune models. Changes take effect on the next
|
|
261
|
+
run — no reinstall required.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Available Models
|
|
266
|
+
|
|
267
|
+
### Classification — Linear
|
|
268
|
+
|
|
269
|
+
| Name | Class |
|
|
270
|
+
| --- | --- |
|
|
271
|
+
| `logistic_regression` | `LogisticRegression` |
|
|
272
|
+
| `logistic_regression_l1` | `LogisticRegression` (L1) |
|
|
273
|
+
| `logistic_regression_l2` | `LogisticRegression` (L2) |
|
|
274
|
+
| `logistic_regression_elasticnet` | `LogisticRegression` (ElasticNet) |
|
|
275
|
+
| `linear_svm` | `LinearSVC` |
|
|
276
|
+
| `sgd_classifier` | `SGDClassifier` |
|
|
277
|
+
| `ridge_classifier` | `RidgeClassifier` |
|
|
278
|
+
| `perceptron` | `Perceptron` |
|
|
279
|
+
| `passive_aggressive` | `PassiveAggressiveClassifier` |
|
|
280
|
+
| `lda` | `LinearDiscriminantAnalysis` |
|
|
281
|
+
| `qda` | `QuadraticDiscriminantAnalysis` |
|
|
282
|
+
| `naive_bayes_gaussian` | `GaussianNB` |
|
|
283
|
+
| `naive_bayes_bernoulli` | `BernoulliNB` |
|
|
284
|
+
| `naive_bayes_multinomial` | `MultinomialNB` |
|
|
285
|
+
| `pls_da` | `PLSRegression` |
|
|
286
|
+
|
|
287
|
+
### Classification — Tree
|
|
288
|
+
|
|
289
|
+
| Name | Class |
|
|
290
|
+
| --- | --- |
|
|
291
|
+
| `decision_tree` | `DecisionTreeClassifier` |
|
|
292
|
+
| `random_forest` | `RandomForestClassifier` |
|
|
293
|
+
| `extra_trees` | `ExtraTreesClassifier` |
|
|
294
|
+
| `bagging_tree` | `BaggingClassifier` |
|
|
295
|
+
| `adaboost` | `AdaBoostClassifier` |
|
|
296
|
+
| `gradient_boosting` | `GradientBoostingClassifier` |
|
|
297
|
+
| `hist_gradient_boosting` | `HistGradientBoostingClassifier` |
|
|
298
|
+
| `xgboost` | `XGBClassifier` |
|
|
299
|
+
| `catboost` | `CatBoostClassifier` |
|
|
300
|
+
|
|
301
|
+
### Regression — Linear
|
|
302
|
+
|
|
303
|
+
| Name | Class |
|
|
304
|
+
| --- | --- |
|
|
305
|
+
| `linear_regression` | `LinearRegression` |
|
|
306
|
+
| `ridge_regression` | `Ridge` |
|
|
307
|
+
| `lasso_regression` | `Lasso` |
|
|
308
|
+
| `elasticnet_regression` | `ElasticNet` |
|
|
309
|
+
| `elasticnet_cv_regression` | `ElasticNetCV` |
|
|
310
|
+
| `pls_regression` | `PLSRegression` |
|
|
311
|
+
| `huber_regression` | `HuberRegressor` |
|
|
312
|
+
| `ransac_regression` | `RANSACRegressor` |
|
|
313
|
+
| `kernel_ridge_regression` | `KernelRidge` |
|
|
314
|
+
| `svr_regression` | `SVR` |
|
|
315
|
+
|
|
316
|
+
### Regression — Tree
|
|
317
|
+
|
|
318
|
+
| Name | Class |
|
|
319
|
+
| --- | --- |
|
|
320
|
+
| `decision_tree_regressor` | `DecisionTreeRegressor` |
|
|
321
|
+
| `random_forest_regressor` | `RandomForestRegressor` |
|
|
322
|
+
| `extra_trees_regressor` | `ExtraTreesRegressor` |
|
|
323
|
+
| `adaboost_regressor` | `AdaBoostRegressor` |
|
|
324
|
+
| `gradient_boosting_regressor` | `GradientBoostingRegressor` |
|
|
325
|
+
| `hist_gradient_boosting_regressor` | `HistGradientBoostingRegressor` |
|
|
326
|
+
| `xgboost_regressor` | `XGBRegressor` |
|
|
327
|
+
| `catboost_regressor` | `CatBoostRegressor` |
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Output Format
|
|
332
|
+
|
|
333
|
+
The result is a dict (or JSON object) keyed by model name, with an additional
|
|
334
|
+
`"average"` entry that aggregates across all models. Each value is a list of
|
|
335
|
+
single-entry dicts sorted by score in descending order. Scores are rounded to
|
|
336
|
+
four decimal places.
|
|
337
|
+
|
|
338
|
+
```json
|
|
339
|
+
{
|
|
340
|
+
"logistic_regression": [
|
|
341
|
+
{"feature_a": 0.1234},
|
|
342
|
+
{"feature_b": 0.0567},
|
|
343
|
+
{"feature_c": 0.0012}
|
|
344
|
+
],
|
|
345
|
+
"random_forest": [
|
|
346
|
+
{"feature_b": 0.0890},
|
|
347
|
+
{"feature_a": 0.0745},
|
|
348
|
+
{"feature_c": 0.0023}
|
|
349
|
+
],
|
|
350
|
+
"average": [
|
|
351
|
+
{"feature_a": 0.0990},
|
|
352
|
+
{"feature_b": 0.0729},
|
|
353
|
+
{"feature_c": 0.0018}
|
|
354
|
+
]
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Troubleshooting
|
|
361
|
+
|
|
362
|
+
| Symptom | Cause | Fix |
|
|
363
|
+
| --- | --- | --- |
|
|
364
|
+
| `Prep file not found` | FeatRanker can't locate `featureCalc.py` | Run the command from the directory that contains `featureCalc.py`, or pass an explicit path with `--prep-file` |
|
|
365
|
+
| `AttributeError: … has no attribute 'X'` | The prep class name doesn't match what's in the file | Check spelling of `--prep-class` against the class defined in your prep file |
|
|
366
|
+
| `'label' key missing` | `_calc_features()` didn't include a `"label"` entry | Add `features["label"] = ...` to your return dict |
|
|
367
|
+
| Feature length mismatch | Feature lists have different lengths | Ensure every feature list and `"label"` have the same number of elements |
|
|
368
|
+
| Model training errors (printed, not fatal) | A model failed to converge or doesn't support the data | Check the printed warning; consider removing or tuning that model in `importance_config.yaml` |
|