Adaptive GRASP-based feature selection with self-tuning subset size
Project description
A-GRASPQ-FS
Adaptive GRASPQ Feature Selection with self-tuning subset size
A-GRASPQ-FS is a scikit-learn compatible feature selector based on a reactive GRASP metaheuristic. It jointly solves two decisions that are usually treated separately:
- how many features should be selected for a given dataset and classifier; and
- which features should compose that subset.
Instead of requiring a fixed value of k, A-GRASPQ-FS searches over a cardinality interval and adapts the probability of choosing each subset size according to the validation performance observed during the search.
The original command-line research prototype used in the ISCC 2026 paper is still available in main.py. Version 1.0 adds a production-oriented Python package in src/agraspqfs/, with a plug-and-play API for scikit-learn workflows.
Associated paper
This repository accompanies the ISCC 2026 paper:
Vagner E. Quincozes, Silvio E. Quincozes, Célio Albuquerque, Diego Passos, and Daniel Mossé. Adaptive Feature Selection with Self-Tuning Subset Size for Intrusion Detection. ISCC 2026, Algarve, Portugal, 2026.
If you use this software in academic work, please cite the paper and/or the software release. Citation files are provided in CITATION.cff and docs/CITATION.md.
Highlights in v1.0
- scikit-learn compatible transformer:
fit,transform,fit_transform,get_support,get_feature_names_out. - Works with any scikit-learn compatible classifier as the subset evaluator.
- Joint optimization of subset size and feature composition.
- Presets for different budgets:
fast,balanced,robust, andpaper. - In-memory cache to avoid repeated evaluations of the same subset.
- Explicit computational controls:
max_evaluations,time_budget, andearly_stopping_rounds. - Exploratory evaluation on a row sample via
evaluation_sample_size. - Final full-data re-evaluation of elite candidate subsets.
- CLI command:
agraspqfs. - Unit tests, examples, GitHub Actions workflow, citation metadata, and release checklist.
Installation
From the repository root:
pip install -e .
For development and tests:
pip install -e ".[dev]"
pytest
Optional XGBoost support:
pip install -e ".[xgboost]"
Minimal usage
from agraspqfs import AGraspQFeatureSelector
from sklearn.naive_bayes import GaussianNB
selector = AGraspQFeatureSelector(
estimator=GaussianNB(),
preset="fast",
min_features=2,
max_features=15,
random_state=42,
)
X_selected = selector.fit_transform(X, y)
print(selector.selected_features_)
print(selector.n_features_selected_)
print(selector.best_score_)
Pipeline usage
from agraspqfs import AGraspQFeatureSelector
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
pipe = Pipeline([
("fs", AGraspQFeatureSelector(
estimator=GaussianNB(),
preset="balanced",
min_features=2,
max_features=20,
random_state=42,
)),
("clf", LogisticRegression(max_iter=2000)),
])
pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)
The estimator inside AGraspQFeatureSelector is used to evaluate feature subsets. The classifier after the selector in the pipeline can be the same model or a different one.
CLI usage
agraspqfs --csv data/hibrid_dataset_GOOSE_train.csv --target class --estimator nb --preset fast --min-features 2 --max-features 15 --output results/agraspqfs_selection.json --history-csv results/agraspqfs_history.csv
The CLI prints and saves a JSON report containing selected features, internal validation score, external holdout score, number of evaluations, cache hits, and elapsed time.
Presets
| Preset | Intended use | Behavior |
|---|---|---|
fast |
notebooks, smoke tests, quick exploration | fewer evaluations, holdout validation, row sampling |
balanced |
default practical use | moderate budget, 3-fold CV, partial row sampling |
robust |
slower experiments | larger budget, 5-fold CV, full exploratory data |
paper |
compatibility with the research-style workflow | conservative budget inspired by the original prototype |
Explicit parameters override preset values.
Example:
selector = AGraspQFeatureSelector(
preset="fast",
max_evaluations=100,
time_budget=60,
early_stopping_rounds=30,
random_state=42,
)
Main parameters
| Parameter | Description |
|---|---|
estimator |
Classifier used to evaluate candidate subsets. Defaults to GaussianNB. |
scoring |
Any scikit-learn scoring name, e.g., f1_weighted, accuracy, roc_auc_ovr. |
min_features, max_features |
Minimum and maximum subset size. |
rcl_size |
Number of ranked candidate features considered by the metaheuristic. |
ranking_method |
mutual_info, variance, random, none, or callable. |
evaluation_sample_size |
Fraction of rows used in exploratory evaluations. |
cv |
Internal CV. Use None for holdout validation. |
max_evaluations |
Maximum number of non-cached subset evaluations. |
time_budget |
Time budget in seconds. |
cache |
Reuse repeated subset scores. |
refit |
If True, fit estimator_ on the selected features after selection. |
Main outputs
After fit, the selector exposes:
selector.selected_features_ # names of selected features
selector.selected_indices_ # integer indices
selector.n_features_selected_ # selected subset size
selector.support_ # boolean mask
selector.best_score_ # best internal score among final candidates
selector.baseline_score_ # internal score with all features
selector.history_ # pandas DataFrame with evaluation trace
selector.size_weights_ # final adaptive cardinality weights
selector.n_evaluations_ # expensive evaluations actually computed
selector.n_cache_hits_ # repeated evaluations avoided by cache
selector.stop_reason_ # completed, budget_exhausted or early_stopping
Examples
Run:
python examples/quickstart.py
python examples/pipeline_example.py
python examples/benchmark_small.py
A minimal notebook is available at examples/agraspqfs_demo.ipynb.
Legacy research prototype
The original scripts are still available:
python main.py -d ereninho -a nb -rcl 10 -is 5 -pq 10 -lc 50 -cc 50
Baseline scripts are also preserved:
python baselines.py -d ereninho -m rfecv -a nb
For new users, prefer the package API or the agraspqfs CLI.
Repository structure
.
├── src/agraspqfs/ # Production package
│ ├── selector.py # AGraspQFeatureSelector
│ ├── cli.py # agraspqfs command
│ └── _version.py
├── tests/ # Unit tests
├── examples/ # Quickstart, pipeline, benchmark and notebook examples
├── docs/ # Documentation and release checklist
├── .github/workflows/ # CI and PyPI publishing workflows
├── main.py # Legacy research prototype
├── baselines.py # Baseline methods
├── utils.py # Legacy utilities
├── priority_queue.py # Legacy queue implementation
├── data/ # Example/research datasets
├── results/ # Runtime outputs, ignored except .gitkeep
├── CITATION.cff # Citation metadata
├── LICENSE # MIT license
├── pyproject.toml # Packaging metadata
└── README.md
Notes on data preprocessing
A-GRASPQ-FS expects the feature matrix passed to fit to be numeric, as is common for scikit-learn estimators and mutual information ranking. For categorical features, use a preprocessing pipeline before the selector, for example OneHotEncoder or ColumnTransformer.
The CLI includes automatic preprocessing for CSV files: numeric columns are scaled and categorical columns are one-hot encoded.
Performance note
A-GRASPQ-FS is a wrapper method and can be computationally expensive because it repeatedly evaluates machine learning models. Use preset="fast", max_evaluations, time_budget, early_stopping_rounds, and evaluation_sample_size to control cost. See docs/PERFORMANCE.md.
License
This project is released under the MIT License. See LICENSE.
The license permits reuse, modification and distribution. For academic use, please cite the associated ISCC 2026 paper and/or the software release as described in CITATION.cff.
Citation
@inproceedings{quincozes2026agraspqfs,
title = {Adaptive Feature Selection with Self-Tuning Subset Size for Intrusion Detection},
author = {Quincozes, Vagner E. and Quincozes, Silvio E. and Albuquerque, Célio and Passos, Diego and Mossé, Daniel},
booktitle = {Proceedings of ISCC 2026},
address = {Algarve, Portugal},
year = {2026}
}
Update the BibTeX with DOI/pages/publisher once the final proceedings metadata is available.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agraspqfs-1.0.0.tar.gz.
File metadata
- Download URL: agraspqfs-1.0.0.tar.gz
- Upload date:
- Size: 692.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5e5e3a8d38842ba45a2deb949bbc0540a89210f1bfe8e503ac803144a117f7e
|
|
| MD5 |
00a0d21429d69e497871365fd3b76e7e
|
|
| BLAKE2b-256 |
bbd1a101c7c608a95bbb86f5dd8448c790d9a0fb8b0d12d2231a0300600dcf2e
|
Provenance
The following attestation bundles were made for agraspqfs-1.0.0.tar.gz:
Publisher:
publish.yml on vagnerereno/A-GRASPQ-FS
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agraspqfs-1.0.0.tar.gz -
Subject digest:
d5e5e3a8d38842ba45a2deb949bbc0540a89210f1bfe8e503ac803144a117f7e - Sigstore transparency entry: 2070854242
- Sigstore integration time:
-
Permalink:
vagnerereno/A-GRASPQ-FS@818f8135f1e14320675ba26df5d6cc3b08906e9f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/vagnerereno
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@818f8135f1e14320675ba26df5d6cc3b08906e9f -
Trigger Event:
release
-
Statement type:
File details
Details for the file agraspqfs-1.0.0-py3-none-any.whl.
File metadata
- Download URL: agraspqfs-1.0.0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
730e922f8af802a6ec664f44d2e7d1046a230b01fa122c156413865663a90f5c
|
|
| MD5 |
214b76ba9ecb2504ac8434558db87749
|
|
| BLAKE2b-256 |
a014c51998d422eacf05bddcfa113f634a5663a29ce3fea6a493fd18a885ed79
|
Provenance
The following attestation bundles were made for agraspqfs-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on vagnerereno/A-GRASPQ-FS
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agraspqfs-1.0.0-py3-none-any.whl -
Subject digest:
730e922f8af802a6ec664f44d2e7d1046a230b01fa122c156413865663a90f5c - Sigstore transparency entry: 2070854268
- Sigstore integration time:
-
Permalink:
vagnerereno/A-GRASPQ-FS@818f8135f1e14320675ba26df5d6cc3b08906e9f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/vagnerereno
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@818f8135f1e14320675ba26df5d6cc3b08906e9f -
Trigger Event:
release
-
Statement type: