|
|
|
import streamlit as st |
|
import os |
|
import pickle |
|
import numpy as np |
|
import pandas as pd |
|
from xgboost import XGBClassifier |
|
|
|
|
|
|
|
st.set_page_config(page_title = "Insurance Prediction App", initial_sidebar_state = "auto") |
|
|
|
|
|
st.title("Insurance Claim Prediction with Machine Learning") |
|
|
|
|
|
|
|
@st.cache_resource() |
|
def load_ml_toolkit(relative_path): |
|
""" |
|
This function loads the src/toolkit into this file by taking the relative path to the src/toolkit. |
|
|
|
Args: |
|
relative_path (string, optional): It receives the file path to the ML toolkit for loading. |
|
Returns: |
|
file: It returns the pickle file (which contains the Machine Learning items in this case). |
|
""" |
|
|
|
with open(relative_path, "rb") as file: |
|
loaded_object = pickle.load(file) |
|
return loaded_object |
|
|
|
|
|
|
|
@st.cache_resource() |
|
def load_data(relative_path): |
|
""" |
|
This function is used to load the DataFrame into the current file. |
|
|
|
Args: |
|
relative_path (string): The relative path to the DataFrame to be loaded. |
|
|
|
Returns: |
|
DataFrame: Returns the DataFrame at the path provided. |
|
""" |
|
|
|
dataset = pd.read_csv(relative_path) |
|
return dataset |
|
|
|
|
|
|
|
rpath = r"data/train_data.csv" |
|
df_loaded = load_data(rpath) |
|
|
|
|
|
loaded_toolkit = load_ml_toolkit(r"src/Streamlit_toolkit") |
|
if "results" not in st.session_state: |
|
st.session_state["results"] = [] |
|
|
|
|
|
scaler = loaded_toolkit["scaler"] |
|
model = loaded_toolkit["model"] |
|
encoder = loaded_toolkit["encoder"] |
|
|
|
|
|
model = XGBClassifier() |
|
model.load_model(r"src/xgb_model.json") |
|
|
|
|
|
|
|
header = st.container() |
|
dataset = st.container() |
|
features_and_output = st.container() |
|
|
|
|
|
form = st.form(key="Information", clear_on_submit = True) |
|
|
|
|
|
with header: |
|
header.write("This app is built of a machine learning model to predict the whether or not a building will have an insurance claim over a period based on given variables for which you will make inputs (see the input section below). The model was trained based on the DSN Insurance Prediction dataset.") |
|
header.write("---") |
|
|
|
|
|
st.sidebar.header("Information on Columns") |
|
st.sidebar.markdown(""" |
|
- *Customer Id*: Identification number for the Policy holder |
|
- *YearOfObservation*: year of observation for the insured policy |
|
- *Insured_Period*: duration of insurance policy in Olusola Insurance. (Ex: Full year insurance, Policy Duration = 1; 6 months = 0.5 |
|
- *Residential*: is the building a residential building or not |
|
- *Building_Painted*: is the building painted or not (N-Painted, V-Not Painted) |
|
- *Building_Fenced*: is the building fence or not (N-Fenced, V-Not Fenced) |
|
- *Garden*: building has garden or not (V-has garden; O-no garden) |
|
- *Settlement*: Area where the building is located. (R- rural area; U- urban area) |
|
- *Building Dimension*: Size of the insured building in m2 |
|
- *Building_Type*: The type of building (Type 1, 2, 3, 4) |
|
- *Date_of_Occupancy*: date building was first occupied |
|
- *NumberOfWindows*: number of windows in the building |
|
- *Geo Code*: Geographical Code of the Insured building |
|
- *Claim*: target variable. (0: no claim, 1: at least one claim over insured period). |
|
""") |
|
|
|
|
|
with dataset: |
|
if dataset.checkbox("Preview the dataset"): |
|
dataset.write(df_loaded.head()) |
|
dataset.write("Take a look at the sidebar for more information on the columns") |
|
dataset.write("---") |
|
|
|
|
|
expected_inputs = ["YearOfObservation", "Insured_Period", "Residential", "Building_Painted", "Building_Fenced", "Garden", "Settlement", "Building Dimension", "Building_Type", "Date_of_Occupancy", "NumberOfWindows"] |
|
|
|
|
|
categoricals = ["Building_Painted", "Building_Fenced", "Garden", "Settlement"] |
|
|
|
|
|
cols_to_scale = ["YearOfObservation", "Insured_Period", "Residential", "Building Dimension", "Building_Type", "Date_of_Occupancy", "NumberOfWindows"] |
|
|
|
|
|
|
|
with features_and_output: |
|
features_and_output.subheader("Inputs") |
|
features_and_output.write("This section captures the inputs to be used in predictions...") |
|
|
|
left_col, right_col = features_and_output.columns(2) |
|
|
|
|
|
with form: |
|
left_col.markdown("**Inputs Set 1:") |
|
YearOfObservation = left_col.number_input("Select a year:", min_value = 2012, step = 1) |
|
Insured_Period = left_col.selectbox("Insured Period (Full year or half-year):", options = [0.5,1]) |
|
Residential = left_col.radio("Is the building residential (1) or not (0):", options= [0, 1], horizontal = True) |
|
Building_Painted = left_col.selectbox("Is the building painted (N) or not(V):", options = ["N", "V"]) |
|
Building_Fenced = left_col.selectbox("Is the building fenced (N) or not(V):", options = ["N", "V"]) |
|
|
|
right_col.markdown("**Inputs Set 2**") |
|
Garden = right_col.radio("Does the building have a garden (V) or not (O):", options = ["V", "O"], horizontal = True) |
|
Settlement = right_col.radio("Is the building situated in a rural (R) or urban (U) area?:", options = ["R", "U"], horizontal = True) |
|
Building_Dimension = right_col.number_input("What is the size of the insured building (m2)?", min_value= 1, value= 1) |
|
Building_Type = right_col.selectbox("What type of building is it?", options = [1,2,3,4]) |
|
Date_of_Occupancy = right_col.number_input("On what date was the building first occupied?", min_value= 1545, value= 1970) |
|
NumberOfWindows = right_col.select_slider("How many windows does the building have?", options= range(1,11)) |
|
|
|
|
|
submitted = form.form_submit_button(label= "Submit") |
|
|
|
|
|
if submitted: |
|
with features_and_output: |
|
|
|
input_dict = { |
|
"YearOfObservation": [YearOfObservation], |
|
"Insured_Period": [Insured_Period], |
|
"Residential": [Residential], |
|
"Building_Painted": [Building_Painted], |
|
"Building_Fenced": [Building_Fenced], |
|
"Garden": [Garden], |
|
"Settlement": [Settlement], |
|
"Building Dimension": [Building_Dimension], |
|
"Building_Type": [Building_Type], |
|
"Date_of_Occupancy": [Date_of_Occupancy], |
|
"NumberOfWindows": [NumberOfWindows] |
|
} |
|
|
|
|
|
input_data = pd.DataFrame.from_dict(input_dict) |
|
|
|
|
|
encoded_test_categoricals = encoder.transform(input_data[categoricals]) |
|
encoded_test_categoricals = pd.DataFrame(encoded_test_categoricals, columns = encoder.get_feature_names_out().tolist()) |
|
|
|
|
|
input_data = input_data.join(encoded_test_categoricals) |
|
input_data.drop(columns= categoricals, inplace= True) |
|
|
|
|
|
input_data[cols_to_scale] = scaler.transform(input_data[cols_to_scale]) |
|
|
|
|
|
model_output = model.predict(input_data) |
|
input_data["Prediction"] = model_output |
|
|
|
if model_output[0] == 0: |
|
display = "The building does not have a claim over the insured period." |
|
else: |
|
display = "The building has a claim over the insured period." |
|
|
|
st.session_state["results"].append(input_data) |
|
result = pd.concat(st.session_state["results"]) |
|
|
|
|
|
st.success(f"**Prediction**: {display}") |
|
|
|
|
|
previous_output = st.expander("**Review previous predictions**") |
|
previous_output.dataframe(result, use_container_width= True) |
|
|