Итак, первое, что я скажу, это то, что нет ничего плохого в травлении ваших моделей. Просто он накладывает несколько ограничений на то, как вы можете загружать модели, о которых вы должны знать. Чтобы проиллюстрировать это, я расскажу о разнице между сохранением вашей модели в виде рассола и ее экспортом во что-то вроде ONNX.

Когда вы выбираете модель, вы сериализуете объект Python, чтобы его можно было сохранить в файле. Когда вы загружаете объект python из файла рассола, он предполагает, что все пакеты и функции, которые он вызывает, одинаковы. Это означает, что ваша экспортированная модель сильно связана со средой, в которую она была экспортирована. Если вы попытаетесь загрузить свою модель с чем-то вроде другой версии sklearn, ваш pickle может не загрузиться.

Напротив, когда вы экспортируете модель в ONNX (https://onnx.ai/), вы конвертируете ее в набор операций, которые могут выполняться непосредственно фреймворком. Когда вы загружаете модель, не будет никаких предположений о других функциях или пакетах, она просто выполнит операции и сгенерирует ваши результаты. Это означает, что ваша модель больше не сильно связана с вашей конкретной средой Python. На самом деле он вообще больше не связан с Python, потому что модели ONNX переносимы на множество разных языков (примеры: https://onnxruntime.ai/docs/get-started/).

С учетом сказанного давайте теперь рассмотрим пример того, как вы можете преобразовать свои модели как в pickle, так и в ONNX.

Во-первых, предположим, что у вас есть обученная модель sklearn:

from sklearn.datasets import make_hastie_10_2
from sklearn.ensemble import GradientBoostingClassifier
X, y = make_hastie_10_2(random_state=0)
X_train, X_test = X[:2000], X[2000:]
y_train, y_test = y[:2000], y[2000:]
clf = GradientBoostingClassifier(
    n_estimators=100, learning_rate=1.0,
    max_depth=1, random_state=0
)
clf = clf.fit(X_train, y_train)

Вы можете сохранить и загрузить его с рассолом следующим образом:

import pickle
with open("model.pkl", "wb") as f:
    pickle.dump(clf, f)
with open("model.pkl","rb") as f:
    pkl_clf = pickle.load(f)
preds = pkl_clf.predict(X_train)

Как обсуждалось ранее, это не очень переносимый формат. Чтобы загрузить модель, вам понадобится точно такая же версия sklearn, иначе рассол может не загрузиться.

Кроме того, если все, что вы хотите сделать, это делать прогнозы с помощью модели (например, при создании конечной точки вывода), вам все равно нужно будет загрузить весь пакет sklearn, что является излишним.

Для экспорта модели в ONNX вам понадобятся следующие пакеты:

  • onnx, skl2onnx, onnxmltools

С установленными вы можете преобразовать модель следующим образом:

from skl2onnx import convert_sklearn
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
from skl2onnx import get_latest_tested_opset_version
from onnxmltools.utils import save_model
target_opset = get_latest_tested_opset_version()
n_features = X_train.shape[1]
onnx_clf = convert_sklearn(
    clf,
    "gbdt_model",
    initial_types=[("input", FloatTensorType([None, n_features]))],
    target_opset={"": target_opset, "ai.onnx.ml": 1}
)
save_model(onnx_clf, "model.onnx")

target_opset — это установленная версия оператора ONNX. Я бы рекомендовал использовать последнюю доступную версию, а затем понизить ее, если она не поддерживается для вашей конкретной модели.

После того, как вы экспортировали свою модель в ONNX, вам больше не нужны никакие пакеты, которые вы использовали для обучения или экспорта своей модели. Все, что вам нужно, это пакет onnxruntime:

import onnxruntime as ort
import numpy as np
sess = rt.InferenceSession(model_name)
preds, _ = sess.run(
    None, {"input": X_train.astype(np.float32)}
)

Как я уже сказал, этот код даже не обязательно должен быть на питоне, поскольку у onnxruntime есть API для разных языков. Это значительно упрощает внедрение вашей модели в любую производственную среду, которая нужна вам или вашей команде.

Спасибо, что зашли так далеко. Я надеюсь, что это проливает свет на преимущества экспорта ваших моделей в что-то вроде ONNX.