9. Сохранение модели

После обучения модели scikit-learn желательно иметь способ сохранить модель для использования в будущем без необходимости повторного обучения. В следующих разделах мы дадим вам несколько советов о том, как сохранить модель scikit-learn.

9.1. Сериализация для Python

Сохранить модель в scikit-learn можно с помощью встроенной в Python модели сохранения, а именно pickle:

>>> from sklearn import svm
>>> from sklearn import datasets
>>> clf = svm.SVC()
>>> X, y= datasets.load_iris(return_X_y=True)
>>> clf.fit(X, y)
SVC()

>>> import pickle
>>> s = pickle.dumps(clf)
>>> clf2 = pickle.loads(s)
>>> clf2.predict(X[0:1])
array([0])
>>> y[0]
0

В конкретном случае scikit-learn, возможно, лучше использовать pickle от joblib (dump и load), которая более эффективна для объектов, несущих внутри себя большие массивы numpy, как это часто бывает для обученых моделей scikit-learn, но может сохранять только на диск, а не в строку:

>>> from joblib import dump, load
>>> dump(clf, 'filename.joblib') 

Позже вы можете загрузить обратно pickle модель (возможно, в другой процесс Python) с помощью:

>>> clf = load('filename.joblib') 

Примечание

Функции dump и load также принимают файлоподобные объекты вместо имен файлов. Больше информации о сохранении данных с помощью Joblib можно найти здесь <https://joblib.readthedocs.io/en/latest/persistence.html>`_.

InconsistentVersionWarning Click for more details

Когда модель распаковывается с версией scikit-learn, которая несовместима с версией, с которой модель был распакован, выдается предупреждение InconsistentVersionWarning. Это предупреждение можно перехватить, чтобы получить исходную версию, с которой была сохранена модель:

from sklearn.exceptions import InconsistentVersionWarning
warnings.simplefilter("error", InconsistentVersionWarning)

try:
    est = pickle.loads("model_from_prevision_version.pickle")
except InconsistentVersionWarning as w:
    print(w.original_sklearn_version)

9.1.1. Ограничения безопасности и удобства сопровождения

У pickle (и joblib в придачу) есть некоторые проблемы, связанные с сопровождаемостью и безопасностью. В связи с этим,

  • Никогда не распаковывайте недоверенные данные, так как это может привести к выполнению вредоносного кода при загрузке.

  • Хотя модели, сохраненные с помощью одной версии scikit-learn, могут загружаться в другие версии, это совершенно не поддерживается и не рекомендуется. Также следует помнить, что операции, выполняемые с такими данными, могут дать разные и неожиданные результаты.

Для того чтобы восстановить аналогичную модель в будущих версиях scikit-learn, необходимо, чтобы дополнительные метаданные были сохранены вместе с моделью:

  • Обучающие данные, например, ссылка на неизменяемый снимок.

  • Исходный код python, использованный для создания модели

  • Версии scikit-learn и его зависимостей

  • Оценка перекрестной валидации, полученная на обучающих данных.

Это должно позволить проверить, что результат кросс-валидации находится в том же диапазоне, что и раньше.

За некоторыми исключениями, сохраненные модели должны быть переносимы между архитектурами при условии, что используются те же версии зависимостей и Python. Если вы столкнулись с моделью, которая не переносится, пожалуйста, откройте проблему на GitHub. Pickled-модели часто разворачиваются в производстве с помощью контейнеров, таких как Docker, чтобы заморозить окружение и зависимости.

Если вы хотите узнать больше об этих проблемах и изучить другие возможные методы сериализации, пожалуйста, обратитесь к этой статье talk by Alex Gaynor.

9.1.2. Более безопасный формат: skops

skops предоставляет более безопасный формат через модуль skops.io. Он позволяет избежать использования pickle и загружает только те файлы, которые имеют типы и ссылки на функции, которым доверяют либо по умолчанию, либо по желанию пользователя.

Использование skops Click for more details

API очень похож на pickle, и вы можете сохранять свои модели, как объясняется в документации, используя skops.io.dump и skops.io.dumps:

import skops.io as sio
obj = sio.dumps(clf)

А загрузить их обратно можно с помощью skops.io.load и skops.io.loads. Однако вам необходимо указать типы, которым вы доверяете. Вы можете получить существующие неизвестные типы в дампе объекта/файла с помощью skops.io.get_untrusted_types, и, проверив его содержимое, передать его функции load:

unknown_types = sio.get_untrusted_types(data=obj)
clf = sio.loads(obj, trusted=unknown_types)

Если вы доверяете источнику файла / объекта, вы можете передать trusted=True:

clf = sio.loads(obj, trusted=True)

Пожалуйста, сообщайте о проблемах и пожеланиях, связанных с этим форматом, на трекере проблем skops.

9.2. Совместимые форматы

Для воспроизводимости и контроля качества, когда необходимо учитывать различные архитектуры и среды, экспорт модели в формат Open Neural Network Exchange или Predictive Model Markup Language (PMML) может быть лучшим подходом, чем использование только pickle. Они полезны, если вы хотите использовать модель для прогнозирования в среде, отличной от той, в которой модель обучалась.

ONNX - это бинарная сериализация модели. Она была разработана для улучшения удобства взаимодействия моделей данных. Она призвана облегчить преобразование моделей данных между различными фреймворками машинного обучения, а также улучшить их переносимость на различные вычислительные архитектуры. Более подробную информацию можно найти в учебнике по ONNX. Для преобразования модели scikit-learn в ONNX был разработан специальный инструмент sklearn-onnx.

PMML - это реализация стандарта документов XML, предназначенного для представления моделей данных вместе с данными, используемыми для их создания. Будучи человеко и машиночитаемым, PMML является хорошим вариантом для проверки моделей на различных платформах и долгосрочного архивирования. С другой стороны, как и XML в целом, его многословность не помогает в производстве, когда производительность критична. Для преобразования модели scikit-learn в PMML можно использовать, например, sklearn2pmml, распространяемый под лицензией Affero GPLv3.