在 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()
函数,所以我将它转换为字典,但是,我收到以下错误:
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 的问题,我需要输出类似于:
[
{
"id": 123,
"prediction": "class1",
"probability": 0.89
},
{
"id": 456,
"prediction": "class3",
"probability": 0.45
}
]
PS:Inputs
class 中的 id
没有出现在预测中(不是特征),但我需要显示它在它的预测旁边(参考它)。
要求:
您对视图函数输入架构的定义与您发送的内容不匹配:
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 响应。
要么更改您要发送的对象以匹配 FastAPI 预期的格式,要么删除 InputsList
包装器并将输入设置为 input_list: List[Inputs]
。
First,您的架构的 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
对象上调用 .dict()
方法;因此,AttributeError: 'list' object has no attribute 'dict'
。相反,如 所示,您应该在 list
中的每个项目上调用 .dict()
方法,如下所示:
df = pd.DataFrame([i.dict() for i in input_list.inputs])
最后,以return你问题中提到的输出格式的结果,使用下面的。 注意 predict_proba()
returns 列表数组,其中包含 input
的 class 概率。如果您只想 return 特定 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 时只想 return 特定 class 的 probability
,您可以提取它并将其添加到新的 list
中,例如这个 prob_list = [item[0] for item in probability.tolist()]
或使用 operator.itemgetter()
像这样 prob_list = list(map(itemgetter(0), probability.tolist()))
,并在创建 DataFrame 时使用那个 list
。
我正在尝试将 Pydantic
模型与 FastAPI 结合使用来进行多项预测(针对输入列表)。问题是不能将 Pydantic 模型直接传递给 model.predict()
函数,所以我将它转换为字典,但是,我收到以下错误:
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 的问题,我需要输出类似于:
[
{
"id": 123,
"prediction": "class1",
"probability": 0.89
},
{
"id": 456,
"prediction": "class3",
"probability": 0.45
}
]
PS:Inputs
class 中的 id
没有出现在预测中(不是特征),但我需要显示它在它的预测旁边(参考它)。
要求:
您对视图函数输入架构的定义与您发送的内容不匹配:
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 响应。
要么更改您要发送的对象以匹配 FastAPI 预期的格式,要么删除 InputsList
包装器并将输入设置为 input_list: List[Inputs]
。
First,您的架构的 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
对象上调用 .dict()
方法;因此,AttributeError: 'list' object has no attribute 'dict'
。相反,如 list
中的每个项目上调用 .dict()
方法,如下所示:
df = pd.DataFrame([i.dict() for i in input_list.inputs])
最后,以return你问题中提到的输出格式的结果,使用下面的。 注意 predict_proba()
returns 列表数组,其中包含 input
的 class 概率。如果您只想 return 特定 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 时只想 return 特定 class 的 probability
,您可以提取它并将其添加到新的 list
中,例如这个 prob_list = [item[0] for item in probability.tolist()]
或使用 operator.itemgetter()
像这样 prob_list = list(map(itemgetter(0), probability.tolist()))
,并在创建 DataFrame 时使用那个 list
。