mloptune
mloptune is a lightweight fine-tuning framework for scikit-learn-compatible
models. Describe an experiment in one configuration object, call run, and get
back a tuned, refitted model together with an honest test score, the Optuna
study behind it, and the seed that reproduces all of it.
- Author: Ziyuan Huang
- Affiliation: Microbiology & Microbiome Dynamic AI Hub, University of Massachusetts, Worcester
Features
- One call, whole workflow. Stratified train / validation / test split, Optuna study on the validation split, refit of the best hyperparameters on train + validation, one final score on the untouched test split.
- Reproducible by name. The
experiment_nameis hashed into the seed for the splits, the sampler and every estimator that acceptsrandom_state. The same name gives the same run on any machine or operating system. - Any scikit-learn classifier or regressor, addressed by class name, plus
XGBClassifierandXGBRegressorwhenxgboostis installed. - Any scikit-learn scorer by name (
roc_auc,f1_macro,neg_root_mean_squared_error, ...) or as amake_scorercallable. - Fail fast. The config validates itself, model names are checked against the problem type, and hyperparameter names are checked against the estimator's constructor before any training starts.
- Fail soft during the study. A hyperparameter combination that raises costs one failed Optuna trial, not the run.
- Works with NumPy arrays, pandas DataFrames, lists and scipy sparse matrices.
Installation
From PyPI:
pip install mloptune
pip install "mloptune[test]" # plus pytest
The latest development version straight from GitHub (no clone needed):
pip install "git+https://github.com/melhzy/MLFactory.git"
pip install "mloptune[test] @ git+https://github.com/melhzy/MLFactory.git" # plus pytest
Or from a local checkout, for development:
git clone https://github.com/melhzy/MLFactory.git
cd MLFactory
pip install -e .[test]
Requires Python 3.10 or newer. On macOS, XGBoost needs the OpenMP runtime
(brew install libomp); without it the XGBoost aliases are simply absent and
everything else works.
Quick start
from sklearn.datasets import load_iris
from mloptune import FineTuneConfig, FineTuner
dataset = load_iris()
config = FineTuneConfig(
model_name="RandomForestClassifier",
problem_type="classification",
experiment_name="iris-demo",
search_space={
"n_estimators": {"type": "int", "low": 10, "high": 30},
"max_depth": {"type": "int", "low": 2, "high": 5},
},
n_trials=3,
)
result = FineTuner(config).run(dataset.data, dataset.target)
print(result.best_params)
print(result.test_score)
print(result.study.trials_dataframe()) # every configuration that was evaluated
Configuration reference
| Field | Default | Meaning |
|---|---|---|
model_name |
required | scikit-learn class name, or XGBClassifier / XGBRegressor |
problem_type |
required | "classification" or "regression"; the model must match |
experiment_name |
required | Free text; hashed into the seed |
search_space |
{} |
Hyperparameters to tune (see below); empty means fit model_kwargs as-is |
n_trials |
10 |
Number of Optuna trials |
n_startup_trials |
Optuna default (10) | Random trials before TPE starts modelling |
model_kwargs |
{} |
Fixed constructor arguments for every candidate |
scoring |
accuracy / neg_mean_squared_error |
Any scikit-learn scorer name or callable |
test_size, validation_size |
0.2, 0.2 |
Fractions of the whole dataset |
Search-space entries are {"type": "int", "low", "high", "step"?},
{"type": "float", "low", "high", "step"?, "log"?} or
{"type": "categorical", "choices": [...]}.
run returns a FineTuneResult with seed, best_params,
validation_score, test_score, split_sizes, the fitted model and the
Optuna study (None when no search space was given).
How tuning works
FineTuner.run follows the holdout-validation recipe from Hands-On Machine
Learning: the data is split into train / validation / test (stratified for
classification), every Optuna trial fits on the training split and is scored
on the validation split, the best hyperparameters are refit on train +
validation, and that final model is scored once on the test split.
Two things to keep in mind:
validation_scoreis the best ofn_trialsscores on a single validation split, so it is optimistically biased;test_scoreis the honest estimate.- Optuna's TPE sampler starts with
n_startup_trialsrandom trials (default 10). With the defaultn_trials=10the study is therefore plain random search. Raisen_trialsor setn_startup_trialslower to get model-based suggestions.
To evaluate the final model with any other metric or plot, rebuild the exact
test rows with split_dataset(X, y, test_size=..., validation_size=..., random_state=result.seed, stratify=y) (drop stratify for regression).
Tutorials
Six executed Jupyter notebooks in tutorials/ take you from a
first run to a trustworthy evaluation. Start with
01_quickstart; the
index describes the rest:
- Quickstart: the holdout recipe, config, result, using the fitted model
- Search spaces: spec types, the Optuna study, startup trials, failing trials
- Classification: metrics for imbalanced data, confusion matrices on the test split, multiclass, string labels
- Regression: RMSE, baselines, confidence intervals, pandas inputs, multi-output
- Models and XGBoost: comparing model families, XGBoost, meta-estimators, edge cases
- Reproducibility and pitfalls: seeds, validation optimism, split noise, saving models
Limitations
- No preprocessing pipelines:
model_namerefers to a single estimator, so scale-sensitive models run on raw features. - A single validation split, not cross-validation. Small datasets give noisy estimates; tutorial 06 shows how to measure that noise.
XGBClassifierneeds integer-encoded class labels; scikit-learn models accept strings directly.
Development
pip install -e .[test]
pytest
The test suite covers the split, the workflow with and without a search
space, XGBoost seeding, reproducibility, config validation, model/problem
type checks, failing-trial handling, sparse inputs and the FIPS seed fallback.
The XGBoost test is skipped when xgboost cannot be loaded.
Releasing to PyPI
Bump version in pyproject.toml, then build and upload with a PyPI API
token (pip install build twine once):
python -m build # writes dist/mloptune-<version>.tar.gz and .whl
python -m twine check dist/*
python -m twine upload dist/* # username: __token__, password: the API token
Upload to TestPyPI first with --repository testpypi if you want to rehearse.
Platform support
The framework is pure Python; everything platform-specific lives in its dependencies, which all publish binary wheels for the platforms below.
| Platform | Status |
|---|---|
| macOS Apple Silicon (arm64) | Test suite run natively |
| macOS Intel (x86_64) | Test suite run under Rosetta 2 |
| Linux x86_64 and aarch64 | Test suite run in python:3.12-slim containers |
| Windows x86_64 and ARM64 | Wheels resolve for all dependencies; not executed |
Python 3.10 through 3.14 resolve on every platform except Windows ARM64,
which needs Python 3.12 or newer (older interpreters lack ARM64 wheels for
xgboost, scikit-learn or pyyaml). Seeds, chosen hyperparameters and
scores were identical across macOS arm64, Linux arm64 and Linux x86_64 for
the quick-start example. Notes:
- macOS needs
libompfor XGBoost (see above); Windows needs the MSVC runtime, which XGBoost's wheels expect to be present. - The experiment seed is derived with MD5. On FIPS-mode Linux, where the
seedhashpackage's MD5 call is rejected, the framework falls back to the same derivation withusedforsecurity=False, so seeds stay identical.
License
MIT. See LICENSE.
Metadata
Release files for mloptune 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mloptune-1.0.1.tar.gz | 12.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mloptune-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.6 kB
Release files / mloptune-1.0.1.tar.gz
| Download URL | mloptune-1.0.1.tar.gz |
|---|---|
| Size | 12.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d074b83356b37b4b244d127cc549fba7cf7f5b4d66db57ef9217e6f4a8240424
|
|
BLAKE2b-256 checksum How to use checksums |
574a0b7a288342ee5f690b50717c12013e74d225d1828b2e7895cc78799128bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / mloptune-1.0.1-py3-none-any.whl
| Download URL | mloptune-1.0.1-py3-none-any.whl |
|---|---|
| Size | 10.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b643af1089670a00a4511fb83b94b29216e75c6f6be5c67888e1b9be135ccf82
|
|
BLAKE2b-256 checksum How to use checksums |
d69b5dd3c9df4e9585c40b4397be00b3a297c28782f3fb564f865b3b9eec25fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Security for mloptune 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.