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.
@@ -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,3 @@
1
+ include README.md
2
+ include LICENSE
3
+ include featranker/importance_config.yaml
@@ -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` |