繁体   English   中英

在 FastAPI 中使用 Pydantic 模型进行基于模型的预测时出现错误“value is not a valid dict”

[英]Getting error "value is not a valid dict" when using Pydantic models in FastAPI for model-based predictions

我正在尝试将Pydantic模型与 FastAPI 结合使用来进行多项预测(对于输入列表)。 问题是不能将 Pydantic 模型直接传递给model.predict() function,因此我将其转换为字典,但是,出现以下错误:

AttributeError: 'list' object has no attribute 'dict'

我的代码:

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

app = FastAPI()

class Inputs(BaseModel):
    id: int
    f1: float
    f2: float
    f3: str

class InputsList(BaseModel):
    inputs: List[Inputs]

@app.post('/predict')
def predict(input_list: InputsList):
    df = pd.DataFrame(input_list.inputs.dict())
    prediction = classifier.predict(df.loc[:, df.columns != 'id'])
    probability = classifier.predict_proba(df.loc[:, df.columns != 'id'])
    return {'id': df["id"].tolist(), 'prediction': prediction.tolist(), 'probability': probability.tolist()}

我的return也有问题,我需要 output 是这样的:

    [
      {
        "id": 123,
        "prediction": "class1",
        "probability": 0.89
      },
      {
        "id": 456,
        "prediction": "class3",
        "probability": 0.45
      }
    ]

PS: Inputs class 中的id不会出现在预测中(不是一个特征),但我需要它显示在它的预测旁边(以引用它)。

要求 在此处输入图像描述

您对视图 function 的输入模式的定义与您发送的内容不匹配:

class Inputs(BaseModel):
    id: int
    f1: float
    f2: float
    f3: str

class InputsList(BaseModel):
    inputs: List[Inputs]

这与以下格式的请求正文相匹配:

{
  "inputs": [
    {
      "id": 1,
      "f1": 1.0,
      "f2": 1.0,
      "f3": "foo"
    }, {
      "id": 2,
      "f1": 2.0,
      "f2": 2.0,
      "f3": "bar"
    }
  ]
}

您发送的请求正文与预期格式不匹配,因此您会收到 422 响应。

要么更改您要发送的 object 以匹配 FastAPI 预期的格式,要么删除InputsList包装器并将输入设置为input_list: List[Inputs]

首先,在您的模式的f1f2属性,末尾以及您发送的JSON有效负载中有不必要的逗号。 因此,您的模式应该是:

class Inputs(BaseModel):
    id: int
    f1: float
    f2: float
    f3: str

其次422错误是由于您发送的JSON负载与您的架构不匹配。 正如@MatsLindh 所指出的,您的JSON有效负载应如下所示:

{
  "inputs": [
    {
      "id": 1,
      "f1": 1.0,
      "f2": 1.0,
      "f3": "text"
    },
    {
      "id": 2,
      "f1": 2.0,
      "f2": 2.0,
      "f3": "text"
    }
  ]
}

第三,您正在以错误的方式创建 DataFrame。 您正在尝试调用list object 上的dict()方法; 因此, AttributeError: 'list' object has no attribute 'dict' 相反,如此处所示,您应该对list中的每个项目调用.dict()方法,如下所示:

df = pd.DataFrame([i.dict() for i in input_list.inputs])

最后,要返回问题中提到的 output 格式的结果,请使用以下内容。 注意predict_proba()返回一个列表数组,其中包含input的 class 个概率。 如果您只想返回特定 class 的probability ,请改用该 class 的索引,例如prob[0]

results = []
for (id, pred, prob) in zip(df["id"].tolist(), prediction.tolist(), probability.tolist()):
    results.append({"id": id, "prediction": pred, "probability": prob})
return results

或者,您可以使用 DataFrame 并调用其to_dict()方法将其转换为字典,如下所示。 如果您有大量数据并发现以下方法返回结果的速度很慢,请查看此答案以了解其他方法。

results = pd.DataFrame({'id': df["id"].tolist(),'prediction': prediction.tolist(),'probability': probability.tolist()})
return results.to_dict(orient="records") 

如果您想在使用 DataFrame 时仅返回特定 class 的probability ,您可以提取它并将其添加到新list ,例如prob_list = [item[0] for item in probability.tolist()]或使用operator.itemgetter()就像这样prob_list = list(map(itemgetter(0), probability.tolist())) ,并在创建 DataFrame 时使用该list

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM