Serialized Model Format#
SerializationManager.serialize()/SklearnSerializer.serialize() produce a plain Python
dict (JSON-serializable by default via JSONConverter, or pickled via PickleConverter -
see Security for why JSON is
generally the safer choice). This page documents that dict’s shape.
Top-level fields#
Field |
Type |
Meaning |
|---|---|---|
|
|
The model’s class name, e.g. |
|
|
The estimator’s constructor parameters, from |
|
|
|
|
|
Like |
|
|
The model’s fitted state - every public attribute following scikit-learn’s trailing-underscore convention ( |
|
|
Like |
|
|
Like |
|
|
The scikit-learn version that produced this file ( |
|
|
The top-level package the model class belongs to ( |
|
|
Currently always |
|
|
The version of this wire format’s shape, independent of both |
|
|
The openmodels release that wrote this file (from package metadata). Informational only - not checked at deserialize time. Useful for tracing whether a file was written before a particular bug fix landed. |
Example#
A fitted LogisticRegression, serialized to JSON:
{
"estimator_class": "LogisticRegression",
"params": {
"C": 1.0, "class_weight": null, "dual": false, "fit_intercept": true,
"intercept_scaling": 1, "l1_ratio": 0.0, "max_iter": 100, "n_jobs": null,
"penalty": "deprecated", "random_state": null, "solver": "lbfgs",
"tol": 0.0001, "verbose": 0, "warm_start": false
},
"param_types": {
"C": "float", "class_weight": "NoneType", "dual": "bool", "fit_intercept": "bool",
"intercept_scaling": "int", "l1_ratio": "float", "max_iter": "int", "n_jobs": "NoneType",
"penalty": "str", "random_state": "NoneType", "solver": "str", "tol": "float",
"verbose": "int", "warm_start": "bool"
},
"param_dtypes": {},
"producer_version": "1.9.0",
"producer_name": "sklearn",
"domain": "sklearn",
"openmodels_format_version": 1,
"openmodels_version": "0.1.0",
"attributes": {
"classes_": [0, 1],
"coef_": [[1.88878277495458, -0.6412359253840524, 0.2560199894923986, 0.0321823421317183]],
"intercept_": [0.6645191069666503]
},
"attribute_types": {
"classes_": "ndarray", "coef_": "ndarray", "intercept_": "ndarray"
},
"attribute_dtypes": {
"classes_": "int64", "coef_": "float64", "intercept_": "float64"
}
}
Nested and composite estimators#
A meta-estimator that holds other estimators - a Pipeline step, a VotingClassifier’s
estimators, a ColumnTransformer’s transformers - doesn’t get a special graph
representation. Wherever a BaseEstimator value appears (inside params or attributes), it’s
serialized recursively as a nested copy of this exact same dict shape. A serialized Pipeline
is a normal JSON tree, not a separate node/edge graph - openmodels reconstructs models by
calling set_params()/rebuilding fitted attributes on the real scikit-learn class, not by
executing an independent computation graph, so there’s no separate graph representation to keep
in sync with it.
Why not ONNX or PMML?#
Formats like ONNX exist to describe an operator computation graph that a separate, cross-language runtime can execute without the original framework. openmodels never executes a model itself - it always reconstructs the real scikit-learn object and lets scikit-learn run it - so there’s no independent graph to encode, and adopting one would add significant complexity without a corresponding benefit for this library’s actual use case.