thanthamky commited on
Commit
0831f66
1 Parent(s): 40a9784

Upload 13 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.12-slim
3
+
4
+ # Set the working directory in the container to /app
5
+ WORKDIR /app
6
+
7
+ # Copy the current directory contents into the container at /app
8
+ COPY . /app
9
+
10
+ # Install any needed packages specified in requirements.txt
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # Make port 5000 available to the world outside this container
14
+ EXPOSE 5000
15
+
16
+ # Define environment variable
17
+ ENV FLASK_APP=src/app.py
18
+ ENV FLASK_RUN_HOST=0.0.0.0
19
+ ENV FLASK_RUN_PORT=7680
20
+
21
+ # Run flaskapp.py when the container launches
22
+ CMD ["flask", "run", "--host=0.0.0.0", "--port=7680"]
23
+
models/best_model.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a3e20603d519b852f2368758445786c3b0e999dae72d19cd4e18ae5df464d2a6
3
+ size 2480120
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # python 3.12
2
+ flask==3.0.3
3
+ pandas==2.2.2
4
+ matplotlib==3.9.0
5
+ numpy==1.26.4
6
+ scikit-learn==1.5.0
7
+ seaborn==0.13.2
8
+ xgboost==2.0.3
9
+ imbalanced-learn==0.12.3
10
+ category-encoders==2.6.3
src/__pycache__/app.cpython-311.pyc ADDED
Binary file (2.23 kB). View file
 
src/__pycache__/app.cpython-312.pyc ADDED
Binary file (1.93 kB). View file
 
src/__pycache__/utils.cpython-311.pyc ADDED
Binary file (2 kB). View file
 
src/__pycache__/utils.cpython-312.pyc ADDED
Binary file (1.75 kB). View file
 
