Узнайте, как создать простой API на основе модели машинного обучения на Python с помощью Flask.
Подходы к реализации моделей машинного обучения
Часто истинная ценность вашей модели машинного обучения проявляется в ядре интеллектуального продукта. Будь то жизненно важный компонент системы рекомендаций или интеллект чат-бота, эти моменты могут представлять собой огромные проблемы.
Например, большинство специалистов по машинному обучению используют такие языки, как R или Python, для проведения экспериментов и разработки сложных моделей. Однако когда дело доходит до развертывания этих моделей машинного обучения, аудитория переключается на инженеров-программистов, которые часто работают с совершенно другими стеками технологий. Это представляет собой проблему: как эффективно преодолеть разрыв между этими двумя мирами.
1 — Один из подходов — переписать всю кодовую базу машинного обучения на языке, который подходит команде разработчиков программного обеспечения. Хотя это может показаться логичным решением, оно может занять невероятно много времени и ресурсов, особенно при работе со сложными моделями. Кроме того, в некоторых языках, например в JavaScript, отсутствуют надежные библиотеки машинного обучения, что делает этот вариант менее привлекательным.
2 — Другой, более практичный подход — использовать стратегию «сначала API». Веб-API произвели революцию в способах взаимодействия приложений на разных языках. Предоставляя доступ к своим моделям машинного обучения через веб-API, вы обеспечиваете плавный мост между наукой о данных и разработкой программного обеспечения. Например, разработчики внешнего интерфейса могут получить доступ к вашей модели машинного обучения через простую конечную точку URL-адреса, что позволяет им легко интегрировать возможности машинного обучения в веб-приложения.
Прежде чем углубляться в подход «сначала API», давайте на минутку поймем, что такое API на самом деле и как он может служить мощным связующим звеном между различными стеками технологий.
Что такое API?
«Проще говоря, API — это (гипотетический) контракт между двумя программами, в котором говорится, что если пользовательское программное обеспечение предоставляет входные данные в заранее определенном формате, то последнее расширяет свои функциональные возможности и предоставляет результат пользовательскому программному обеспечению».
По сути, API функционируют так же, как веб-приложения, хотя с особым упором на обмен данными, а не на представление информации в удобном для пользователя формате HTML. Вместо этого они обычно возвращают данные в стандартизированных форматах, таких как JSON или XML. Как только разработчик получает желаемый результат от API, он получает творческую свободу стилизовать и представить его в соответствии со своими конкретными предпочтениями и требованиями. Такая гибкость позволяет разработчикам беспрепятственно интегрировать данные в свои приложения, сохраняя при этом полный контроль над уровнем представления, что обеспечивает широкие возможности настройки и адаптации пользовательского интерфейса.
Теперь, когда вы имеете четкое представление о том, что такое API, давайте посмотрим, как можно объединить модель машинного обучения (разработанную на Python) в API на Python.
Flask — фреймворк веб-сервисов на Python
Flask — это веб-сервис (Веб-API, Веб-сервис — эти термины взаимозаменяемы). Платформа разработки на Python. Он не единственный в Python, есть еще несколько, например Django, Falcon, Hug и т. д. Но для этого урока вы будете использовать Flask.
Если вы загрузили дистрибутив Anaconda, у вас уже установлен Flask. В противном случае вам придется установить его самостоятельно с помощью:
pip install flask
Flask, любимый среди разработчиков Python по нескольким веским причинам, может похвастаться минималистичным дизайном. Среди его привлекательных функций — интегрированный легкий веб-сервер, который требует минимальной настройки и которым можно легко управлять с помощью кода Python. Эта присущая Flask простота является важным фактором, способствующим широкой популярности Flask.
from flask import Flask from flask import Flask app = Flask(__name__) @app.route("'/landing-page', methods=['POST']") def test(): return "Welcome to machine learning model APIs!" if __name__ == '__main__': app.run(debug=True)
После выполнения вы можете перейти по веб-адресу (ввести адрес в веб-браузере), который отображается на терминале, и наблюдать за результатом.
Модели обучения Scikit с Flask
Scikit-learn — это библиотека Python, предоставляющая простые и эффективные инструменты для интеллектуального анализа данных.
- Кластеризация
- Регрессия
- Классификация
- Уменьшение размерности
- Выбор модели
- Предварительная обработка
Scikit-learn упрощает процесс работы с моделями машинного обучения по нескольким причинам. Во-первых, он предлагает поддержку сериализации и десериализации, что позволяет легко сохранять и загружать обученные модели. Это экономит ваше драгоценное время, которое в противном случае было бы потрачено на переобучение моделей. Кроме того, он упрощает создание API-интерфейсов Flask для упрощенного развертывания.
Однако модели scikit-learn требуют числовых данных, а это означает, что вам необходимо обрабатывать категориальные функции, которые не являются числовыми. К счастью, scikit-learn предоставляет полезные утилиты, такие как LabelEncoder и OneHotEncoder в модуле sklearn.preprocessing, которые делают это преобразование безболезненным.
Кроме того, модели scikit-learn не обрабатывают пропущенные значения автоматически. Вам нужно будет устранить недостающие данные в вашем наборе данных, прежде чем передавать их в модель. Scikit-learn предлагает надежный набор инструментов для обработки пропущенных значений, все они доступны в модуле sklearn.предварительная обработка, что гарантирует готовность ваших данных к модели.
В этом уроке вы будете использовать набор данных Титаника. Этот набор данных посвящен задаче классификации, заключающейся в прогнозировании того, выживет пассажир или нет.
Для простоты в нашем анализе мы будем работать всего с четырьмя ключевыми переменными: возраст, пол, начало пути и выживание. Переменная «survived» служит меткой нашего класса.
# Import necessary libraries import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression # Load the dataset from a URL and select only the specified features url = "http://s3.amazonaws.com/assets.datacamp.com/course/Kaggle/train.csv" df = pd.read_csv(url) selected_features = ['Age', 'Sex', 'Embarked', 'Survived'] # We're interested in these four features df = df[selected_features] # Data Preprocessing categorical_columns = [] # To store categorical columns for column, data_type in df.dtypes.iteritems(): if data_type == 'O': # Check if the column has object data type (categorical) categorical_columns.append(column) else: df[column].fillna(0, inplace=True) # Fill missing values in non-categorical columns with 0 # Perform one-hot encoding on categorical columns df_encoded = pd.get_dummies(df, columns=categorical_columns, dummy_na=True) # Define the dependent variable and split data into features (x) and target (y) dependent_variable = 'Survived' x = df_encoded[df_encoded.columns.difference([dependent_variable])] y = df_encoded[dependent_variable] # Create and train a Logistic Regression classifier lr = LogisticRegression() lr.fit(x, y)
Вы создали свою модель машинного обучения. Теперь вы сохраните эту модель. Технически говоря, вы будете сериализовать эту модель. В Python это называется маринование.
from sklearn.externals import joblib joblib.dump(lr, 'rl_model.pkl') ['lr_model.pkl'] lr = joblib.load('r_lmodel.pkl')
Теперь вы хорошо подготовлены к развертыванию сохраняемой модели с помощью Flask. Как вы уже видели, простота Flask делает его отличным выбором для начала вашего пути к веб-сервису.
Для обслуживания вашей модели с помощью Flask вам нужно сделать следующие две вещи:
- Загрузите уже сохраненную модель в память при запуске приложения,
- Создайте конечную точку API, которая принимает входные переменные, преобразует их в соответствующий формат и возвращает прогнозы.
Наши входные данные в модель будут выглядеть следующим образом:
[ {"Age": 80, "Sex": "male", "Embarked": "S"}, {"Age": 24, "Sex": "female", "Embarked": "C"}, {"Age": 5, "Sex": "male", "Embarked": "C"}, {"Age": 21, "Sex": "male", "Embarked": "S"} ]
И вывод нашей модели будет выглядеть так:
{"prediction": [0, 1, 1, 0]}
Давайте создадим удобную функцию predict()
, которая служит двум ключевым целям:
- Загрузка модели. Сохраненная модель машинного обучения будет загружена в память сразу после запуска приложения.
- Создание конечной точки API. Эта функция также позволяет настроить конечную точку API. Эта конечная точка будет отвечать за прием входных переменных, интеллектуальное преобразование их в необходимый формат для обработки модели, а затем предоставление ценных прогнозов, которые мы ищем.
from flask import Flask, jsonify app = Flask(__name__) @app.route('/predict', methods=['POST']) def predict(): json_ = request.json query_df = pd.DataFrame(json_) query = pd.get_dummies(query_df) prediction = lr.predict(query) return jsonify({'prediction': list(prediction)})
Большой! Однако в текущей реализации есть небольшая проблема. Написанная вами функция предполагает, что входящие запросы содержат все возможные значения категориальных переменных, что может быть не так в сценариях реального времени. Если в запросе отсутствуют некоторые категориальные значения, текущее определение метода predict()
, использующее get_dummies()
, создаст DataFrame с меньшим количеством столбцов, чем ожидает классификатор, что приведет к ошибке времени выполнения.
Чтобы решить эту проблему, рассмотрите возможность сохранения списка столбцов во время обучения модели. Вы можете сериализовать эту информацию в файл .pkl с помощью joblib, как и раньше.
model_columns = list(x.columns) joblib.dump(model_columns, 'lr_model_columns.pkl')
Поскольку вы уже сохранили список столбцов, вы можете просто обработать недостающие значения во время прогнозирования. Вам придется загружать столбцы модели при запуске приложения.
@app.route('/predict', methods=['POST']) # Your API endpoint URL would consist /predict def predict(): if lr: try: json_ = request.json query = pd.get_dummies(pd.DataFrame(json_)) query = query.reindex(columns=model_columns, fill_value=0) prediction = list(lr.predict(query)) return jsonify({'prediction': prediction}) except: return jsonify({'trace': traceback.format_exc()}) else: print ('Train the model first') return ('No model here to use') if __name__ == '__main__': try: port = int(sys.argv[1]) # This is for a command-line argument except: port = 12345 # If you don't provide any port then the port will be set to 12345 lr = joblib.load(model_file_name) # Load "lr_model.pkl" print ('Model loaded') model_columns = joblib.load(model_columns_file_name) # Load "r_lmodel_columns.pkl" print ('Model columns loaded') app.run(port=port, debug=True)
Теперь ваш API готов к размещению. Но прежде чем идти дальше, давайте подведем итоги всего, что вы сделали до этого момента:
Собираем все вместе:
- Вы загрузили набор данных Титаника и выбрали четыре объекта.
- Вы выполнили необходимую предварительную обработку данных.
- Вы создали классификатор логистической регрессии и сериализовали его.
- Вы также сериализовали все столбцы из обучения, поскольку решение проблемы меньшего, чем ожидалось, количества столбцов — сохранить список столбцов из обучения.
- Затем вы написали простой API с использованием Flask, который мог бы предсказать, выжил ли человек после кораблекрушения, учитывая его возраст, пол и информацию о том, как он отправился на борт.