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.
$ python -m pip install scikit-learn skops
Matching dependency versions across training and inference prevent compatibility failures when the artifact is reused later.
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}")
$ python save-load-skops.py artifact: iris-hist-gradient.skops untrusted types: []
An empty list requires no additions. A name that cannot be traced to the known training code leaves the artifact unapproved for loading.
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.
if set(unknown_types) != set(trusted_types): raise SystemExit("Review every untrusted type before loading the artifact.")
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}")
$ 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.