Разверните свою модель машинного обучения в REST API с помощью FastAPI.

Большинство людей, которые хотят начать изучать науку о данных или машинное обучение, обычно ищут данные на Kaggle и проводят некоторые эксперименты внутри блокнота Kaggle. Но иногда после того, как они закончили эксперимент и создали отличную модель, они не знают, что с ней делать. Есть куча причин, по которым люди занимаются машинным обучением, это может быть просто для получения информации, поэтому им не нужно развертывать модель, но, скорее всего, модель можно развернуть в рабочей среде, чтобы она могла быть полезной. Существует несколько подходов к развертыванию моделей машинного обучения. Вот некоторые из них:

  1. ОТДЫХА API
  2. Общая БД
  3. Потоковое

Эти подходы сравниваются в сообщении в блоге о том, как развернуть модель машинного обучения от ChristoperGS. Но я здесь, чтобы рассказать больше о практическом подходе первого подхода (REST API). Ограничение этого развертывания машинного обучения REST API заключается в том, что модель нельзя обучить с помощью REST API, но тем временем мне удастся это сделать, потому что это действительно возможно в качестве доказательства концепции.

Сначала получите модель

Я не буду здесь фокусироваться на создании модели, поэтому давайте выберем существующую модель на Kaggle. Вы можете выбрать любое ядро ​​на Kaggle, если оно создает модель машинного обучения, но я выберу это ядро, потому что оно хорошо работает. Даже если мы просто хотим развернуть модель, нам все равно нужно разобраться в темах, поэтому я немного объясню модель.

Идея этой модели состоит в том, чтобы определить, являются ли новости фальшивыми или реальными, используя контролируемую классификацию машинного обучения. Это ядро ​​​​использует LSTM на библиотеке Keras в качестве модели, другие ядра могут использовать другие библиотеки для модели, которые могут иметь другой синтаксис или методы для выполнения процесса.

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

  1. Скопируйте и отредактируйте блокнот
  2. Запустите все ячейки и дождитесь завершения процесса
  3. Добавьте ячейку кода и экспортируйте модель в каталог «/kaggle/working/». Ниже приведен пример экспорта модели Keras.
model.save('/kaggle/working/model.keras')

Kaggle позволяет вам получить доступ только к вашему временному выходному файлу внутри каталога «/kaggle/working/», поэтому у вас не так много вариантов. Вы можете просто поискать в Google информацию о том, как экспортировать модель машинного обучения, каждая библиотека имеет свой собственный подход, убедитесь, что вы также знаете, как импортировать/загружать модель, потому что вам придется делать это при развертывании.

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

import pickle
with open('/kaggle/working/tokenizer.pkl', 'wb') as f:
    pickle.dump(tokenizer, f, pickle.HIGHEST_PROTOCOL)

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

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

FastAPI

FastAPI — веб-фреймворк для создания API. Он называется Быстрый, потому что он быстро кодируется, быстро развертывается, его можно быстро изучить, а также он высокопроизводителен. Если у вас уже есть python и pip, вы можете легко их установить. Также вам понадобится сервер ASGI для производства, я рекомендую использовать uvicorn.

pip install fastapi
pip install uvicorn

Но если вы предпочитаете хорошо управляемую среду, я предпочитаю использовать Conda. О том, как установить conda, а также о конфигурации jupyter lab, вы узнаете из моего предыдущего рассказа. Чтобы установка FastAPI и Uvicorn была одинаковой, просто измените имя пакета.

conda install fastapi uvicorn -y

Вы можете проверить Документацию FastAPI, чтобы узнать больше об этом. Но для этого руководства вам просто нужно изучить некоторые основы REST API, включая запросы и ответы. Типичной характеристикой REST API является то, что клиент отправляет запросы на сервер, затем сервер обрабатывает эти запросы и отправляет ответы в соответствии с запросами. Затем клиент извлекает эти ответы. Запросы отправляются с использованием HTTP-методов, есть несколько HTTP-методов, но наиболее распространенными являются следующие:

  1. GET, чтобы прочитать данные с сервера
  2. POST, чтобы добавить новые данные на сервер
  3. PUT, чтобы изменить данные на сервере
  4. УДАЛИТЬ, чтобы удалить данные на сервере

Подробное, но простое объяснение этих методов можно увидеть на странице Википедии о HTTP. На самом деле вы можете создать API, который получает запрос POST, но вообще не добавляет новые данные на сервер или другие методы для другого использования, но, конечно, это будет плохой практикой, потому что это запутает клиентов.

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

from fastapi import FastAPI
description = """
A REST API to load predict if the news is fake or not using LSTM with GloVe Embeeded Text Data
"""
app_config = {
    'title': 'FakeNewsAPI',
    'description': description,
    'version': '0.0.1'
}
app = FastAPI(**app_config)

Ход процесса

Это не очень хорошо отформатированная диаграмма, но, по крайней мере, она может помочь нам понять, что мы хотим разработать. вот схема, описывающая процесс этого API.

