Перейти к содержимому

Как сохранить модель машинного обучения python

  • автор:

Как сохранить модель машинного обучения в файл?

Возможно ли сохранить обученную модель машинного обучения в файл и открыть этот файл в другом .py файле? Пробовал joblib и pickle. Эти способы сработали только в рамках одного файла (обучаю модель, сохраняю в файл, загружаю в нем же). Но при обучении и сохранении в одном .py файле и загрузке модели для предсказания в другом .py файле возникает ошибка. в первом файле:

clf = LogisticRegression(max_iter=1000) clf.fit(df_train,df_train_target) joblib.dump(clf, "model.pkl") 
clf2 = joblib.load("model.pkl") y_pred = clf2.predict(df_val) 

введите сюда описание изображения

ошибка:

Отслеживать

51.6k 201 201 золотой знак 65 65 серебряных знаков 247 247 бронзовых знаков

Способы сохранения и загрузки моделей в Keras

Часто спроектированную и обученную модель требуется сохранять для последующего ее использования в прикладных задачах. Либо, еще в процессе обучения создавать контрольные точки на случай возникновения какого-либо сбоя. Могут быть и другие причины, требующие запись данных на носитель и последующего восстановления модели. На этом занятии мы с вами рассмотрим такой базовый функционал пакета Keras.

Для простоты положим, что у нас простая задача классификации изображений цифр последовательной полносвязной сетью:

