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

Наука о данных - это слишком круто, чтобы оставлять ее в блокноте. Нам нужен какой-то способ сделать модели полезными, скажем, для веб-приложений, но как мы можем это сделать? Сегодня мы обучим простую модель машинного обучения и развернем ее с помощью Flask, а затем будем делать прогнозы с помощью библиотеки запросов Python.

Если вы больше любите видео или просто хотите подкрепить свои знания, посмотрите наше видео по этой теме. Исходный код включает:

Почему мне нужно заботиться о развертывании? Хороший вопрос. Позвольте мне ответить на него еще одним вопросом: какова цель вашей модели, если вы не собираетесь ее использовать? Или хотя бы заставить его использовать кого-нибудь? Не можете придумать причины? Хорошо, я тоже.

Что такое Flask? Flask - это микрофреймворк для разработки веб-приложений. Мы не будем использовать его для этой цели, но мы воспользуемся Flask-RESTful, чтобы раскрыть определенные функции нашей модели.

Хорошо, но что такое запросы? Это еще одна простая библиотека, которая взаимодействует с REST API.

Ух, а что такое REST API? REST или передача репрезентативного состояния - в зависимости от того, что вам кажется более естественным - это набор стилей и ограничений, используемых для создания веб-сервисов. Как только Restful API будет запущен, мы можем сделать запрос к определенной конечной точке с определенными параметрами - это все, что вам нужно знать на данный момент. При этом выполняется некоторая внутренняя логика - в нашем случае - прогноз.

Вот структура каталогов (не стесняйтесь настраивать):

Корневой каталог называется mldeploy, а внутри у нас есть еще две папки: modeler и models. Первый содержит файл modeler.py (два других создал Python), а второй будет содержать сохраненную модель после того, как мы проведем обучение.

Наконец, app.py свяжет все вместе и будет использовать Flask и Flask-RESTful для раскрытия прогнозирующей части.

А теперь давайте сделаем до глупости простой классификатор.

Делаем классификатор

Мы будем использовать знаменитый набор данных Iris , потому что в этом примере нас не волнует часть задачи, связанная с машинным обучением. Нас интересует только то, как модель может быть развернута, а не построена.

Вот импорт:

import os
import joblib
import pandas as pd
from sklearn.tree import DecisionTreeClassifier

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

Затем мы написали класс для загрузки, обучения, сохранения и прогнозирования моделей. Подготовка данных не требуется, поэтому все сводится к паре строк кода:

class Modeler:
    def __init__(self):
        self.df = pd.read_csv(‘https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv')
        try: self.model = joblib.load(‘models/iris.model’)
        except: self.model = None
    def fit(self):
        X = self.df.drop(‘species’, axis=1)
        y = self.df[‘species’]
        self.model = DecisionTreeClassifier().fit(X, y)
        joblib.dump(self.model, ‘models/iris.model’)
    def predict(self, measurement):
        if not os.path.isfile(‘models/iris.model’):
            raise Exception(‘Model not trained yet. Call .fit() before making predictions.’)
        if len(measurement) != 4:
            raise Exception(f’Expected sepal_length, sepal_width, petal_length, petal_width, got {measurement}’)
        prediction = self.model.predict([measurement])
        return prediction[0]

На этом все для modeler.py. Сам API мы разработаем в следующем разделе.

REST API

Теперь мы можем приступить к развертыванию. Давайте откроем app.py и выполним несколько операций импорта:

import os
import joblib
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
from modeler.modeler import Modeler

Здесь мы также будем использовать Joblib, но на этот раз для загрузки обученной модели. Внизу мы импортируем ранее написанный класс Modeler. А теперь займемся уборкой Flask:

app = Flask(__name__)
api = Api(app)

Flask-RESTful структурирован таким образом, что каждая конечная точка должна находиться внутри своего собственного класса. Внутри мы объявляем функции, соответствующие типу запроса, который делает конечный пользователь, наиболее популярными из которых являются GET и POST.

В этом примере используется POST, и как только запрос будет сделан, мы получим данные, предоставленные пользователем. Ожидаются 4 значения: длина чашелистика, ширина чашелистника, длина лепестка и ширина лепестка, соответствующие характеристикам нашего набора данных.

Затем создается экземпляр класса Modeler и вызывается функция pred () с указанными входными данными. Наконец, возвращается JSON-представление прогноза.

Звучит просто, правда? Потому что это так. Вот код:

class Predict(Resource):
    @staticmethod
    def post():
        data = request.get_json()
        sepal_length = data[‘sepal_length’]
        sepal_width = data[‘sepal_width’]
        petal_length = data[‘petal_length’]
        petal_width = data[‘petal_width’]
        m = Modeler()
        if not os.path.isfile(‘models/iris.model’):
            m.fit()
        prediction = m.predict([sepal_length, sepal_width, petal_length, petal_width])
        return jsonify({
            ‘Input’: {
                ‘SepalLength’: sepal_width,
                ‘SepalWidth’: sepal_width,
                ‘PetalLength’: petal_length,
                ‘PetalWidth’: petal_width
            },
            ‘Class’: prediction
        })

Теперь нам нужно немного больше поработать в Flask, и это фактически связывает класс Predict с конечной точкой - / predict должен это сделать. :

api.add_resource(Predict, ‘/predict’)

Последнее, что нужно сделать с точки зрения кода, - это сделать app.py исполняемым:

if __name__ == ‘__main__’:
    app.run(debug=True)

Затем мы можем проверить, все ли работает так, как рекламируется.

Делать прогнозы

Давайте сначала запустим app.py. Откройте корневую папку в терминале и введите:

python3 app.py

Или без «3», если вы работаете в Windows:

API теперь работает на http://127.0.0.1:5000/. Чтобы проверить, работает ли он правильно, мы будем использовать записные книжки - они немного более интерактивны, чем редактор кода.

Нам понадобится библиотека requests:

import requests

Отсюда мы можем сделать POST-запрос к конечной точке / прогноз со значениями для длины чашелистика, ширины чашелистика, длины лепестка и ширина лепестка. Это довольно просто сделать:

res = requests.post(
    url=’http://localhost:5000/predict',
    json={
        ‘sepal_length’: 5.0,
        ‘sepal_width’: 3.2,
        ‘petal_length’: 1.5,
        ‘petal_width’: 0.3
    }
)

Прохладный. Мы можем проверить, что находится внутри переменной res:

res
>>> <Response [200]>

Код состояния 200 означает, что все прошло хорошо, и мы готовы делать прогнозы. Вызов res.json () делает свое дело:

res.json()
>>> {‘Class’: ‘setosa’,
     ‘Input’: {‘PetalLength’: 1.5,
      ‘PetalWidth’: 0.3,
      ‘SepalLength’: 3.2,
      ‘SepalWidth’: 3.2}}

Вот и все! Согласитесь - все оказалось проще, чем вы ожидали.

Последние слова

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

Таким образом, это будет не http://127.0.0.1:5000/predict, а что-то вроде http: // your_url: port / predict.

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

Спасибо за прочтение.