Training and inference often run at different times or in different processes, so a fitted estimator needs a durable handoff between them. The skops.io format stores supported scikit-learn objects without relying on the automatic code execution behavior of pickle-based formats.
A .skops file is not safe merely because of its extension. The loader rejects types that are not trusted by default unless they appear in the trusted list, so compare every reported type with the training code before allowing it to be reconstructed.
The loading environment should use the same scikit-learn, NumPy, SciPy, and skops versions as the training environment. A built-in HistGradientBoostingClassifier on the Iris dataset keeps the trust review empty and provides deterministic predictions for the final round-trip check.
Steps to save and load a scikit-learn model with skops:
- Install scikit-learn and skops in the active Python environment.
$ python -m pip install scikit-learn skops
Matching dependency versions across training and inference prevent compatibility failures when the artifact is reused later.
- Create save-load-skops.py with the model setup and .skops artifact dump.
- 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)
- Append the unknown-type inspection below the sio.dump() call in save-load-skops.py.
unknown_types = sio.get_untrusted_types(file=model_path) print(f"artifact: {model_path}") print(f"untrusted types: {unknown_types}")
- Run save-load-skops.py to inspect the saved artifact's unknown types.
$ python save-load-skops.py artifact: iris-hist-gradient.skops untrusted types: []
- Review every reported type against the classes imported by the model's training code.
An empty list requires no additions. A name that cannot be traced to the known training code leaves the artifact unapproved for loading.
- Define trusted_types below the inspection output with only the approved type names.
trusted_types = []
The built-in estimator reports no unknown types, so its reviewed list stays empty. A custom estimator may require fully qualified type names that passed the preceding review.
- Append the fail-closed type comparison below trusted_types.
if set(unknown_types) != set(trusted_types): raise SystemExit("Review every untrusted type before loading the artifact.")
- Append the model load and prediction comparison below the type guard in save-load-skops.py.
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}")
- Run save-load-skops.py for the round-trip prediction check.
$ 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.
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.