Spaces:
Runtime error
Runtime error
App Deployed.
Browse files- ensemble_model.pkl +3 -0
- main.py +299 -0
- requirements.txt +13 -0
- templates/index.html +237 -0
- templates/prediction.html +165 -0
ensemble_model.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:bf5c8a9bb51b7ecf3649aab68357394c1ce6c51d8ffb74b0091074ae330b393e
|
3 |
+
size 54780923
|
main.py
ADDED
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, request, jsonify, render_template, session, url_for, redirect
|
2 |
+
from flask_wtf import FlaskForm
|
3 |
+
from flask_wtf import Form
|
4 |
+
from flask_bootstrap import Bootstrap
|
5 |
+
from wtforms import StringField, SubmitField, SelectField
|
6 |
+
import pickle
|
7 |
+
import joblib
|
8 |
+
import numpy as np
|
9 |
+
|
10 |
+
app = Flask(__name__, template_folder='templates')
|
11 |
+
app.config['SECRET_KEY'] = b'_5#y2L"F4Q8z\n\xec]/'
|
12 |
+
model = joblib.load('ensemble_model.pkl')
|
13 |
+
|
14 |
+
|
15 |
+
def return_prediction(model, input_json) :
|
16 |
+
|
17 |
+
input_data = [[input_json[k] for k in input_json.keys()]]
|
18 |
+
prediction = model.predict(input_data)[0]
|
19 |
+
|
20 |
+
return prediction
|
21 |
+
|
22 |
+
|
23 |
+
class PredictForm(FlaskForm):
|
24 |
+
age = StringField("Age")
|
25 |
+
gender = SelectField("Gender", choices=[('male', 'Male'), ('female', 'Female')])
|
26 |
+
annual_income = StringField("Annual Income")
|
27 |
+
marital_status = SelectField("Marital Status", choices=[('married', 'Married'), ('single', 'Single'), ('divorced', 'Divorced')])
|
28 |
+
dependents = StringField("Number of Dependents")
|
29 |
+
education_level = SelectField("Education Level", choices=[('high_school', "High School"), ('bachelors', "Bachelor's"), ("masters", "'Master's"), ('phd', "PHD")])
|
30 |
+
occupation = SelectField("Occupation", choices=[('unemployed', 'Unemployed'), ('self_employed', 'Self-Employed'), ('employed', 'Employed')])
|
31 |
+
health_score = StringField("Health Score")
|
32 |
+
location = SelectField("Location", choices=[('rural', 'Rural'), ('suburban', 'Suburban'), ('urban', 'Urban')])
|
33 |
+
policy_type = SelectField("Policy Type", choices=[('basic', 'Basic'), ('comprehensive', 'Comprehensive'), ('premium', 'Premium')])
|
34 |
+
previous_claims = StringField("Previous Claims")
|
35 |
+
vehicle_age = StringField("Vehicle Age (in years)")
|
36 |
+
credit_score = StringField("Credit Score")
|
37 |
+
insurance_duration = StringField("Insurance Duration")
|
38 |
+
customer_feedback = SelectField("Customer Feedback", choices=[('poor', 'Poor'), ('average', 'Average'), ('good', 'Good')])
|
39 |
+
smoking_status = SelectField("Smoking Status", choices=[('yes', 'Yes'), ('no', 'No')])
|
40 |
+
exercise_frequency = SelectField("Exercise Frequency", choices=[('rarely', 'Rarely'), ('monthly', 'Monthly'), ('weekly', 'Weekly'), ('daily', 'Daily')])
|
41 |
+
property_type = SelectField("Property Type", choices=[('apartment', 'Apartment'), ('condo', 'Condo'), ('house', 'House')])
|
42 |
+
year = StringField("Year")
|
43 |
+
day = StringField("Day (of the month)")
|
44 |
+
month = StringField("Month (1-12)")
|
45 |
+
month_name = ""
|
46 |
+
day_of_week = StringField("Day of the Week (1-7)")
|
47 |
+
|
48 |
+
contract_length = ""
|
49 |
+
income_per_dependent = ""
|
50 |
+
credit_score_insurance_duration = ""
|
51 |
+
health_risk_score = ""
|
52 |
+
credit_health_score = ""
|
53 |
+
health_age_interaction = ""
|
54 |
+
|
55 |
+
submit = SubmitField("Predict")
|
56 |
+
|
57 |
+
|
58 |
+
|
59 |
+
@app.route('/', methods=['GET', 'POST'])
|
60 |
+
def index():
|
61 |
+
|
62 |
+
form = PredictForm()
|
63 |
+
|
64 |
+
if form.validate_on_submit():
|
65 |
+
|
66 |
+
# age
|
67 |
+
session['age'] = form.age.data
|
68 |
+
|
69 |
+
# gender
|
70 |
+
if(form.gender.data == 'female'):
|
71 |
+
session['pronoun'] = 0
|
72 |
+
session['gender'] = 'Female'
|
73 |
+
else:
|
74 |
+
session['pronoun'] = 1
|
75 |
+
session['gender'] = 'Male'
|
76 |
+
|
77 |
+
# annual income
|
78 |
+
session['annual_income'] = form.annual_income.data
|
79 |
+
|
80 |
+
# marital status
|
81 |
+
if(form.marital_status.data == 'married'):
|
82 |
+
session['married'] = 0
|
83 |
+
session['marital_status'] = 'Married'
|
84 |
+
elif(form.marital_status.data == 'single'):
|
85 |
+
session['married'] = 2
|
86 |
+
session['marital_status'] = 'Single'
|
87 |
+
else:
|
88 |
+
session['married'] = 1
|
89 |
+
session['marital_status'] = 'Divorced'
|
90 |
+
|
91 |
+
# dependents
|
92 |
+
session['dependents'] = form.dependents.data
|
93 |
+
|
94 |
+
# education level
|
95 |
+
if(form.education_level.data == 'high_school'):
|
96 |
+
session['education'] = 0
|
97 |
+
session['education_level'] = 'High School'
|
98 |
+
elif(form.education_level.data == 'bachelors'):
|
99 |
+
session['education'] = 1
|
100 |
+
session['education_level'] = 'Bachelor\'s'
|
101 |
+
elif(form.education_level.data == 'masters'):
|
102 |
+
session['education'] = 2
|
103 |
+
session['education_level'] = 'Master\'s'
|
104 |
+
else:
|
105 |
+
session['education'] = 3
|
106 |
+
session['education_level'] = 'PHD'
|
107 |
+
|
108 |
+
# occupation
|
109 |
+
if(form.occupation.data == 'unemployed'):
|
110 |
+
session['occupation'] = 0
|
111 |
+
session['occupation_status'] = 'Unemployed'
|
112 |
+
elif(form.occupation.data == 'self_employed'):
|
113 |
+
session['occupation'] = 1
|
114 |
+
session['occupation_status'] = 'Self-Employed'
|
115 |
+
else:
|
116 |
+
session['occupation'] = 2
|
117 |
+
session['occupation_status'] = 'Employed'
|
118 |
+
|
119 |
+
# health score
|
120 |
+
session['health_score'] = form.health_score.data
|
121 |
+
|
122 |
+
# location
|
123 |
+
if(form.location.data == 'rural'):
|
124 |
+
session['place'] = 0
|
125 |
+
session['location'] = 'Rural'
|
126 |
+
elif(form.location.data == 'suburban'):
|
127 |
+
session['place'] = 1
|
128 |
+
session['location'] = 'Suburban'
|
129 |
+
else:
|
130 |
+
session['place'] = 2
|
131 |
+
session['location'] = 'Urban'
|
132 |
+
|
133 |
+
# policy type
|
134 |
+
if(form.policy_type.data == 'basic'):
|
135 |
+
session['policy_type'] = 0
|
136 |
+
session['policy'] = 'Basic'
|
137 |
+
elif(form.policy_type.data == 'comprehensive'):
|
138 |
+
session['policy_type'] = 1
|
139 |
+
session['policy'] = 'Comprehensive'
|
140 |
+
else:
|
141 |
+
session['policy_type'] = 2
|
142 |
+
session['policy'] = 'Premium'
|
143 |
+
|
144 |
+
# previous claims
|
145 |
+
session['previous_claims'] = form.previous_claims.data
|
146 |
+
|
147 |
+
# vehicle age
|
148 |
+
session['vehicle_age'] = form.vehicle_age.data
|
149 |
+
|
150 |
+
# credit score
|
151 |
+
session['credit_score'] = form.credit_score.data
|
152 |
+
|
153 |
+
# insurance duration
|
154 |
+
session['insurance_duration'] = form.insurance_duration.data
|
155 |
+
|
156 |
+
# customer feedback
|
157 |
+
if(form.customer_feedback.data == 'poor'):
|
158 |
+
session['feedback'] = 0
|
159 |
+
session['feedback_status'] = 'Poor'
|
160 |
+
elif(form.customer_feedback.data == 'average'):
|
161 |
+
session['feedback'] = 1
|
162 |
+
session['feedback_status'] = 'Average'
|
163 |
+
else:
|
164 |
+
session['feedback'] = 2
|
165 |
+
session['feedback_status'] = 'Good'
|
166 |
+
|
167 |
+
# smoking status
|
168 |
+
if(form.smoking_status.data == 'yes'):
|
169 |
+
session['smoke'] = 1
|
170 |
+
session['smoking_status'] = 'Yes'
|
171 |
+
else:
|
172 |
+
session['smoke'] = 0
|
173 |
+
session['smoking_status'] = 'No'
|
174 |
+
|
175 |
+
# exercise frequency
|
176 |
+
if(form.exercise_frequency.data == 'rarely'):
|
177 |
+
session['exercise'] = 0
|
178 |
+
session['exercise_frequency'] = 'Rarely'
|
179 |
+
elif(form.exercise_frequency.data == 'monthly'):
|
180 |
+
session['exercise'] = 1
|
181 |
+
session['exercise_frequency'] = 'Monthly'
|
182 |
+
elif(form.exercise_frequency.data == 'weekly'):
|
183 |
+
session['exercise'] = 2
|
184 |
+
session['exercise_frequency'] = 'Weekly'
|
185 |
+
else:
|
186 |
+
session['exercise'] = 3
|
187 |
+
session['exercise_frequency'] = 'Daily'
|
188 |
+
|
189 |
+
# property type
|
190 |
+
if(form.property_type.data == 'apartment'):
|
191 |
+
session['property'] = 0
|
192 |
+
session['property_type'] = 'Apartment'
|
193 |
+
elif(form.property_type.data == 'condo'):
|
194 |
+
session['property'] = 1
|
195 |
+
session['property_type'] = 'Condo'
|
196 |
+
else:
|
197 |
+
session['property'] = 2
|
198 |
+
session['property_type'] = 'House'
|
199 |
+
|
200 |
+
# year
|
201 |
+
session['year'] = form.year.data
|
202 |
+
|
203 |
+
# day
|
204 |
+
session['day'] = form.day.data
|
205 |
+
|
206 |
+
# month
|
207 |
+
session['month'] = form.month.data
|
208 |
+
|
209 |
+
session['month_name'] = form.month.data
|
210 |
+
|
211 |
+
# day of the week
|
212 |
+
session['day_of_week'] = form.day_of_week.data
|
213 |
+
|
214 |
+
# contract length
|
215 |
+
session['contract_length'] = 0
|
216 |
+
if(float(session['insurance_duration']) < 1):
|
217 |
+
session['contract_length'] = 0
|
218 |
+
elif(float(session['insurance_duration']) < 5):
|
219 |
+
session['contract_length'] = 1
|
220 |
+
else:
|
221 |
+
session['contract_length'] = 2
|
222 |
+
|
223 |
+
if(float(session['dependents']) == 0):
|
224 |
+
session['dependents'] = 1
|
225 |
+
|
226 |
+
# income per dependent
|
227 |
+
session['income_per_dependent'] = float(session['annual_income']) / float(session['dependents'])
|
228 |
+
|
229 |
+
# credit score insurance duration
|
230 |
+
session['credit_score_insurance_duration'] = float(session['credit_score']) * float(session['insurance_duration'])
|
231 |
+
|
232 |
+
# health risk score
|
233 |
+
session['health_risk_score'] = float(session['smoke']) + float(session['exercise']) - float(session['health_score']) / 20
|
234 |
+
|
235 |
+
# credit health score
|
236 |
+
session['credit_health_score'] = float(session['credit_score']) * float(session['health_score'])
|
237 |
+
|
238 |
+
# health age interaction
|
239 |
+
session['health_age_interaction'] = float(session['health_score']) * float(session['age'])
|
240 |
+
|
241 |
+
return redirect(url_for('predict'))
|
242 |
+
|
243 |
+
return render_template('index.html', form=form)
|
244 |
+
|
245 |
+
|
246 |
+
|
247 |
+
# return """
|
248 |
+
# <h1>Model Deployment</hjson>
|
249 |
+
# <p>Use a POST request to /predict to get a prediction of Premium Amount</p>
|
250 |
+
# <ul>
|
251 |
+
# <li>Annual Income</li>
|
252 |
+
# <li>Age</li>
|
253 |
+
# <li>Gender</li>
|
254 |
+
# <li>Dependents</li>
|
255 |
+
# </ul>
|
256 |
+
# """
|
257 |
+
|
258 |
+
@app.route('/predict')
|
259 |
+
def predict():
|
260 |
+
|
261 |
+
content = {}
|
262 |
+
|
263 |
+
content['Age'] = float(session['age'])
|
264 |
+
content['Gender'] = float(session['pronoun'])
|
265 |
+
content['Annual Income'] = float(session['annual_income'])
|
266 |
+
content['Marital Status'] = float(session['married'])
|
267 |
+
content['Number of Dependents'] = float(session['dependents'])
|
268 |
+
content['Education Level'] = float(session['education'])
|
269 |
+
content['Occupation'] = float(session['occupation'])
|
270 |
+
content['Health Score'] = float(session['health_score'])
|
271 |
+
content['Location'] = float(session['place'])
|
272 |
+
content['Policy Type'] = float(session['policy_type'])
|
273 |
+
content['Previous Claims'] = float(session['previous_claims'])
|
274 |
+
content['Vehicle Age'] = float(session['vehicle_age'])
|
275 |
+
content['Credit Score'] = float(session['credit_score'])
|
276 |
+
content['Insurance Duration'] = float(session['insurance_duration'])
|
277 |
+
content['Customer Feedback'] = float(session['feedback'])
|
278 |
+
content['Smoking Status'] = float(session['smoke'])
|
279 |
+
content['Exercise Frequency'] = float(session['exercise'])
|
280 |
+
content['Property Type'] = float(session['property'])
|
281 |
+
content['Year'] = float(session['year'])
|
282 |
+
content['Day'] = float(session['day'])
|
283 |
+
content['Month'] = float(session['month'])
|
284 |
+
content['Month Name'] = float(session['month_name'])
|
285 |
+
content['Day of the Week'] = float(session['day_of_week'])
|
286 |
+
content['contract length'] = float(session['contract_length'])
|
287 |
+
content['Income to Dependents Ratio'] = float(session['income_per_dependent'])
|
288 |
+
content['CreditScore_InsuranceDuration'] = float(session['credit_score_insurance_duration'])
|
289 |
+
content['Health_Risk_Score'] = float(session['health_risk_score'])
|
290 |
+
content['Credit_Health_Score'] = float(session['credit_health_score'])
|
291 |
+
content['Health_Age_Interaction'] = float(session['health_age_interaction'])
|
292 |
+
|
293 |
+
prediction = return_prediction(model, content)
|
294 |
+
prediction = np.expm1(prediction)
|
295 |
+
return render_template('prediction.html', prediction=prediction)
|
296 |
+
|
297 |
+
Bootstrap = Bootstrap(app)
|
298 |
+
if __name__ == '__main__':
|
299 |
+
app.run(debug=True)
|
requirements.txt
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
ipykernel
|
2 |
+
pandas
|
3 |
+
matplotlib
|
4 |
+
seaborn
|
5 |
+
scikit-learn==1.2.2
|
6 |
+
catboost==1.2.7
|
7 |
+
lightgbm==4.5.0
|
8 |
+
xgboost==2.0.3
|
9 |
+
optuna
|
10 |
+
Flask
|
11 |
+
flask_wtf
|
12 |
+
flask_bootstrap
|
13 |
+
gunicorn
|
templates/index.html
ADDED
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
|
4 |
+
<head>
|
5 |
+
<meta charset="UTF-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
+
<!-- Bootstrap 5 CSS -->
|
8 |
+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEJr+K+GkABh9h3l+mybJfA0bG5gHiE5Q1LO1rHwUtZoZr8JjxfQEC8t09/8U" crossorigin="anonymous">
|
9 |
+
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">
|
10 |
+
|
11 |
+
<!-- FontAwesome Icons -->
|
12 |
+
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
|
13 |
+
|
14 |
+
<title>Insurance Premium Amount Prediction</title>
|
15 |
+
<style>
|
16 |
+
body {
|
17 |
+
background: linear-gradient(to right, rgba(34, 193, 195, 0.8), rgba(253, 187, 45, 0.8));
|
18 |
+
background-size: cover;
|
19 |
+
font-family: 'Arial', sans-serif;
|
20 |
+
color: #333;
|
21 |
+
margin: 0;
|
22 |
+
padding: 0;
|
23 |
+
height: 100vh; /* Full viewport height */
|
24 |
+
display: flex;
|
25 |
+
justify-content: center;
|
26 |
+
align-items: center;
|
27 |
+
flex-direction: column;
|
28 |
+
}
|
29 |
+
|
30 |
+
.form-container {
|
31 |
+
background-color: rgba(255, 255, 255, 0.9); /* White background with transparency */
|
32 |
+
border-radius: 15px;
|
33 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
34 |
+
padding: 40px;
|
35 |
+
width: 100%;
|
36 |
+
max-width: 800px;
|
37 |
+
overflow-y: auto;
|
38 |
+
max-height: 90vh; /* Prevents overflow */
|
39 |
+
}
|
40 |
+
|
41 |
+
h1 {
|
42 |
+
font-size: 36px;
|
43 |
+
font-weight: bold;
|
44 |
+
color: #333;
|
45 |
+
text-align: center;
|
46 |
+
}
|
47 |
+
|
48 |
+
h3 {
|
49 |
+
font-size: 18px;
|
50 |
+
color: #555;
|
51 |
+
line-height: 1.6;
|
52 |
+
text-align: center;
|
53 |
+
margin-bottom: 20px;
|
54 |
+
}
|
55 |
+
|
56 |
+
label {
|
57 |
+
font-size: 16px;
|
58 |
+
font-weight: 500;
|
59 |
+
color: #333;
|
60 |
+
}
|
61 |
+
|
62 |
+
.form-control {
|
63 |
+
border-radius: 8px;
|
64 |
+
height: 45px;
|
65 |
+
border: 1px solid #ccc;
|
66 |
+
font-size: 16px;
|
67 |
+
margin-bottom: 15px;
|
68 |
+
}
|
69 |
+
|
70 |
+
.btn-primary {
|
71 |
+
background-color: #007bff;
|
72 |
+
border-color: #007bff;
|
73 |
+
padding: 12px 20px;
|
74 |
+
font-size: 16px;
|
75 |
+
border-radius: 8px;
|
76 |
+
}
|
77 |
+
|
78 |
+
.btn-primary:hover {
|
79 |
+
background-color: #0056b3;
|
80 |
+
}
|
81 |
+
|
82 |
+
.form-group {
|
83 |
+
margin-bottom: 20px;
|
84 |
+
}
|
85 |
+
|
86 |
+
.form-group input,
|
87 |
+
.form-group select {
|
88 |
+
width: 100%;
|
89 |
+
}
|
90 |
+
|
91 |
+
.form-check-label {
|
92 |
+
font-size: 16px;
|
93 |
+
color: #333;
|
94 |
+
}
|
95 |
+
|
96 |
+
.custom-input-group {
|
97 |
+
display: flex;
|
98 |
+
justify-content: space-between;
|
99 |
+
gap: 10px;
|
100 |
+
}
|
101 |
+
|
102 |
+
.custom-input-group select {
|
103 |
+
flex-grow: 1;
|
104 |
+
}
|
105 |
+
|
106 |
+
.form-check {
|
107 |
+
margin-top: 10px;
|
108 |
+
}
|
109 |
+
|
110 |
+
.form-group input,
|
111 |
+
.form-group select,
|
112 |
+
.form-group textarea {
|
113 |
+
width: 100%;
|
114 |
+
}
|
115 |
+
|
116 |
+
/* Add a subtle abstract pattern as the background */
|
117 |
+
.abstract-background {
|
118 |
+
position: absolute;
|
119 |
+
top: 0;
|
120 |
+
left: 0;
|
121 |
+
width: 100%;
|
122 |
+
height: 100%;
|
123 |
+
background-image: url('https://www.transparenttextures.com/patterns/asfalt.png'); /* Abstract pattern */
|
124 |
+
background-repeat: repeat;
|
125 |
+
z-index: -1; /* Make sure it's behind the content */
|
126 |
+
}
|
127 |
+
</style>
|
128 |
+
</head>
|
129 |
+
|
130 |
+
<body>
|
131 |
+
<!-- Add the abstract background -->
|
132 |
+
<div class="abstract-background"></div>
|
133 |
+
|
134 |
+
<div class="form-container">
|
135 |
+
<h1>Insurance Premium Amount Predictor</h1>
|
136 |
+
<h3 class="mb-4">The purpose of this model is to predict insurance premiums based on various customer characteristics and policy details. Since the model has been trained on synthetically generated data which simulates real-world scenarios (from a Kaggle competition), the predicted value is not for real world usage, but should rather be leveraged to get an educated assumption. Since insurance premium amount is prone to a lot of risk, we need to collect all your information. Please bear with me and carefully enter your details below:</h3>
|
137 |
+
|
138 |
+
<form method="POST">
|
139 |
+
{{ form.hidden_tag() }}
|
140 |
+
|
141 |
+
<!-- Styling the Form Elements Without Modifying the Form Itself -->
|
142 |
+
<div class="form-group">
|
143 |
+
{{ form.age.label }} {{ form.age }}
|
144 |
+
</div>
|
145 |
+
<div class="form-group">
|
146 |
+
{{ form.gender.label }} {{ form.gender }}
|
147 |
+
</div>
|
148 |
+
<div class="form-group">
|
149 |
+
{{ form.annual_income.label }} {{ form.annual_income }}
|
150 |
+
</div>
|
151 |
+
<div class="form-group">
|
152 |
+
{{ form.marital_status.label }} {{ form.marital_status }}
|
153 |
+
</div>
|
154 |
+
<div class="form-group">
|
155 |
+
{{ form.dependents.label }} {{ form.dependents }}
|
156 |
+
</div>
|
157 |
+
<div class="form-group">
|
158 |
+
{{ form.education_level.label }} {{ form.education_level }}
|
159 |
+
</div>
|
160 |
+
<div class="form-group">
|
161 |
+
{{ form.occupation.label }} {{ form.occupation }}
|
162 |
+
</div>
|
163 |
+
<div class="form-group">
|
164 |
+
{{ form.health_score.label }} {{ form.health_score }}
|
165 |
+
</div>
|
166 |
+
<div class="form-group">
|
167 |
+
{{ form.location.label }} {{ form.location }}
|
168 |
+
</div>
|
169 |
+
<div class="form-group">
|
170 |
+
{{ form.policy_type.label }} {{ form.policy_type }}
|
171 |
+
</div>
|
172 |
+
<div class="form-group">
|
173 |
+
{{ form.previous_claims.label }} {{ form.previous_claims }}
|
174 |
+
</div>
|
175 |
+
<div class="form-group">
|
176 |
+
{{ form.vehicle_age.label }} {{ form.vehicle_age }}
|
177 |
+
</div>
|
178 |
+
<div class="form-group">
|
179 |
+
{{ form.credit_score.label }} {{ form.credit_score }}
|
180 |
+
</div>
|
181 |
+
<div class="form-group">
|
182 |
+
{{ form.insurance_duration.label }} {{ form.insurance_duration }}
|
183 |
+
</div>
|
184 |
+
<div class="form-group">
|
185 |
+
{{ form.customer_feedback.label }} {{ form.customer_feedback }}
|
186 |
+
</div>
|
187 |
+
<div class="form-group">
|
188 |
+
{{ form.smoking_status.label }} {{ form.smoking_status }}
|
189 |
+
</div>
|
190 |
+
<div class="form-group">
|
191 |
+
{{ form.exercise_frequency.label }} {{ form.exercise_frequency }}
|
192 |
+
</div>
|
193 |
+
<div class="form-group">
|
194 |
+
{{ form.property_type.label }} {{ form.property_type }}
|
195 |
+
</div>
|
196 |
+
<div class="form-group custom-input-group">
|
197 |
+
{{ form.year.label }} {{ form.year }}
|
198 |
+
{{ form.day.label }} {{ form.day }}
|
199 |
+
{{ form.month.label }} {{ form.month }}
|
200 |
+
</div>
|
201 |
+
<div class="form-group">
|
202 |
+
{{ form.month_name.label }} {{ form.month_name }}
|
203 |
+
</div>
|
204 |
+
<div class="form-group">
|
205 |
+
{{ form.day_of_week.label }} {{ form.day_of_week }}
|
206 |
+
</div>
|
207 |
+
<div class="form-group">
|
208 |
+
{{ form.contract_length.label }} {{ form.contract_length }}
|
209 |
+
</div>
|
210 |
+
<div class="form-group">
|
211 |
+
{{ form.income_per_dependent.label }} {{ form.income_per_dependent }}
|
212 |
+
</div>
|
213 |
+
<div class="form-group">
|
214 |
+
{{ form.credit_score_insurance_duration.label }} {{ form.credit_score_insurance_duration }}
|
215 |
+
</div>
|
216 |
+
<div class="form-group">
|
217 |
+
{{ form.health_risk_score.label }} {{ form.health_risk_score }}
|
218 |
+
</div>
|
219 |
+
<div class="form-group">
|
220 |
+
{{ form.credit_health_score.label }} {{ form.credit_health_score }}
|
221 |
+
</div>
|
222 |
+
<div class="form-group">
|
223 |
+
{{ form.health_age_interaction.label }} {{ form.health_age_interaction }}
|
224 |
+
</div>
|
225 |
+
|
226 |
+
<div class="form-group text-center">
|
227 |
+
{{ form.submit(class="btn btn-primary") }}
|
228 |
+
</div>
|
229 |
+
</form>
|
230 |
+
</div>
|
231 |
+
|
232 |
+
<!-- Bootstrap JS and dependencies -->
|
233 |
+
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz4fnFO9gybVYfFf8bW9y5pI5aBf7c10CkEM6SOePbSfi1tHIKa35gAbJq" crossorigin="anonymous"></script>
|
234 |
+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-pzjw8f+ua7Kw1TIq0v8Fqk5K9qAqg6O+h1XYThRKnUNnT1Lf0zLtx/W7zQ9r5pB7" crossorigin="anonymous"></script>
|
235 |
+
</body>
|
236 |
+
|
237 |
+
</html>
|
templates/prediction.html
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
|
4 |
+
<head>
|
5 |
+
<meta charset="UTF-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
+
|
8 |
+
<!-- Bootstrap 5 CSS -->
|
9 |
+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEJr+K+GkABh9h3l+mybJfA0bG5gHiE5Q1LO1rHwUtZoZr8JjxfQEC8t09/8U" crossorigin="anonymous">
|
10 |
+
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">
|
11 |
+
|
12 |
+
<title>Premium Amount</title>
|
13 |
+
<style>
|
14 |
+
body {
|
15 |
+
background: linear-gradient(to right, rgba(34, 193, 195, 0.8), rgba(253, 187, 45, 0.8));
|
16 |
+
background-size: cover;
|
17 |
+
font-family: 'Arial', sans-serif;
|
18 |
+
margin: 0;
|
19 |
+
padding: 0;
|
20 |
+
height: 100vh;
|
21 |
+
display: flex;
|
22 |
+
justify-content: center;
|
23 |
+
align-items: center;
|
24 |
+
flex-direction: column;
|
25 |
+
}
|
26 |
+
|
27 |
+
.container {
|
28 |
+
width: 100%;
|
29 |
+
max-width: 800px;
|
30 |
+
background-color: rgba(255, 255, 255, 0.9);
|
31 |
+
border-radius: 15px;
|
32 |
+
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.1);
|
33 |
+
padding: 30px;
|
34 |
+
overflow-y: auto;
|
35 |
+
max-height: 90vh;
|
36 |
+
}
|
37 |
+
|
38 |
+
.card {
|
39 |
+
border-radius: 8px;
|
40 |
+
border: none;
|
41 |
+
}
|
42 |
+
|
43 |
+
.card-body {
|
44 |
+
padding: 20px;
|
45 |
+
}
|
46 |
+
|
47 |
+
.card-header {
|
48 |
+
font-size: 26px;
|
49 |
+
font-weight: 600;
|
50 |
+
text-align: center;
|
51 |
+
color: #fff;
|
52 |
+
background-color: #007bff;
|
53 |
+
border-radius: 8px;
|
54 |
+
padding: 10px 0;
|
55 |
+
}
|
56 |
+
|
57 |
+
h3 {
|
58 |
+
font-size: 24px;
|
59 |
+
font-weight: bold;
|
60 |
+
color: #333;
|
61 |
+
text-align: center;
|
62 |
+
}
|
63 |
+
|
64 |
+
ul {
|
65 |
+
list-style-type: none;
|
66 |
+
padding: 0;
|
67 |
+
}
|
68 |
+
|
69 |
+
ul li {
|
70 |
+
font-size: 16px;
|
71 |
+
color: #555;
|
72 |
+
padding: 8px 0;
|
73 |
+
}
|
74 |
+
|
75 |
+
ul li:nth-child(even) {
|
76 |
+
background-color: #f9f9f9;
|
77 |
+
}
|
78 |
+
|
79 |
+
ul li span {
|
80 |
+
font-weight: 500;
|
81 |
+
color: #007bff;
|
82 |
+
}
|
83 |
+
|
84 |
+
.prediction {
|
85 |
+
font-size: 24px;
|
86 |
+
font-weight: bold;
|
87 |
+
color: #28a745;
|
88 |
+
padding-top: 20px;
|
89 |
+
text-align: center;
|
90 |
+
}
|
91 |
+
|
92 |
+
.card-footer {
|
93 |
+
text-align: center;
|
94 |
+
padding-top: 20px;
|
95 |
+
}
|
96 |
+
|
97 |
+
/* Add abstract background pattern */
|
98 |
+
.abstract-background {
|
99 |
+
position: absolute;
|
100 |
+
top: 0;
|
101 |
+
left: 0;
|
102 |
+
width: 100%;
|
103 |
+
height: 100%;
|
104 |
+
background-image: url('https://www.transparenttextures.com/patterns/asfalt.png');
|
105 |
+
background-repeat: repeat;
|
106 |
+
z-index: -1;
|
107 |
+
}
|
108 |
+
|
109 |
+
</style>
|
110 |
+
</head>
|
111 |
+
|
112 |
+
<body>
|
113 |
+
<!-- Add the abstract background -->
|
114 |
+
<div class="abstract-background"></div>
|
115 |
+
|
116 |
+
<div class="container">
|
117 |
+
<div class="card">
|
118 |
+
<div class="card-header">
|
119 |
+
<h3>Thank You! Here is the information you provided:</h3>
|
120 |
+
</div>
|
121 |
+
<div class="card-body">
|
122 |
+
<ul>
|
123 |
+
<li><span>Age:</span> {{session['age']}}</li>
|
124 |
+
<li><span>Gender:</span> {{session['gender']}}</li>
|
125 |
+
<li><span>Annual income:</span> {{session['annual_income']}}</li>
|
126 |
+
<li><span>Marital status:</span> {{session['marital_status']}}</li>
|
127 |
+
<li><span>Dependents:</span> {{session['dependents']}}</li>
|
128 |
+
<li><span>Education level:</span> {{session['education_level']}}</li>
|
129 |
+
<li><span>Occupation:</span> {{session['occupation_status']}}</li>
|
130 |
+
<li><span>Health score:</span> {{session['health_score']}}</li>
|
131 |
+
<li><span>Location:</span> {{session['location']}}</li>
|
132 |
+
<li><span>Policy type:</span> {{session['policy']}}</li>
|
133 |
+
<li><span>Previous claims:</span> {{session['previous_claims']}}</li>
|
134 |
+
<li><span>Vehicle age:</span> {{session['vehicle_age']}}</li>
|
135 |
+
<li><span>Credit score:</span> {{session['credit_score']}}</li>
|
136 |
+
<li><span>Insurance duration:</span> {{session['insurance_duration']}}</li>
|
137 |
+
<li><span>Customer feedback:</span> {{session['feedback_status']}}</li>
|
138 |
+
<li><span>Smoking status:</span> {{session['smoking_status']}}</li>
|
139 |
+
<li><span>Exercise frequency:</span> {{session['exercise_frequency']}}</li>
|
140 |
+
<li><span>Property type:</span> {{session['property_type']}}</li>
|
141 |
+
<li><span>Year:</span> {{session['year']}}</li>
|
142 |
+
<li><span>Day:</span> {{session['day']}}</li>
|
143 |
+
<li><span>Month:</span> {{session['month']}}</li>
|
144 |
+
<li><span>Month name:</span> {{session['month_name']}}</li>
|
145 |
+
<li><span>Day of week:</span> {{session['day_of_week']}}</li>
|
146 |
+
<li><span>Contract length:</span> {{session['contract_length']}}</li>
|
147 |
+
<li><span>Income per dependent:</span> {{session['income_per_dependent']}}</li>
|
148 |
+
<li><span>Credit score insurance duration:</span> {{session['credit_score_insurance_duration']}}</li>
|
149 |
+
<li><span>Health risk score:</span> {{session['health_risk_score']}}</li>
|
150 |
+
<li><span>Credit health score:</span> {{session['credit_health_score']}}</li>
|
151 |
+
<li><span>Health age interaction:</span> {{session['health_age_interaction']}}</li>
|
152 |
+
</ul>
|
153 |
+
</div>
|
154 |
+
<div class="card-footer">
|
155 |
+
<h3 class="prediction">Insurance premium amount predicted is: {{ '%.2f' | format(prediction) }} dollars</h3>
|
156 |
+
</div>
|
157 |
+
</div>
|
158 |
+
</div>
|
159 |
+
|
160 |
+
<!-- Bootstrap JS and dependencies -->
|
161 |
+
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz4fnFO9gybVYfFf8bW9y5pI5aBf7c10CkEM6SOePbSfi1tHIKa35gAbJq" crossorigin="anonymous"></script>
|
162 |
+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-pzjw8f+ua7Kw1TIq0v8Fqk5K9qAqg6O+h1XYThRKnUNnT1Lf0zLtx/W7zQ9r5pB7" crossorigin="anonymous"></script>
|
163 |
+
</body>
|
164 |
+
|
165 |
+
</html>
|