![](/img/trans.png)
[英]FastAPI gives "value is not a valid dict (type=type_error.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]
。
首先,在您的模式的f1
和f2
属性,
末尾以及您发送的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.