src/app.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pickle
2
+ from pathlib import Path
3
+
4
+ import pandas as pd
5
+ from flask import Flask, render_template, request
6
+
7
+ import utils
8
+
9
+
10
+ project_dir = Path(__file__).resolve().parents[1]
11
+ app = Flask(__name__)
12
+
13
+
14
+ with open(project_dir / "models" / "best_model.pickle", "rb") as f:
15
+ model = pickle.load(f)
16
+
17
+
18
+ @app.route("/")
19
+ def home():
20
+ return render_template("index.html")
21
+
22
+
23
+ @app.route("/predict", methods=["POST"])
24
+ def predict():
25
+ form_data = request.form.to_dict()
26
+ preprocessed_data = utils.preprocess(form_data)
27
+
28
+ print(pd.DataFrame(preprocessed_data, index=[0]))
29
+ pd.DataFrame(preprocessed_data, index=[0]).to_csv('./sample.csv')
30
+ probability = model.predict_proba(pd.DataFrame(preprocessed_data, index=[0]))
31
+ return render_template("result.html", probability=f"{probability[0, 1] * 100:.2f}")
32
+
33
+ #if __name__ == "__main__":
34
+ # app.run(host="0.0.0.0", port=8080)
src/sample.csv ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ ,age_of_driver,annual_income,past_num_of_claims,safty_rating,gender,marital_status,living_status,high_education_ind,address_change_ind,claim_est_payout,liab_prct,witness_present_ind,policy_report_filed_ind,accident_site,channel,age_of_vehicle,vehicle_price,vehicle_weight,vehicle_category,latitude,longitude
2
+ 0,39,36633,0,73,F,1,Own,1,1,5196,25,1,1,Highway,Broker,8,24360,26633,Compact,41.5,-94.52
src/templates/base.html ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <!-- Required meta tags -->
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7
+
8
+ <!-- Bootstrap CSS -->
9
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
10
+
11
+ <title>Auto Insurance Fraud Prediction</title>
12
+ </head>
13
+ <body class="bg-light">
14
+ <div class="container">
15
+ <div class="py-5 text-center">
16
+ <h2>Auto Insurance Fraud Prediction</h2>
17
+ </div>
18
+
19
+ <div class="row justify-content-center">
20
+ {% block content %}{% endblock %}
21
+ </div>
22
+ </div>
23
+
24
+ <footer class="my-5 pt-5 text-muted text-center text-small">
25
+ <p class="mb-1">&copy; 2021 King Yiu Suen</p>
26
+ <ul class="list-inline">
27
+ <li class="list-inline-item"><a href="https://github.com/kingyiusuen/travelers-insurance-fraud">Github</a></li>
28
+ </ul>
29
+ </footer>
30
+
31
+ <!-- Optional JavaScript -->
32
+ <!-- jQuery first, then Popper.js, then Bootstrap JS -->
33
+ <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
34
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
35
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
36
+ </body>
37
+ </html>
src/templates/index.html ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <form class="needs-validation" action="{{ url_for('predict')}}" method="post">
5
+ <h4 class="mb-3">Driver</h4>
6
+ <div class="row">
7
+ <div class="col-md-4 mb-3">
8
+ <label for="age-of-driver">Age</label>
9
+ <input type="text" class="form-control" name="age_of_driver" placeholder="" value="39" required>
10
+ </div>
11
+ <div class="col-md-4 mb-3">
12
+ <label for="zip-code">Zip code</label>
13
+ <input type="text" class="form-control" name="zip_code" placeholder="" value="50048" required>
14
+ </div>
15
+ <div class="col-md-4 mb-3">
16
+ <label for="annual-income">Annual income</label>
17
+ <input type="text" class="form-control" name="annual_income" placeholder="" value="36633" required>
18
+ </div>
19
+ </div>
20
+ <div class="row">
21
+ <div class="col-md-4 mb-3">
22
+ <label for="past-num-of-claims">Number of claims in past 5 years</label>
23
+ <input type="text" class="form-control" name="past_num_of_claims" placeholder="" value="0" required>
24
+ </div>
25
+ <div class="col-md-8 mb-3">
26
+ <label for="safty-rating">Safety rating index</label>
27
+ <input type="text" class="form-control" name="safty_rating" placeholder="" value="73" required>
28
+ <small class="text-muted">A score to measure driver's safety level or possibility of having an accident (0 - 100)</small>
29
+ </div>
30
+ </div>
31
+ <div class="row">
32
+ <div class="col-md-4 my-3">
33
+ <label for="gender">Gender</label>
34
+ <select class="custom-select d-block w-100" name="gender" required>
35
+ <option>Female</option>
36
+ <option>Male</option>
37
+ </select>
38
+ </div>
39
+ <div class="col-md-4 my-3">
40
+ <label for="marital-status">Are you been married?</label>
41
+ <select class="custom-select d-block w-100" name="marital_status" required>
42
+ <option>Yes</option>
43
+ <option>No</option>
44
+ </select>
45
+ </div>
46
+ <div class="col-md-4 my-3">
47
+ <label for="living-status">Living status</label>
48
+ <select class="custom-select d-block w-100" name="living_status" required>
49
+ <option>Own</option>
50
+ <option>Rent</option>
51
+ </select>
52
+ </div>
53
+ </div>
54
+ <div class="row">
55
+ <div class="col-md-4 my-3">
56
+ <label for="high-education-ind">Do you have a college degree?</label>
57
+ <select class="custom-select d-block w-100" name="high_education_ind" required>
58
+ <option>Yes</option>
59
+ <option>No</option>
60
+ </select>
61
+ </div>
62
+ <div class="col-md-8 my-3">
63
+ <label for="address-change-ind">Did you change your living address in past 1 year?</label>
64
+ <select class="custom-select d-block w-100" name="address_change_ind" required>
65
+ <option>Yes</option>
66
+ <option>No</option>
67
+ </select>
68
+ </div>
69
+ </div>
70
+ <hr class="mb-4">
71
+ <h4 class="mb-3">Claim</h4>
72
+ <div class="row">
73
+ <div class="col-md-4 mb-3">
74
+ <label for="claim-est-payout">Estimated claim payout</label>
75
+ <input type="text" class="form-control" name="claim_est_payout" placeholder="" value="5196" required>
76
+ </div>
77
+ <div class="col-md-4 mb-3">
78
+ <label for="liab-prct">Liability percentage of the claim</label>
79
+ <input type="text" class="form-control" name="liab_prct" placeholder="" value="25" required>
80
+ </div>
81
+ </div>
82
+ <div class="row">
83
+ <div class="col-md-4 my-3">
84
+ <label for="witness-present-ind">Was a witness present?</label>
85
+ <select class="custom-select d-block w-100" name="witness_present_ind" required>
86
+ <option>Yes</option>
87
+ <option>No</option>
88
+ </select>
89
+ </div>
90
+ <div class="col-md-8 my-3">
91
+ <label for="policy-report-filed-ind">Did a third party request policy report after the claim?</label>
92
+ <select class="custom-select d-block w-100" name="policy_report_filed_ind" required>
93
+ <option>Yes</option>
94
+ <option>No</option>
95
+ </select>
96
+ <small class="text-muted">The third party could be attorney, provider or police department, etc</small>
97
+ </div>
98
+ </div>
99
+ <div class="row">
100
+ <div class="col-md-4 mb-3">
101
+ <label for="accident-site">Accident location</label>
102
+ <select class="custom-select d-block w-100" name="accident_site" required>
103
+ <option>Highway</option>
104
+ <option>Local</option>
105
+ <option>Parking Lot</option>
106
+ </select>
107
+ </div>
108
+ <div class="col-md-4 mb-3">
109
+ <label for="channel">Channel of policy purchasing</label>
110
+ <select class="custom-select d-block w-100" name="channel" required>
111
+ <option>Broker</option>
112
+ <option>Online</option>
113
+ <option>Phone</option>
114
+ </select>
115
+ </div>
116
+ </div>
117
+ <hr class="mb-4">
118
+ <h4 class="mb-3">Vehicle</h4>
119
+ <div class="row">
120
+ <div class="col-md-4 mb-3">
121
+ <label for="age-of-vehicle">Age</label>
122
+ <input type="text" class="form-control" name="age_of_vehicle" placeholder="" value="8" required>
123
+ </div>
124
+ <div class="col-md-4 mb-3">
125
+ <label for="vehicle-price">Price</label>
126
+ <input type="text" class="form-control" name="vehicle_price" placeholder="" value="24360" required>
127
+ </div>
128
+ <div class="col-md-4 mb-3">
129
+ <label for="vehicle-weight">Weight</label>
130
+ <input type="text" class="form-control" name="vehicle_weight" placeholder="" value="26633" required>
131
+ </div>
132
+ </div>
133
+ <div class="row">
134
+ <div class="col-md-4 mb-3">
135
+ <label for="vehicle-category">Category</label>
136
+ <select class="custom-select d-block w-100" name="vehicle_category" required>
137
+ <option>Compact</option>
138
+ <option>Medium</option>
139
+ <option>Large</option>
140
+ </select>
141
+ </div>
142
+ </div>
143
+ <hr class="mb-4">
144
+ <div class="row justify-content-center">
145
+ <button class="btn btn-primary btn-lg" type="submit">Submit</button>
146
+ </div>
147
+ </form>
148
+ {% endblock %}
src/templates/result.html ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div class="row justify-content-center">
5
+ <div class="col-md-8"></div>
6
+ <p>The probability that this insurance claim is fraudulent is <span class="font-weight-bold">{{ probability }}%</spanclass>.</p>
7
+ </div>
8
+ </div>
9
+ <div class="row justify-content-center py-5">
10
+ <a class="btn btn-primary btn-lg" href="javascript:history.back();" role="button">Back</a>
11
+ </div>
12
+ {% endblock %}
src/utils.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ from typing import Any, Dict
3
+
4
+ import pandas as pd
5
+
6
+
7
+ project_dir = Path(__file__).resolve().parents[1]
8
+
9
+
10
+ zip_code_database = pd.read_csv(project_dir / "data" / "external" / "zip_code_database.csv")
11
+ latitude_and_longitude_lookup = {
12
+ row.zip: (row.latitude, row.longitude) for row in zip_code_database.itertuples()
13
+ }
14
+
15
+
16
+ def preprocess(data: Dict[str, Any]) -> Dict[str, Any]:
17
+ data["gender"] = "M" if data["gender"] == "Male" else "F"
18
+
19
+ zip_code = int(data.pop("zip_code"))
20
+ data["latitude"], data["longitude"] = latitude_and_longitude_lookup[zip_code]
21
+
22
+ for feature in [
23
+ "annual_income",
24
+ "past_num_of_claims",
25
+ "safty_rating",
26
+ "age_of_driver",
27
+ "claim_est_payout",
28
+ "liab_prct",
29
+ "age_of_vehicle",
30
+ "vehicle_price",
31
+ "vehicle_weight",
32
+ ]:
33
+ data[feature] = int(data[feature])
34
+
35
+ for feature in [
36
+ "marital_status",
37
+ "high_education_ind",
38
+ "address_change_ind",
39
+ "witness_present_ind",
40
+ "policy_report_filed_ind",
41
+ ]:
42
+ data[feature] = 1 if data[feature] == "Yes" else 0
43
+ return data