forked from udacity/nd0821-c3-starter-code
-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.py
142 lines (121 loc) · 4.81 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
"""
Script for FastAPI instance and model inference
author: Laurent veyssier
Date: Dec. 16th 2022
"""
# Put the code for your API here.
from fastapi import FastAPI, HTTPException
from typing import Union, Optional
# BaseModel from Pydantic is used to define data objects
from pydantic import BaseModel
import pandas as pd
import os, pickle
from ml.data import process_data
# path to saved artifacts
savepath = './model'
filename = ['trained_model.pkl', 'encoder.pkl', 'labelizer.pkl']
# Declare the data object with its components and their type.
class InputData(BaseModel):
age: int
workclass: str
fnlgt: int
education: str
education_num: int
marital_status: str
occupation: str
relationship: str
race: str
sex: str
capital_gain: int
capital_loss: int
hours_per_week: int
native_country: str
class Config:
schema_extra = {
"example": {
'age':50,
'workclass':"Private",
'fnlgt':234721,
'education':"Doctorate",
'education_num':16,
'marital_status':"Separated",
'occupation':"Exec-managerial",
'relationship':"Not-in-family",
'race':"Black",
'sex':"Female",
'capital_gain':0,
'capital_loss':0,
'hours_per_week':50,
'native_country':"United-States"
}
}
# instantiate FastAPI app
app = FastAPI( title="Inference API",
description="An API that takes a sample and runs an inference",
version="1.0.0")
# load model artifacts on startup of the application to reduce latency
@app.on_event("startup")
async def startup_event():
global model, encoder, lb
# if saved model exits, load the model from disk
if os.path.isfile(os.path.join(savepath,filename[0])):
model = pickle.load(open(os.path.join(savepath,filename[0]), "rb"))
encoder = pickle.load(open(os.path.join(savepath,filename[1]), "rb"))
lb = pickle.load(open(os.path.join(savepath,filename[2]), "rb"))
@app.get("/")
async def greetings():
return "Welcome to our model API"
# This allows sending of data (our InferenceSample) via POST to the API.
@app.post("/inference/")
async def ingest_data(inference: InputData):
data = { 'age': inference.age,
'workclass': inference.workclass,
'fnlgt': inference.fnlgt,
'education': inference.education,
'education-num': inference.education_num,
'marital-status': inference.marital_status,
'occupation': inference.occupation,
'relationship': inference.relationship,
'race': inference.race,
'sex': inference.sex,
'capital-gain': inference.capital_gain,
'capital-loss': inference.capital_loss,
'hours-per-week': inference.hours_per_week,
'native-country': inference.native_country,
}
# prepare the sample for inference as a dataframe
sample = pd.DataFrame(data, index=[0])
# apply transformation to sample data
cat_features = [
"workclass",
"education",
"marital-status",
"occupation",
"relationship",
"race",
"sex",
"native-country",
]
# if saved model exits, load the model from disk
if os.path.isfile(os.path.join(savepath,filename[0])):
model = pickle.load(open(os.path.join(savepath,filename[0]), "rb"))
encoder = pickle.load(open(os.path.join(savepath,filename[1]), "rb"))
lb = pickle.load(open(os.path.join(savepath,filename[2]), "rb"))
sample,_,_,_ = process_data(
sample,
categorical_features=cat_features,
training=False,
encoder=encoder,
lb=lb
)
# get model prediction which is a one-dim array like [1]
prediction = model.predict(sample)
# convert prediction to label and add to data output
if prediction[0]>0.5:
prediction = '>50K'
else:
prediction = '<=50K',
data['prediction'] = prediction
return data
if __name__ == '__main__':
pass