Вот некоторые пояснения к схеме.

  1. Клиент отправляет запрос на сервер
  2. Сервер извлекает запрос как полезную нагрузку
  3. Сервер загружает модель машинного обучения
  4. Сервер предварительно обрабатывает запрос в приемлемый вход для модели.
  5. Сервер прогнозирует ввод, используя модель
  6. Сервер форматирует вывод в JSON как ответ
  7. Сервер отправляет ответ клиенту
  8. Клиент получает ответ от сервера

Это довольно сложный процесс, давайте перейдем к каждому из них.

Клиент отправляет запрос на сервер

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

Сервер получает запрос

Как объяснялось ранее, ожидается, что клиент отправит запрос с помощью метода GET, который включает заголовок и содержание новости. Итак, мы должны получить его должным образом.

@app.get('/predict')
async def predict(title: str, content: str):
    pass

как видите, приложение принимает запрос с помощью метода GET в конечной точке прогнозирования, а функция прогнозирования определяется после асинхронного префикса. Я могу объяснить об этом, но я думаю, что вы можете получить лучшее объяснение этого из его официальной документации, а также объяснение в Документации FastAPI. Функция Predict принимает два параметра: заголовок и содержимое. В методе GET параметрами функции будут тело запроса, поэтому оно будет соответствовать телу запроса клиента. Для других методов, таких как POST, тело запроса будет в формате JSON, а ввод должен обрабатываться с использованием pydantic BaseModel, но я не буду его здесь включать. Для проходной части это будет основная программа.

Сервер загружает модель машинного обучения

Модель машинного обучения необходимо загрузить в систему для целей прогнозирования. Поскольку модель написана в Keras, мы можем использовать встроенную функцию Keras для загрузки модели. В других библиотеках может быть свой способ загрузки модели, это может быть pickle, joblib или любой другой подход.

from tensorflow.keras.models import load_model
import pickle
import os
model_path = os.path.abspath('models/model.keras')
model = load_model(model_path)
tokenizer_path = os.path.abspath('models/tokenizer.pkl')
with open(tokenizer_path, 'rb') as f:
    tokenizer = pickle.load(f)

Сервер предварительно обрабатывает запрос в приемлемый вход для модели.

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

from nltk.corpus import stopwords
from bs4 import BeautifulSoup
import string, re
stop = set(stopwords.words('english'))
punctuation = list(string.punctuation)
stop.update(punctuation)
def strip_html(text):
    soup = BeautifulSoup(text, 'html.parser')
    return soup.get_text()
def remove_between_square_brackets(text):
    return re.sub('\[[^]]*\]', '', text)
def remove_url(text):
    return re.sub(r'http\S+', '', text)
def remove_stopwords(text):
    final_text = []
    for i in text.split():
        if i.strip().lower() not in stop:
            final_text.append(i.strip())
    return " ".join(final_text)
def denoise_text(text):
    text = strip_html(text)
    text = remove_between_square_brackets(text)
    text = remove_url(text)
    text = remove_stopwords(text)
    return text
maxlen = 300
def fake_news_preprocess(title, content):
    text = content + ' ' + title
    text = denoise_text(text)
    tokenized_text = tokenizer.texts_to_sequences(np.array([text]))
    vector = sequence.pad_sequences(tokenized_text, maxlen=maxlen)
    return vector
vector = fake_news_preprocess(title, content)

Сервер прогнозирует ввод, используя модель

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

prediction = model.predict(vector)

Сервер форматирует вывод в JSON как ответ

Выходные данные прогноза метода прогнозирования модели Keras представляют собой тип данных вложенного массива numpy. Поскольку метод прогнозирования предназначен для прогнозирования нескольких данных, а в этом REST API нам просто нужно прогнозировать только одни данные. Итак, мы должны взять первый индекс первого индекса прогноза. Чтобы сделать данные JSON читаемыми, мы должны преобразовать данные в тип данных python float. Этот REST API предназначен для проверки того, являются ли новости фальшивыми, и в этом случае прогноз 1 означает 100% настоящие новости, а прогноз 0 означает 100% фальшивку. Итак, мы должны инвертировать прогноз, чтобы получить фальшивую вероятность. После этого мы помещаем поддельную вероятность в словарь Python в качестве ответа.

real_probability = float(prediction[0][0])
fake_probability = 1 - real_probability
response = {
    'fake_probability': fake_probability
}

Сервер отправляет ответ клиенту

Получив ответ, мы должны отправить его клиенту. FastAPI уже обрабатывает этот процесс, возвращая основную функцию в качестве ответа, поэтому я не буду объяснять дальше.

return response

Клиент получает ответ от сервера

Эта часть обрабатывается клиентом, и нам не нужно ничего делать, потому что мы просто фокусируемся на REST API. Если мы хотим создать приложение с полным стеком, нам нужно рассмотреть интерфейсную часть, но это выходит за рамки этой статьи.

Полный сценарий

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