-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.py
165 lines (147 loc) · 4.98 KB
/
server.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Imports
import os
from tqdm import tqdm
from flask import Flask, request, render_template
import csv
from pandas import DataFrame
from numpy import nan
from joblib import load
from util import *
# Setup
app = Flask(__name__)
# Page Render
@app.route('/', methods=['GET'])
def page():
models = os.listdir("models")
context = {
"models": models
}
return render_template('index.html', context=context)
# --- APIs ---
@app.route('/api/data', methods=['GET'])
def data():
with open("model-dev/titanic.csv", "r", newline='') as fh:
csv_reader = csv.reader(fh, delimiter=',')
titanic_data = list(csv_reader)
return titanic_data
@app.route('/api/model', methods=['GET', 'POST'])
def model():
if request.method == 'GET':
return os.listdir("models")
else:
args = request.args
if ('model' not in args) or (args.get('model') not in os.listdir('models')):
return {
"success": 0,
"message": "Invalid Model"
}, 400
model = args.get('model')
submitData = request.get_json()
if isinstance(submitData, list):
return handle_batch_request(model, submitData)
elif isinstance(submitData, dict):
return call_model(model, submitData)
else:
return {
"success": 0,
"message": "Invalid Model"
}, 400
# --- Helpers ---
def call_model(model_name, point, batch=False):
try:
if model_name == 'KerasFNN.pkl':
# Load point
if batch:
point_df = point
else:
point_df = DataFrame(point, index=['0'])
point_df = proccess_data(point_df)
cleaned = preproccess_nn(point_df)
# Load model and make preds
model = load(f'./models/{model_name}')
y_pred_prob = model.predict(cleaned, verbose = 0)
y_pred = (y_pred_prob > 0.5).astype(int)
return {
"success": 1,
"message": f"Model prediction for model: {model_name}",
"prediction": int(y_pred)
}, 200
else:
# Load point
if batch:
point_df = point
else:
point_df = DataFrame(point, index=['0'])
point_df = proccess_data(point_df)
# Load model and make preds
model = load(f'./models/{model_name}')
predictions = model.predict(point_df)
return {
"success": 1,
"message": f"Model prediction for model: {model_name}",
"prediction": int(predictions)
}, 200
except Exception as e:
print(e, flush=True)
return {
"success": 0,
"message": "Internal Server Error"
}, 500
def handle_batch_request(model, submitData):
submitDataHeaders = submitData.pop(0)
errors = []
predResponses = {}
# Attempt to handle a mass submit otherwise iterate one by one
try:
submitDataDF = DataFrame(submitData, columns=submitDataHeaders)
pred_result = call_model(model, submitDataDF, batch=True)
if 'success' in pred_result[0] and pred_result[0]['success'] == 0:
raise ValueError()
return {
"success": 1,
"message": f"Model prediction for model: {model}",
"prediction": pred_result
}, 200
except Exception as e:
for dataRow in tqdm(submitData, total=len(submitData), bar_format='{l_bar}{bar:50}{r_bar}{bar:-50b}'):
try:
point = dict(zip(submitDataHeaders, dataRow))
pred_result = call_model(model, point)
if 'success' in pred_result[0] and pred_result[0]['success'] == 0:
raise ValueError()
predResponses[point['PassengerId']] = pred_result[0]['prediction']
except Exception as e:
errors.append(point['PassengerId'])
dataReturn = ({
"success": 1,
"message": f"Model prediction for model: {model}",
"prediction": predResponses,
"errors": errors
}, 200) if len(errors) < len(submitData) else ({
"success": 0,
"message": "Internal Server Error"
}, 500)
return dataReturn
def proccess_data(point_df):
column_data_types = {
"PassengerId": int,
"Pclass": int,
"Name": str,
"Sex": str,
"Age": float,
"SibSp": int,
"Parch": int,
"Ticket": str,
"Fare": float,
"Cabin": str,
"Embarked": str
}
for column, data_type in column_data_types.items():
try:
point_df[column] = point_df[column].astype(data_type)
except ValueError as e:
point_df[column] = nan
point_df = point_df.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1)
if 'Survived' in point_df:
point_df = point_df.drop(['Survived'], axis=1)
return point_df