A fitted scikit-learn estimator often needs to move from training code into a later scoring job without using a raw pickle artifact. skops.io saves supported estimators in a format that can be inspected for unknown types before Python reconstructs the object.
The saved artifact still belongs to the Python stack that created it. Keep the training and loading environments on matching scikit-learn, NumPy, SciPy, and skops versions, and store the training code or dependency lock file with the model when the artifact is shared.
A built-in HistGradientBoostingClassifier on the Iris dataset keeps the trust review at an empty extra-type list. Models that contain third-party estimators or custom components can report type names; inspect those names against the training code and trust only classes or functions expected in that artifact.
Steps to save and load a scikit-learn model with skops:
- Install scikit-learn and skops in the Python environment that will train and load the model.
$ python -m pip install scikit-learn skops
Use the same virtual environment, container image, or dependency lock for training and loading when the artifact will be reused later.
- Create the smoke script that trains an estimator, saves a .skops file, inspects unknown types, and reloads only after the review is empty.
- save-load-skops.py
from pathlib import Path import skops.io as sio from sklearn.datasets import load_iris from sklearn.ensemble import HistGradientBoostingClassifier from sklearn.model_selection import train_test_split model_path = Path("iris-hist-gradient.skops") X, y = load_iris(return_X_y=True) X_train, X_test, y_train, _ = train_test_split( X, y, random_state=42, stratify=y, ) model = HistGradientBoostingClassifier(random_state=42).fit(X_train, y_train) expected = model.predict(X_test[:5]).tolist() sio.dump(model, model_path) unknown_types = sio.get_untrusted_types(file=model_path) print(f"artifact: {model_path}") print(f"untrusted types: {unknown_types}") if unknown_types: raise SystemExit("Review these types before loading the artifact.") trusted_types = [] loaded = sio.load(model_path, trusted=trusted_types) actual = loaded.predict(X_test[:5]).tolist() print(f"expected predictions: {expected}") print(f"loaded predictions: {actual}") print(f"predictions match: {actual == expected}")
If unknown_types prints names, compare them with the model training code and set trusted_types to only the reviewed names before calling sio.load().
- Run the smoke script and confirm the loaded model reproduces the reference predictions.
$ python save-load-skops.py artifact: iris-hist-gradient.skops untrusted types: [] expected predictions: [0, 1, 1, 1, 0] loaded predictions: [0, 1, 1, 1, 0] predictions match: True
The empty untrusted types list means skops did not require extra user-trusted classes beyond its defaults for this built-in estimator.
- Remove the smoke-test artifact when the check was only a local validation run.
$ rm iris-hist-gradient.skops
Keep real .skops files only in a controlled artifact store. Loading a model from an untrusted source is still a security decision, even when the format is designed for inspection.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.