import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.datasets import mnist tf.random.set_seed(1) (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.reshape(-1, 784) / 255.0 x_test = x_test.reshape(-1, 784) / 255.0 y_train = keras.utils.to_categorical(y_train, 10) y_test = keras.utils.to_categorical(y_test, 10) model = keras.Sequential([ layers.Dense(128, activation='relu'), layers.Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc']) model.fit(x_train, y_train, epochs=5)
  • model.save() или tf.keras.models.save_model() – для записи модели на носитель;
  • keras.models.load_model() – для загрузки модели по указанному пути.
model.save('16_model') model_loaded = keras.models.load_model('16_model')

И, затем, прогнать тестовую выборку через загруженную модель:

model_loaded.evaluate(x_test, y_test)
  • архитектура модели;
  • значения весовых коэффициентов модели;
  • информация о начальной настройки метода compile() (вид оптимизатора, функции потерь и метрик);
  • состояние оптимизатора в момент сохранения модели (для возможности продолжения обучения из текущего состояния).
model.save('16_model_2.h5') model.save('16_model_3', save_format='h5') model_loaded = keras.models.load_model('16_model_2.h5')

Разумеется, рекомендуется использовать новый формат данных при сохранении моделей.

Методы get_config() и from_config()

Остается вопрос, как более детально происходит сохранение и загрузка архитектуры модели? Что конкретно хранится на диске? Согласно документации: https://www.tensorflow.org/guide/keras/save_and_serialize формат SavedModel хранит имя класса, реализацию функцииcall(), потери, веса и значение конфигурации (если в модели реализован метод get_config). Так вот, при отсутствии явного описания конфигурации, реализация функции call() используется для воссоздания работы модели или слоя (если реконструируется отдельный слой). Чтобы все это было понятнее, давайте рассмотрим пример сохранения и загрузки пользовательского класса модели с полносвязными слоями:

class NeuralNetwork(tf.keras.Model): def __init__(self, units): super().__init__() self.units = units self.model_layers = [layers.Dense(n, activation='relu') for n in self.units] def call(self, inputs): x = inputs for layer in self.model_layers: x = layer(x) return x

Мы здесь в конструкторе формируем список полносвязных слоев с функцией активации ReLU, а затем, в методе call() пропускаем входной сигнал последовательно через эти слои. Далее, мы должны воспользоваться этой моделью, чтобы сформировались весовые коэффициенты:

model = NeuralNetwork([128, 10]) y = model.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

И, если теперь выполнить сохранение этой модели:

model.save('16_model')

то в файле saved_model.pb будет храниться реализация метода call(), которая и будет определять структуру модели. Тоесть, послееезагрузки:

model_loaded = keras.models.load_model('16_model')

будет воссоздан класс NeuralNetwork вместе с конкретной реализацией метода call() и теми же самыми весовыми коэффициентами. Именно поэтому, при пропускании того же самого входного сигнала, мы получим абсолютно такие же результаты:

y = model_loaded.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

На первый взгляд эта информация может показаться избыточной. Какая нам разница, как все это в деталях работает, главное, что мы можем сохранять и загружать модели?Однако, существуют ситуации, когда это имеет важное значение. И одну из них я сейчас продемонстрирую. Предположим, что мы бы хотели загрузить модель, но с некоторыми изменениями. Например, вместо функции активации ReLU использовать другую – linear. По идее, для этого можно описать еще один похожий класс модели NeuralNetworkLinear с измененной активационной функцией:

class NeuralNetworkLinear(tf.keras.Model): def __init__(self, units): super().__init__() self.units = units self.model_layers = [layers.Dense(n, activation='linear') for n in self.units] def call(self, inputs): x = inputs for layer in self.model_layers: x = layer(x) return x

А при загрузке указать, чтобы вместо прежнего класса NeuralNetwork был подставлен новый:

model_loaded = keras.models.load_model('16_model', custom_objects={"NeuralNetwork": NeuralNetworkLinear})

Однако, при запуске программы, мы увидим прежний результат, так как через метод call() будут восстановлены исходные полносвязные слоии конструктор класса вызван не будет. Чтобы полноценно использовать новую модель класса NeuralNetworkLinear при загрузке данных, в файл необходимо сохранять конфигурацию модели, а затем, реконструировать ее по этой конфигурации. Для этого в оба класса добавим два специальных метода:

def get_config(self): return {'units': self.units} @classmethod def from_config(cls, config): return cls(**config)
  • Sequential.from_config(config);
  • Model.from_config(config).
config = model.get_config()
  • json_config = model.to_json() – конфигурация архитектуры в формате JSON;
  • new_model = keras.models.model_from_json(json_config) – загрузкаархитектуры модели из JSON-формата.

Методы get_weights(), set_weights() и save_weights(), load_weights()

  • get_weights() – получение коэффициентов модели / слоя;
  • set_weights() – установка коэффициентов модели / слоя;
  • save_weights() – запись коэффициентов модели / слоя на носитель;
  • set_weights() – загрузка коэффициентов модели / слоя с носителя.
model = NeuralNetwork([128, 10]) model2 = NeuralNetwork([128, 10])

Затем, пропустить через них входной сигнал (для формирования весовых коэффициентов в слоях):

y = model.predict(tf.expand_dims(x_test[0], axis=0)) print(y) y = model2.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

А потом скопировать веса, допустим, из первой модели во вторую:

# считываем и записываем веса только после пропускания через модели входного сигнала # иначе возникнет ошибка из-за отсутствия начальной инициализации весов weights = model.get_weights() model2.set_weights(weights) y = model2.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

Как видим, последний вывод для y совпадает по значениям с первой моделью. Это показывает корректность копирования данных. Похожие действия можно выполнять и на уровне отдельных слоев, так как они поддерживают те же самые методы get_weights() и set_weights(). Вторая пара методов save_weights() и load_weights() позволяет сохранять веса на диск, а затем, считывать их обратно в модель. Делается это очень простопутем вызова этих методов для модели или слоя:

model.save_weights('model_weights') model2.load_weights('model_weights')
  • model_weights.data-00000-of-00001 – значения весовых коэффициентов;
  • model_weights.index – индексный вспомогательный файл.
model.save_weights('model_weights.h5') model2.load_weights('model_weights.h5')

Rukovodstvo

статьи и идеи для разработчиков программного обеспечения и веб-разработчиков.

scikit-learn: Сохранение и восстановление моделей

Во многих случаях при работе с библиотекой scikit-learn [http://scikit-learn.org/stable/] вам необходимо сохранить свои модели прогнозов в файл, а затем восстановить их, чтобы повторно использовать вашу предыдущую работу. чтобы: протестировать вашу модель на новых данных, сравнить несколько моделей или что-то еще. Эта процедура сохранения также известна как сериализация объекта — представляет объект с потоком байтов, чтобы сохранить его на диске, отправить по сети или сохранить в базе данных, в то время как процедура восстановления

Время чтения: 7 мин.

Во многих случаях при работе с библиотекой scikit-learn вам необходимо сохранить свои модели прогнозов в файл, а затем восстановить их, чтобы повторно использовать вашу предыдущую работу для: тестирования вашей модели на новых данных, сравнения нескольких моделей или что-нибудь еще. Эта процедура сохранения также известна как сериализация объекта — представляет объект с потоком байтов, чтобы сохранить его на диске, отправить по сети или сохранить в базе данных, в то время как процедура восстановления известна как десериализация. В этой статье мы рассмотрим три возможных способа сделать это в Python и scikit-learn, каждый из которых имеет свои плюсы и минусы.

Инструменты для сохранения и восстановления моделей

Первый инструмент, который мы описываем, — это Pickle , стандартный инструмент Python для (де) сериализации объектов. После этого мы рассмотрим библиотеку Joblib, которая предлагает простую (де) сериализацию объектов, содержащих большие массивы данных, и, наконец, мы представляем ручной подход для сохранения и восстановления объектов в / из JSON (нотация объектов JavaScript). Ни один из этих подходов не представляет собой оптимального решения, но правильный выбор следует выбирать в соответствии с потребностями вашего проекта.

Инициализация модели

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

 from sklearn.linear_model import LogisticRegression from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split # Load and split data data = load_iris() Xtrain, Xtest, Ytrain, Ytest = train_test_split(data.data, data.target, test_size=0.3, random_state=4) 

Теперь давайте создадим модель с некоторыми параметрами, не заданными по умолчанию, и подгоним ее под данные обучения. Мы предполагаем, что вы ранее нашли оптимальные параметры модели, т. Е. Те, которые обеспечивают максимальную расчетную точность.

 # Create a model model = LogisticRegression(C=0.1, max_iter=20, fit_intercept=True, n_jobs=3, solver='liblinear') model.fit(Xtrain, Ytrain) 

И наша получившаяся модель:

 LogisticRegression(C=0.1, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, max_iter=20, multi_class='ovr', n_jobs=3, penalty='l2', random_state=None, solver='liblinear', tol=0.0001, verbose=0, warm_start=False) 

Используя fit метод, модель узнала ее коэффициенты , которые хранятся в model.coef_ . Цель состоит в том, чтобы сохранить параметры и коэффициенты модели в файл, чтобы вам не нужно было снова повторять шаги обучения модели и оптимизации параметров для новых данных.

Модуль рассола

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

 import pickle # # Create your model here (same as above) # # Save to file in the current working directory pkl_filename = "pickle_model.pkl" with open(pkl_filename, 'wb') as file: pickle.dump(model, file) # Load from file with open(pkl_filename, 'rb') as file: pickle_model = pickle.load(file) # Calculate the accuracy score and predict target values score = pickle_model.score(Xtest, Ytest) print("Test score: %".format(100 * score)) Ypredict = pickle_model.predict(Xtest) 

Выполнение этого кода должно дать ваш результат и сохранить модель через Pickle:

 $ python save_model_pickle.py Test score: 91.11 % 

Самое замечательное в использовании Pickle для сохранения и восстановления наших моделей обучения заключается в том, что это быстро

    вы можете сделать это в двух строках кода. Это полезно, если вы оптимизировали параметры модели на обучающих данных, поэтому вам не нужно повторять этот шаг снова. В любом случае, он не сохраняет результаты тестов или какие-либо данные. Тем не менее, вы можете сделать это, сохранив кортеж или список из нескольких объектов (и запомните, какой объект куда идет) следующим образом: tuple_objects = (model, Xtrain, Ytrain, score)

Save tuple

pickle.dump(tuple_objects, open(“tuple_model.pkl”, ‘wb’))

Restore tuple

Модуль Joblib

Библиотека Joblib предназначена для замены Pickle для объектов, содержащих большие данные. Повторим процедуру сохранения и восстановления, как и в случае с Pickle.

 from sklearn.externals import joblib # Save to file in the current working directory joblib_file = "joblib_model.pkl" joblib.dump(model, joblib_file) # Load from file joblib_model = joblib.load(joblib_file) # Calculate the accuracy and predictions score = joblib_model.score(Xtest, Ytest) print("Test score: %".format(100 * score)) Ypredict = pickle_model.predict(Xtest) $ python save_model_joblib.py Test score: 91.11 % 

Как видно из примера, библиотека Joblib предлагает немного более простой рабочий процесс по сравнению с Pickle. В то время как Pickle требует передачи файлового объекта в качестве аргумента, Joblib работает как с файловыми объектами, так и с строковыми именами файлов. Если ваша модель содержит большие массивы данных, каждый массив будет храниться в отдельном файле, но процедура сохранения и восстановления останется прежней. Joblib также поддерживает различные методы сжатия, такие как zlib, gzip, bz2, а также различные уровни сжатия.

Ручное сохранение и восстановление в JSON

В зависимости от вашего проекта, Pickle и Joblib часто оказываются неподходящими решениями. Некоторые из этих причин обсуждаются позже в разделе « Проблемы совместимости ». В любом случае, когда вы хотите иметь полный контроль над процессом сохранения и восстановления, лучший способ — создать свои собственные функции вручную.

Ниже показан пример сохранения и восстановления объектов вручную с помощью JSON. Этот подход позволяет нам выбрать данные, которые необходимо сохранить, такие как параметры модели, коэффициенты, данные обучения и все, что нам нужно.

Поскольку мы хотим сохранить все эти данные в одном объекте, один из возможных способов сделать это — создать новый класс, наследующий от класса модели, которым в нашем примере является LogisticRegression . Новый класс, названный MyLogReg , затем реализует методы save_json и load_json для сохранения и восстановления в / из файла JSON соответственно.

Для простоты мы сохраним только три параметра модели и данные обучения. Некоторые дополнительные данные, которые мы могли бы сохранить с помощью этого подхода, — это, например, оценка перекрестной проверки обучающего набора, тестовые данные, оценка точности тестовых данных и т. Д.

 import json import numpy as np class MyLogReg(LogisticRegression): # Override the class constructor def __init__(self, C=1.0, solver='liblinear', max_iter=100, X_train=None, Y_train=None): LogisticRegression.__init__(self, C=C, solver=solver, max_iter=max_iter) self.X_train = X_train self.Y_train = Y_train # A method for saving object data to JSON file def save_json(self, filepath): dict_ = <> dict_['C'] = self.C dict_['max_iter'] = self.max_iter dict_['solver'] = self.solver dict_['X_train'] = self.X_train.tolist() if self.X_train is not None else 'None' dict_['Y_train'] = self.Y_train.tolist() if self.Y_train is not None else 'None' # Creat json and save to file json_txt = json.dumps(dict_, indent=4) with open(filepath, 'w') as file: file.write(json_txt) # A method for loading data from JSON file def load_json(self, filepath): with open(filepath, 'r') as file: dict_ = json.load(file) self.C = dict_['C'] self.max_iter = dict_['max_iter'] self.solver = dict_['solver'] self.X_train = np.asarray(dict_['X_train']) if dict_['X_train'] != 'None' else None self.Y_train = np.asarray(dict_['Y_train']) if dict_['Y_train'] != 'None' else None 

Теперь попробуем класс MyLogReg Сначала мы создаем объект mylogreg , передаем ему обучающие данные и сохраняем в файл. Затем мы создаем новый объект json_mylogreg и вызываем load_json для загрузки данных из файла.

 filepath = "mylogreg.json" # Create a model and train it mylogreg = MyLogReg(X_train=Xtrain, Y_train=Ytrain) mylogreg.save_json(filepath) # Create a new object and load its data from JSON file json_mylogreg = MyLogReg() json_mylogreg.load_json(filepath) json_mylogreg 

Распечатав новый объект, мы сможем увидеть наши параметры и данные обучения по мере необходимости.

 MyLogReg(C=1.0, X_train=array([[ 4.3, 3. , 1.1, 0.1], [ 5.7, 4.4, 1.5, 0.4], . [ 7.2, 3. , 5.8, 1.6], [ 7.7, 2.8, 6.7, 2. ]]), Y_train=array([0, 0, . 2, 2]), class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1, penalty='l2', random_state=None, solver='liblinear', tol=0.0001, verbose=0, warm_start=False) 

Поскольку сериализация данных с использованием JSON фактически сохраняет объект в строковом формате, а не в потоке байтов, файл mylogreg.json можно открывать и изменять с помощью текстового редактора. Хотя этот подход был бы удобен для разработчика, он менее безопасен, поскольку злоумышленник может просматривать и изменять содержимое файла JSON. Более того, этот подход больше подходит для объектов с небольшим количеством переменных экземпляра, таких как модели scikit-learn, потому что любое добавление новых переменных требует изменений в методах сохранения и восстановления.

Проблемы совместимости

Хотя некоторые из плюсов и минусов каждого инструмента до сих пор были рассмотрены в тексте, вероятно, самым большим недостатком инструментов Pickle и Joblib является их совместимость с различными моделями и версиями Python.

Совместимость версий Python. В документации к обоим инструментам указано, что не рекомендуется (де) сериализовать объекты в разных версиях Python, хотя это может работать при изменении второстепенных версий.

Совместимость модели. Одна из наиболее частых ошибок — сохранение модели с помощью Pickle или Joblib, а затем изменение модели перед попыткой восстановления из файла. Внутренняя структура модели должна оставаться неизменной между сохранением и перезагрузкой.

Последняя проблема с Pickle и Joblib связана с безопасностью. Оба инструмента могут содержать вредоносный код, поэтому не рекомендуется восстанавливать данные из ненадежных или непроверенных источников.

Выводы

В этом посте мы описали три инструмента для сохранения и восстановления моделей scikit-learn. Библиотеки Pickle и Joblib быстры и просты в использовании, но имеют проблемы совместимости с разными версиями Python и изменениями в модели обучения. С другой стороны, ручной подход сложнее реализовать, и его необходимо модифицировать при любых изменениях в структуре модели, но с другой стороны, он может быть легко адаптирован к различным потребностям и не имеет проблем с совместимостью.

Licensed under CC BY-NC-SA 4.0

Учебник по Python. Обучение модели линейной регрессии с помощью машинного обучения SQL

В третьей части серии руководств из четырех частей вы проведете обучение модели линейной регрессии в Python. В следующей части данного цикла вы развернете эту модель в базе данных SQL Server с использованием Служб машинного обучения или в Кластерах больших данных SQL Server 2019.

В третьей части серии руководств из четырех частей вы проведете обучение модели линейной регрессии в Python. В следующей части этого учебника вы развернете эту модель в базе данных SQL Server с использованием служб машинного обучения.

В третьей части серии руководств из четырех частей вы проведете обучение модели линейной регрессии в Python. В следующей части этого учебника вы развернете эту модель в базе данных управляемого экземпляра SQL Azure с использованием служб машинного обучения.

В этой статье вы узнаете, как выполнять следующие задачи.

  • Обучение модели линейной регрессии
  • Прогнозирование по модели линейной регрессии

В первой части вы узнали, как восстановить учебную базу данных.

Во второй части вы узнали, как загрузить данные из базы данных в кадр данных Python, а также подготовить данные в Python.

В четвертой части вы узнаете, как сохранить модель в базе данных, а затем создать хранимые процедуры на основе сценариев Python, разработанных во второй и третьей частях. Хранимые процедуры будут запускаться на сервере, чтобы формировать прогнозы на основе новых данных.

Предварительные требования

  • В третьей части этого учебника предполагается, что вы уже выполнили первую часть и описанные в ней предварительные требования.

Обучение модели

Для прогнозирования необходимо найти функцию (модель), которая лучше всего описывает зависимость между переменными в нашем наборе данных. Это называется обучением модели. Набор данных для обучения будет подмножеством всего набора данных из кадра данных Pandas df , созданного в второй части этой серии.

Вы обучите модель lin_model с использованием алгоритма линейной регрессии.

# Store the variable we'll be predicting on. target = "Rentalcount" # Generate the training set. Set random_state to be able to replicate results. train = df.sample(frac=0.8, random_state=1) # Select anything not in the training set and put it in the testing set. test = df.loc[~df.index.isin(train.index)] # Print the shapes of both sets. print("Training set shape:", train.shape) print("Testing set shape:", test.shape) # Initialize the model class. lin_model = LinearRegression() # Fit the model to the training data. lin_model.fit(train[columns], train[target]) 

Результат должен иметь следующий вид.

Training set shape: (362, 7) Testing set shape: (91, 7) 

Составление прогнозов

Используйте функцию прогнозирования для предсказания количества аренд с помощью модели lin_model .

# Generate our predictions for the test set. lin_predictions = lin_model.predict(test[columns]) print("Predictions:", lin_predictions) # Compute error between our test predictions and the actual values. lin_mse = mean_squared_error(lin_predictions, test[target]) print("Computed error:", lin_mse) 

Результат должен иметь следующий вид.

Predictions: [124.41293228 123.8095075 117.67253182 209.39332151 135.46159387 199.50603805 472.14918499 90.15781602 216.61319499 120.30710327 89.47591091 127.71290441 207.44065517 125.68466139 201.38119194 204.29377218 127.4494643 113.42721447 127.37388762 94.66754136 90.21979191 173.86647615 130.34747586 111.81550069 118.88131715 124.74028405 211.95038051 202.06309706 123.53053083 167.06313191 206.24643852 122.64812937 179.98791527 125.1558454 168.00847713 120.2305587 196.60802649 117.00616326 173.20010759 89.9563518 92.11048236 120.91052805 175.47818992 129.65196995 120.97443971 175.95863082 127.24800008 135.05866542 206.49627783 91.63004147 115.78280925 208.92841718 213.5137192 212.83278197 96.74415948 95.1324457 199.9089665 206.10791806 126.16510228 120.0281266 209.08150631 132.88996619 178.84110582 128.85971386 124.67637239 115.58134503 96.82167192 514.61789505 125.48319717 207.50359894 121.64080826 201.9381774 113.22575025 202.46505762 90.7002328 92.31194658 201.25627228 516.97252195 91.36660136 599.27093251 199.6445585 123.66905128 117.4710676 173.12259514 129.60359486 209.59478573 206.29481361 210.69322009 205.50255751 210.88011563 207.65572019] Computed error: 35003.54030828391 

Дальнейшие действия

В третьей части этого учебника вы выполнили следующие действия:

  • Обучение модели линейной регрессии
  • Прогнозирование по модели линейной регрессии

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *