【问题标题】:Can we use Pydantic models (BaseModel) directly inside model.predict() using FastAPI, and if not ,why?我们可以使用 FastAPI 直接在 model.predict() 内部使用 Pydantic 模型 (BaseModel),如果不能,为什么?
【发布时间】:2023-02-13 14:40:18
【问题描述】:

我将 Pydantic 模型 (Basemodel) 与 FastAPI 一起使用,并将输入转换为 dictionary,然后将其转换为 Pandas DataFrame 以将其传递给 model.predict() 函数以进行机器学习预测,如下所示:

from fastapi import FastAPI
import uvicorn
from pydantic import BaseModel
import pandas as pd
from typing import List

class Inputs(BaseModel):
    f1: float,
    f2: float,
    f3: str

@app.post('/predict')
def predict(features: List[Inputs]):
    output = []

    # loop the list of input features
    for data in features:
         result = {}

         # Convert data into dict() and then into a DataFrame
            data = data.dict()
            df = pd.DataFrame([data])

         # get predictions
            prediction = classifier.predict(df)[0]

         # get probability
            probability = classifier.predict_proba(df).max()

         # assign to dictionary 
            result["prediction"] = prediction
            result["probability"] = probability

         # append dictionary to list (many outputs)
            output.append(result)

    return output

它工作正常,我只是不太确定它是否优化或正确的方法,因为我将输入转换两次以获得预测。另外,我不确定它是否会起作用快速地在有一个的情况下数量巨大输入。这方面有什么改进吗?如果有办法(甚至除了使用 Pydantic 模型之外),我可以直接工作并避免进行转换和循环。

【问题讨论】:

    标签: python machine-learning fastapi prediction pydantic


    【解决方案1】:

    首先,您应该为变量/对象使用更具描述性的名称。例如:

    @app.post('/predict')
    def predict(inputs: List[Inputs]):
        for input in inputs:
        # ...
    

    您不能将 Pydantic 模型直接传递给 predict() 函数,因为它接受数据 array,而不是 Pydantic 模型。下面列出了可用的选项。

    选项1

    你可以使用:

    prediction = model.predict([[input.f1, input.f2, input.f3]])[0]
    

    选项 2

    如果您不想使用 Pandas DataFrame,如您的问题所示,即

    df = pd.DataFrame([input.dict()])
    prediction = model.predict(df)[0]
    

    您可以改为使用 __dict__ 方法获取模型中所有属性的值并将其转换为 list

    prediction = model.predict([list(input.__dict__.values())])[0]
    

    或者,最好使用 Pydantic 的 .dict() 方法:

    prediction = model.predict([list(input.dict().values())])[0]
    

    选项 3

    您可以避免循环遍历单个项目并多次调用 predict() 函数,而是使用以下代码:

    import pandas as pd
    
    df = pd.DataFrame([i.dict() for i in inputs])
    prediction = model.predict(df)
    probability = model.predict_proba(df)
    return {'prediction': prediction.tolist(), 'probability': probability.tolist()}
    

    或者(如果您不想使用 Pandas DataFrame):

    inputs_list = [list(i.dict().values()) for i in inputs]
    prediction = model.predict(inputs_list)
    probability = model.predict_proba(inputs_list)
    return {'prediction': prediction.tolist(), 'probability': probability.tolist()}
    

    【讨论】:

    • 我正在使用输入列表我不知道如何在其中使用这种方法,重新检查我的帖子我用我的案例更新了它(输入列表和输出列表)
    • 谢谢,如果我有很多功能怎么办,因为实际上我有 40 个功能,所以把它们都写出来会很累
    • 这不会浪费内存吧?因为我为到达项目创建了一个数据框,想象一下有 50 万个项目?
    • 收到“AttributeError:'list'对象没有属性'的错误字典'"
    • 有用!我希望我可以像通常使用 mode.predict 那样摆脱循环并直接分配数据
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多