Разработка, документирование, развертывание и типизация

Многие из вас, возможно, слышали о FastAPI или даже читали мою статью о нем. FastAPI, как следует из названия, представляет собой платформу ASGI на основе Python, которая намного быстрее, чем Django и Flask. Он поставляется с Pydantic и Starlette и доказывает, что является лучшим py-кандидатом.



Приступая к делу, в этой статье предполагается, что у вас уже настроен FastAPI с uvicorn для сервера. Мы собираемся использовать замороженную модель, обученную на наборе данных MNIST, который можно найти здесь — Github. Загрузите это и поместите в свою основную папку.

Теперь напишем файл нашего сервера — main.py. Давайте сначала напишем статический код, в котором мы создаем экземпляр сервера, и загружаем модель.

Чтобы загрузить модель, мы пишем следующее: —

import tensorflow.compat.v1 as tf
frozen_file_path = 'mnist.model.best.hdf5'
print("Loading Model")
model_graph = tf.Graph()

new_model = tf.keras.models.load_model(frozen_file_path)

Чтобы создать экземпляр сервера, мы импортируем и вызываем следующее

from fastapi import FastAPI
app = FastAPI()

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

@app.get("/random_prediction")
async def predict_random():
    rand_int =  random.randint(0,len(X_test))
    print(rand_int)
    random_image_data = X_test[rand_int]
    rand_image = Image.fromarray(random_image_data,'L')
    y_out = await new_model.predict(numpy.expand_dims(random_image_data,axis=0))
    predicted_value = numpy.where(y_out[0]==1)[0][0]

    return {"prediction": predicted_value}

Убедитесь, что вы импортируете данные для MNIST из keras, используя

from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()

Давайте рассмотрим другой пример, когда входные данные являются числовыми или категориальными. Теперь мы получаем входные данные из нашего внешнего интерфейса, когда пользователь обращается к нашему API. Чтобы использовать поддержку Pydantic, мы будем вводить нашу модель ввода, например:

@app.post("/input_predict")
def get_output_category(data: InputType):
    predicted_output = model.predict([[**data.dict()]])
    return {'prediction': predicted_output}

Это полезно, так как автоматически обрабатывает случаи неверного ввода. Кроме того, этот InputType также отображается в сгенерированных документах API.

InputType должен быть определен в другом (предпочтительном) файле с использованием базовой модели Pydantic.

from pydantic import BaseModel
from typing import Optional

class InputType(BaseModel):
    input_field1: float
    input_field2: Optional[float] = 0.1
    ...

Теперь FastAPI также позволяет HTMLResponse, если вы хотите напрямую генерировать HTML. Также для людей, имеющих опыт работы с Jinja и Django, можно использовать шаблоны Jinja2, доступные в FastAPI. Подробнее здесь.

Автоматически сгенерированные документы по умолчанию размещаются по адресу http://127.0.0.1:8000/docs и автоматически отображают информацию о ваших конечных точках, ожидаемом типе данных и типе возвращаемого значения, если он указан. Это полезно, если вы не хотите создавать модный интерфейс для своего веб-приложения, поскольку документы swagger интерактивны.

Вы можете не только отправить запрос (POST, GET, PUT, DELETE), но и указать данные по умолчанию для каждой конечной точки. Вы также можете включить информацию в описание каждой конечной точки, поля и схемы.

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

У FastAPI есть очень классный пример того, как работает параллелизм и асинхронный код с использованием бургеров! Проверьте, что здесь. Используя асинхронные методы, вы можете обучать свою модель параллельно, продолжая обслуживать API, и даже выполнять прогнозирование модели для большого объема данных и отображать выходные данные после их получения.

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

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7  
COPY ./app /app

Поскольку у нас также будут внешние библиотеки, нам придется установить их в наш файл докера. Это можно сделать с помощью команды run pip следующим образом:

RUN pip install -r requirements.txt

Если в вашем проекте нет файла requirements.txt, вы можете просто установить библиотеки, включив

RUN pip install sklearn numpy tensorflow tensorflow-gpu

и любые другие библиотеки, которые вы использовали.

Вывод

Поскольку большинство из вас пришли сюда из Flask, вы можете увидеть сходство с Flask. Но что делает FastAPI лучше, помимо скорости, так это поддержка ASGI. У нас также могут быть автоматически сгенерированные документы из FastAPI, которые действительно полезны. FastAPI — это недостающая золотая середина между Django и flask. Хотя для Data Scientist или разработчика машинного обучения Django — это излишество. FastAPI обеспечивает столь необходимое превосходство, когда речь идет о скорости и асинхронных вызовах.

Ссылки

  1. https://fastapi.tiangolo.com/tutorial/response-model/
  2. https://fastapi.tiangolo.com/deployment/docker/
  3. Привет этому простому проекту GitHub, который можно клонировать и запустить, чтобы увидеть базовую модель RF, работающую с FastAPI https://github.com/kaustubhgupta/FastAPI-Demo