СТАТЬЯ
Развертывание моделей машинного обучения, часть 1: сохранение моделей
Из Книжного лагеря по машинному обучению Алексея Григорьева
В этой серии статей мы рассмотрим развертывание моделей: процесс использования моделей. В частности, мы увидим, как упаковать модель в веб-службу, чтобы другие службы могли ее использовать. Мы также покажем, как развернуть веб-службу в среде, готовой к работе.
Получите скидку 40% на Книжный лагерь по машинному обучению, введя fccgrigorev в поле кода скидки при оформлении заказа на manning.com.
Модель прогнозирования оттока
Чтобы начать развертывание, мы будем использовать модель, которая используется в книге. Вы можете загрузить исходный код здесь (модель и данные находятся в папке CH 03, а другой соответствующий код находится в папке Ch05). Сначала в этой статье мы рассмотрим, как можно использовать модель для прогнозирования, а затем посмотрим, как сохранить ее с помощью Pickle.
Использование модели
Давайте воспользуемся этой моделью, чтобы рассчитать вероятность ухода следующего клиента:
customer = { 'customerid': '8879-zkjof', 'gender': 'female', 'seniorcitizen': 0, 'partner': 'no', 'dependents': 'no', 'tenure': 41, 'phoneservice': 'yes', 'multiplelines': 'no', 'internetservice': 'dsl', 'onlinesecurity': 'yes', 'onlinebackup': 'no', 'deviceprotection': 'yes', 'techsupport': 'yes', 'streamingtv': 'yes', 'streamingmovies': 'yes', 'contract': 'one_year', 'paperlessbilling': 'yes', 'paymentmethod': 'bank_transfer_(automatic)', 'monthlycharges': 79.85, 'totalcharges': 3320.75, }
Чтобы предсказать, собирается ли этот клиент уйти, мы можем использовать функцию predict
:
df = pd.DataFrame([customer]) y_pred = predict(df, dv, model) y_pred[0]
Этой функции нужен фрейм данных, а это значит, что мы должны сначала создать фрейм данных с одной строкой - нашего клиента. Затем мы помещаем его в функцию predict
. Результатом является массив NumPy с единственным элементом: прогнозируемая вероятность оттока для этого клиента:
0.061875
Это означает, что вероятность ухода этого клиента составляет шесть процентов.
Теперь давайте посмотрим на функцию predict
. Мы написали его ранее для применения модели к клиентам в наборе для проверки. Вот как это выглядит:
def predict(df, dv, model): cat = df[categorical + numerical].to_dict(orient='rows') X = dv.transform(cat) y_pred = model.predict_proba(X)[:, 1] return y_pred
Использование его для одного клиента кажется неэффективным и ненужным: мы создаем фрейм данных из одного клиента только для того, чтобы преобразовать этот фрейм данных обратно в словарь позже внутри predict
.
Чтобы избежать этого ненужного преобразования, мы можем создать отдельную функцию для прогнозирования вероятности оттока только для одного клиента. Назовем эту функцию predict_single
:
def predict_single(customer, dv, model): #A X = dv.transform([customer]) #B y_pred = model.predict_proba(X)[:, 1] #C return y_pred[0] #D
#A Вместо передачи фрейма данных передайте одного клиента
#B Векторизовать клиента: создать матрицу X
#C Применить модель к этой матрице
#D Поскольку у нас только один клиент, нам нужен только первый элемент результата
Его использование становится проще: мы вызываем его у нашего покупателя (словаря):
predict_single(customer, dv, model)
Результат тот же: вероятность того, что у этого покупателя изменится, составляет шесть процентов.
Эта модель живет в записной книжке Jupyter, и как только мы ее останавливаем, обученная модель исчезает. Это означает, что теперь мы можем использовать его только внутри ноутбука и больше нигде. Далее мы посмотрим, как с этим справиться.
Использование Pickle для сохранения и загрузки модели
Чтобы иметь возможность использовать его вне нашей записной книжки, нам нужно сохранить его, а позже другой процесс сможет загрузить его и использовать (рисунок 1).
Pickle - это модуль сериализации / десериализации, который уже встроен в Python: с его помощью мы можем сохранить произвольный объект Python (за некоторыми исключениями) в файл. Когда у нас есть файл, мы можем загрузить модель оттуда в другом процессе.
ПРИМЕЧАНИЕ. «Pickle» также может использоваться как глагол: травление объекта в Python означает его сохранение с помощью модуля Pickle.
Сохранение модели
Чтобы сохранить модель, мы сначала импортируем модуль pickle
, а затем используем функцию dump
:
import pickle with open('churn-model.bin', 'wb') as f_out: #A pickle.dump(model, f_out) #B
#A Укажите файл, в котором мы хотим сохранить
#B Сохраните модель в файл с помощью pickle
Для сохранения модели используем функцию open
. Требуется два аргумента:
- Имя файла, который мы хотим открыть. Для нас это
churn-model.bin
. - Режим, в котором мы открываем файл. Для нас это
wb
, что означает, что мы хотим писать в файл (w
), и файл должен быть двоичным (b
).
Функция open
возвращает f_out
- дескриптор файла, который мы можем использовать для записи в файл.
Далее мы используем функцию дампа из Pickle. Также требуется два аргумента:
- Объект, который мы хотим сохранить. Для нас это
model
- Дескриптор файла, указывающий на выходной файл, который для нас
f_out
Наконец, мы используем конструкцию with
в этом коде. Когда мы открываем файл с открытым, нам нужно закрыть его после того, как мы закончим писать. С with
это происходит автоматически. Без with
наш код выглядит так:
f_out = open('churn-model.bin', 'wb') pickle.dump(model, f_out) f_out.close()
В нашем случае сохранения модели недостаточно: у нас также есть DictVectorizer
, который мы также «обучили» вместе с моделью. Нам нужно спасти обоих.
Самый простой способ сделать это - поместить их обоих в кортеж при мариновании:
with open('churn-model.bin', 'wb') as f_out: pickle.dump((dv, model), f_out) #A
# Сохраняемый нами объект представляет собой кортеж с двумя элементами
Загрузка модели
Чтобы загрузить его, мы используем функцию load
из Pickle. Мы можем протестировать это в том же блокноте Jupyter:
with open('churn-model.bin', 'rb') as f_in: #A dv, model = pickle.load(f_in) #B
#A Откройте файл в режиме чтения
#B Загрузить кортеж и распаковать его
Мы снова используем функцию open
, но на этот раз в другом режиме: rb
, что означает, что мы открываем его для чтения (r
), а файл является двоичным (b
).
ВНИМАНИЕ: будьте осторожны при указании режима. Случайное указание неправильного режима может привести к потере данных: если вы откроете существующий файл в режиме w
вместо r
, содержимое будет перезаписано.
Поскольку мы сохранили кортеж, мы распаковываем его при загрузке и получаем одновременно векторизатор и модель.
ВНИМАНИЕ! Распаковка объектов, найденных в Интернете, небезопасна: при этом может выполняться произвольный код на вашем компьютере. Используйте его только для того, чему доверяете, и для того, что спасли сами.
Давайте создадим простой скрипт Python, который загружает модель и применяет ее к клиенту.
Мы называем этот файл churn_serving.py
. Это содержит:
predict_single
функции, которые мы написали ранее- Код для загрузки модели
- Код для применения модели заказчику
Во-первых, начнем с импорта. Для этого скрипта нам нужно импортировать Pickle и NumPy:
import pickle import numpy as np
Теперь давайте поместим туда функцию predict_single
:
def predict_single(customer, dv, model): X = dv.transform([customer]) y_pred = model.predict_proba(X)[:, 1] return y_pred[0]
Теперь мы можем загрузить нашу модель:
with open('churn-model.bin', 'rb') as f_in: dv, model = pickle.load(f_in)
И примените это:
customer = { 'customerid': '8879-zkjof', 'gender': 'female', 'seniorcitizen': 0, 'partner': 'no', 'dependents': 'no', 'tenure': 41, 'phoneservice': 'yes', 'multiplelines': 'no', 'internetservice': 'dsl', 'onlinesecurity': 'yes', 'onlinebackup': 'no', 'deviceprotection': 'yes', 'techsupport': 'yes', 'streamingtv': 'yes', 'streamingmovies': 'yes', 'contract': 'one_year', 'paperlessbilling': 'yes', 'paymentmethod': 'bank_transfer_(automatic)', 'monthlycharges': 79.85, 'totalcharges': 3320.75, } prediction = predict_single(customer, dv, model)
Наконец, давайте покажем результаты:
print('prediction: %.3f' % prediction) if prediction >= 0.5: print('verdict: Churn') else: print('verdict: Not churn')
После сохранения файла мы можем запустить этот скрипт с Python:
python churn_serving.py
Мы должны сразу увидеть результаты:
prediction: 0.062 verdict: Not churn
Таким образом, мы можем загрузить модель и применить ее к клиенту, указанному в скрипте.
Мы не собираемся вручную помещать информацию о клиентах в скрипт. Во части 2 мы рассмотрим более практичный подход: размещение модели в веб-сервисе.
Это все для этой статьи.
Если вы хотите узнать больше о книге, посмотрите ее на нашей браузерной платформе liveBook здесь.