数据STUDIO

机器学习模型部署之 FastAPI 速成

本文中,云朵君将和大家一起学习FastAPI,我们可以使用了FastAPI将机器学习模型部署为API。
一般来说,对于机器学习,我们常常使用Flask( 点击查看 👉 使用 Flask API 将机器学习模型部署到生产环境中 ),一个轻量级的后台框架,来部署我们的模型。当涉及到用Python构建后端时,Django也是一个流行的选择。但我更喜欢使用FastAPI而不是Flask,原因有几个。
  • 首先,关键优势之一是速度;FastAPI使用pydantic进行数据验证,Starlette进行工具化。这使得FastAPI的性能与Node或Go相当。
  • 其次,它还支持开箱即用的异步模式。这意味着你可以同时运行coroutines,如果按顺序运行,这将大大减少执行时间。
  • 第三,FastAPI有很好的开发体验,因为它感觉像Flask这样的轻量级库。
  • 第四,它带有开箱即用的OpenAPI文档,使前端团队更容易与API集成。我已经使用FastAPI很长时间了。通常情况下,我得到的前端开发人员比其他框架少,因为我为他们提供了FastAPI自动生成的文档。
  • 最后,它给你提供了广泛的、例子丰富的文档。我不记得我最后一次在FastAPI文档(主要是Stackoverflow)之外查找东西来实现某个功能。

考虑到这一点,我们用FastAPI写一个最小的例子,了解如何用FastAPI部署任何机器学习模型。

学习目标

学习完本章后,我们不应该能够独立完成:

  • 用FastAPI部署机器学习模型
  • 了解使用FastAPI的基础知识
  • 用pydantic轻松进行数据验证

创建一个简单的推理API

我们将从一个简单的推理API开始,并将我们的模型相关的东西(序列化的模型文件、测试、预处理文件等等)放在一个叫做ml的模块中。我们不会为我们的简单模型维护任何测试,但这是你在创建机器学习推理API时应该遵循的结构。以下将是我们文件夹的结构。

在我们的API模块中,我们有主文件和一个包含测试的ml文件夹, model.py 为API加载模型。现在我们先查看 model.py 。

下面是这个文件中的代码。

# model.py
MALE_WORDS = ['he', 'him', 'his']
FEMALE_WORDS = ['she', 'her']
min_length = 10

def preprocess(text): return text.lower().split(' ')
def predict(text):
    m = 0
    f = 0
    preprocessed = preprocess(text)
    for word in MALE_WORDS:
        if word.lower() in preprocessed:
            m += 1
    for word in FEMALE_WORDS:
        if word.lower() in preprocessed:
            f += 1

    return {
        "gender_content": {
            "male": m/(m+f) if (m+f) != 0 else 0,
            "female": f/(m+f) if (m+f) != 0 else 0
        },
        "text_processed": preprocessed,
    }
这是一个简单的模型,根据某些关键词获得男性和女性的百分比。我还提到了文本的 min_length 作为一个输入约束。我们将在后面看到我们如何为我们的输入强制执行这个约束。 这一点很重要,因为当从用户那里获得输入时,必须确保我们以适当的格式获得输入,可以用 pydantic 轻松地执行这一点。 这个模型很简单。它通过空间分割文本来进行标记,然后检查简单模型中存在的所有男性/女性词汇。然后,它返回男性、女性的内容以及预处理的文本。所以,现在进入 main.py 文件,检查里面的代码是什么。
from fastapi import FastAPI
from .ml.model import predict, min_length
@app.get("/")
def health():
  return {"message": "API is working"}
@app.post("/predict")
def predict_gender_content(text: str):
  resp = predict(text)
  return resp

这就是创建具有完整文档支持(通过OpenAPI)的API的简单程度。我们得到预测函数并创建一个 @app.post 路由,用于获取文本并返回响应。注意,要运行这个程序,需要安装 uvicorn 并输入“ uvicorn api.main:app –reload ”。

看看是如何查找文档的:

我们可以看到一个文本参数作为输入,现在可以用任何文本来测试该模型。

但是最小文本长度怎么办?我们怎样才能将其纳入呢?一种方法是在预测端点检查输入长度,当它不满足最小长度时返回错误信息。但是可以通过pydantic验证器做得更好。我们还需要向用户展示输入和输出的适当结构。

定义输入和输出数据结构并处理数据验证

我们直接进入代码,看看处理这个问题有多容易:

# main.py
from typing import Optional, List
from fastapi import FastAPI
from pydantic import BaseModel, validator
from .ml.model import predict, preprocess, min_length

class PredictRequest(BaseModel):
    data: str

    @validator("data")
    def check_length(cls, t):
        if len(t) < min_length:
            raise ValueError(f"Text is too short! require at least {min_length} characters")
        return t

class PredictResponse(BaseModel):
    data: dict

app = FastAPI()

@app.get("/")
def health():
    return {"message": "API is working"}

@app.post("/predict", response_model=PredictResponse)
def predict_gender_content(input: PredictRequest):
    text = input.data
    resp = predict(text)
    result = PredictResponse(data=resp)
    return result

我们定义 PredictRequest 类,该类继承自 pydantic 的 BaseModel ,我们将其定义为一个字符串和一个验证器,用于检查文本是否具有适当的长度。这就是我们对输入数据实施验证的地方。而一般来说,在机器学习中,我们会对数据维度进行验证(比方说,我们正在构建一个预测房价的应用程序,有十个特征;应该检查数据是否包含十个值。我们可以按照这个过程来做,定义一个带有适当验证的 PredictRequest 。我们还定义了一个 PredictResponse 类,定义了输出的结构和修改后的预测路线。

现在,如果传递一个短于10的字符串,那么将得到一个422错误,其信息是在验证器中定义的,如下所示。

无效数据的错误响应

定义请求和响应格式的原因是为了使用户能够很容易地将我们的API与他们的代码集成。

总结

至此,我们结束了对FastAPI的简短介绍。现在,你可以为你的机器学习模型创建一个推理API,并遵循一个适当的结构。首先,我们创建了一个简单的推理API,然后添加输入和适当的数据验证。更多优质内容,请关注和星标公众号 数据STUDIO 。

需要记住的几点

以下是需要记住的几个要点。

  • FastAPI对网络使用starlette,对数据验证使用pydantic。
  • FastAPI拥有开箱即用的async和await。
  • 始终从用户那里验证你的输入数据

🏴‍☠️宝藏级🏴‍☠️ 原创公众号『 数据STUDIO 』内容超级硬核。公众号以Python为核心语言,垂直于数据科学领域,包括 可戳 👉 Python | MySQL | 数据分析 | 数据可视化 | 机器学习与数据挖掘 | 爬虫 等,从入门到进阶!
长按👇关注- 数据STUDIO -设为星标,干货速递