Skip to main content

Serialize fitted scikit-learn models to safetensors + JSON

Project description

skeights logo

skeights

Serialize fitted scikit-learn models to safetensors + JSON.

No pickle. No joblib. Just weights and config.

Why?

Pickle is the default way to save sklearn models, but it's insecure (arbitrary code execution on load), fragile (breaks across versions), and opaque (you can't inspect what's inside without loading it).

skeights splits a model into two layers:

  • .json: hyperparameters, fitted scalars, and structural config. Human-readable, greppable, diffable. You can inspect how a model is configured without deserializing it or running any code.
  • .safetensors: the numeric bulk (coefficients, tree split arrays, leaf values) as dense typed arrays in the safetensors format. Typed binary arrays instead of numbers encoded as text, which matters most for large tree ensembles.

Why safetensors specifically: it is memory-mappable, language-agnostic, and widely adopted across the ML ecosystem. The weight payload is readable outside Python and outside skeights. Loading safetensors does not execute arbitrary code.

[!NOTE] skeights does not use pickle or joblib. The JSON state file names the Python classes to instantiate (e.g. sklearn.linear_model.Ridge), but the loader only allows imports from sklearn, lightgbm, and xgboost. Arbitrary module imports from crafted JSON files are blocked.

When to use something else

There are other tools for serializing sklearn models. Here is when to reach for them instead.

skops is the actively maintained, scikit-learn-adjacent option for secure persistence, referenced in sklearn's own docs. It covers pipelines, XGBoost, LightGBM, has compression, model inspection, and Hugging Face Hub integration. Reach for skops if you want the broadest, most battle-tested secure persistence and do not need to inspect model config without loading it. Use skeights if you want human-readable, diffable model configuration.

sklearn-migrator is purpose-built for loading models across different sklearn versions, with a peer-reviewed paper behind it. Reach for it if cross-version migration is your problem. skeights does not guarantee cross-version support. Note that sklearn-migrator does not yet cover pipelines, XGBoost, or LightGBM, which skeights does.

Note: the feature descriptions of skops and sklearn-migrator above reflect their state as of mid-2026. Check their current docs for the latest.

Install

pip install skeights

Compatibility

Requires scikit-learn >= 1.5, LightGBM >= 4.4 (optional), XGBoost >= 2.1 (optional). CI tests against scikit-learn 1.5, 1.6, and latest; LightGBM 4.4 and latest; XGBoost 2.1 and latest.

Saved models are forward-compatible on a best-effort basis: we test loading fixtures saved on older library versions with newer ones, but don't guarantee cross-version compatibility. skeights will emit a warning when loading a model saved with a different library version.

Usage

import skeights
from sklearn.linear_model import Ridge
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

# Fit your model as usual
pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("model", Ridge(alpha=0.1)),
])
pipe.fit(X_train, y_train)

# Save
skeights.save(pipe, "model.safetensors", "model.json")

# Load and predict
loaded = skeights.load("model.safetensors", "model.json")
predictions = loaded.predict(X_test)

API

Function Description
save(estimator: BaseEstimator, arrays_path: str, state_path: str, format: str | None = None) -> None Serialize to safetensors + JSON files
load(arrays_path: str, state_path: str) -> BaseEstimator Load from files, return fitted estimator
serialize(estimator: BaseEstimator, format: str | None = None) -> tuple[dict, dict] Return (state_dict, arrays_dict) in memory
deserialize(state: dict, arrays: dict) -> BaseEstimator Reconstruct estimator from dicts
get_model_params(estimator: BaseEstimator) -> dict Recursively extract hyperparameters
set_model_params(estimator: BaseEstimator, params: dict) -> None Recursively set hyperparameters

Supported estimators

Status Estimators
Supported Ridge, Lasso, LinearRegression, LogisticRegression, and other linear models. MLPRegressor/MLPClassifier. DecisionTreeRegressor/Classifier, RandomForestRegressor/Classifier, GradientBoostingRegressor/Classifier, HistGradientBoostingRegressor/Classifier. LGBMRegressor/Classifier (columnar tensors or native text), XGBRegressor/Classifier (columnar tensors or native JSON). GaussianProcessRegressor/Classifier (including composite kernels). TransformedTargetRegressor. StandardScaler, MinMaxScaler, RobustScaler. Pipeline composed of any of the above.
Not yet implemented CatBoost, other ensemble meta-estimators (VotingClassifier, StackingRegressor, etc.), PCA and other decomposition transforms. Open an issue or PR if you need any of these.
Not planned Cross-version sklearn migration (use sklearn-migrator). General-purpose secure persistence with broad estimator coverage (use skops).

Tree model formats

LightGBM and XGBoost models are serialized as columnar tensors by default: split features, thresholds, child pointers, and leaf values are stored as typed numpy arrays in safetensors, with only small scalar config (objective, feature names, etc.) in JSON.

This gives 30-85% smaller files compared to the native format and makes the JSON human-readable. To use the native format instead:

skeights.save(model, "model.safetensors", "model.json", format="native")

Artifacts saved with older versions of skeights (before columnar support) are loaded transparently, no migration needed.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skeights-0.3.0.tar.gz (2.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skeights-0.3.0-py3-none-any.whl (27.8 kB view details)

Uploaded Python 3

File details

Details for the file skeights-0.3.0.tar.gz.

File metadata

  • Download URL: skeights-0.3.0.tar.gz
  • Upload date:
  • Size: 2.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skeights-0.3.0.tar.gz
Algorithm Hash digest
SHA256 2621838d5df8fa872c11720a303dad71ab84e13974c012de514ac88d852bef5d
MD5 7280273325ad034cad4994722939dc8e
BLAKE2b-256 74d23748e5530e5d07abc402be24cff3a2e98db9083c60d27d60bbe6353eeb8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for skeights-0.3.0.tar.gz:

Publisher: publish.yml on carbon-re/skeights

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file skeights-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: skeights-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 27.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skeights-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e4f41dd856b0a1993b69f5a93e672c4470c5683623698cc52aa71b31db2c0444
MD5 f52e4745d05f8897aa4975527bde6451
BLAKE2b-256 98b318fa2bc91f607a6369ccc6c98c20ffc256018f0e1d7ba02077b0e196742a

See more details on using hashes here.

Provenance

The following attestation bundles were made for skeights-0.3.0-py3-none-any.whl:

Publisher: publish.yml on carbon-re/skeights

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page