other files
Browse files- app.py +179 -0
- requirements.txt +8 -0
app.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import pickle
|
| 3 |
+
from sklearn.preprocessing import StandardScaler
|
| 4 |
+
import random
|
| 5 |
+
|
| 6 |
+
# Title of the app
|
| 7 |
+
st.title('Credit Default Risk Prediction')
|
| 8 |
+
|
| 9 |
+
# Updated list of column names
|
| 10 |
+
fin_cols = ['MONTHS_BALANCE_mean', 'CNT_INSTALMENT_mean', 'CNT_INSTALMENT_FUTURE_mean', 'SK_DPD_mean', 'SK_DPD_DEF_mean',
|
| 11 |
+
'DAYS_CREDIT_MEAN', 'CREDIT_DAY_OVERDUE_MEAN', 'AMT_CREDIT_MAX_OVERDUE_MEAN', 'AMT_CREDIT_SUM_MEAN',
|
| 12 |
+
'AMT_CREDIT_SUM_DEBT_MEAN', 'AMT_CREDIT_SUM_OVERDUE_MEAN', 'DAYS_CREDIT_ENDDATE_MEAN',
|
| 13 |
+
'DAYS_ENDDATE_FACT_MEAN', 'AMT_CREDIT_SUM_LIMIT_MEAN', 'CREDIT_LEFT', 'AMT_ANNUITY_mean', 'AMT_APPLICATION_mean',
|
| 14 |
+
'AMT_CREDIT_mean', 'AMT_DOWN_PAYMENT_mean', 'AMT_GOODS_PRICE_mean', 'HOUR_APPR_PROCESS_START_mean',
|
| 15 |
+
'RATE_DOWN_PAYMENT_mean', 'SELLERPLACE_AREA_mean', 'amt_income_total', 'amt_credit', 'amt_goods_price',
|
| 16 |
+
'days_birth', 'days_employed', 'days_registration', 'days_id_publish', 'hour_appr_process_start',
|
| 17 |
+
'days_last_phone_change', 'amt_req_credit_bureau_year', 'NUM_LATE_PAYMENTS_MEAN', 'DIFF_AMOUNT_MORE_OR_LESS_MEAN',
|
| 18 |
+
'def_60_cnt_social_circle (0-5)', 'name_contract_type(cash_loans/revolving_loans)',
|
| 19 |
+
'organization_type(check document to know your organisation type in our github page)',
|
| 20 |
+
'loan_purpose(Business development/Medicine/Other/celebration/Cancelled/Unused offer/Unknown)',
|
| 21 |
+
'payment_type(Cashless from the account of the employer/Non-cash from your account/Unknown)',
|
| 22 |
+
'channel_type(AP+(Cash loan)/Contact center/Unknown)']
|
| 23 |
+
|
| 24 |
+
num_cols = ['MONTHS_BALANCE_mean', 'CNT_INSTALMENT_mean', 'CNT_INSTALMENT_FUTURE_mean', 'SK_DPD_mean', 'SK_DPD_DEF_mean',
|
| 25 |
+
'DAYS_CREDIT_MEAN', 'CREDIT_DAY_OVERDUE_MEAN', 'AMT_CREDIT_MAX_OVERDUE_MEAN', 'AMT_CREDIT_SUM_MEAN',
|
| 26 |
+
'AMT_CREDIT_SUM_DEBT_MEAN', 'AMT_CREDIT_SUM_OVERDUE_MEAN', 'DAYS_CREDIT_ENDDATE_MEAN',
|
| 27 |
+
'DAYS_ENDDATE_FACT_MEAN', 'AMT_CREDIT_SUM_LIMIT_MEAN', 'CREDIT_LEFT', 'AMT_ANNUITY_mean', 'AMT_APPLICATION_mean',
|
| 28 |
+
'AMT_CREDIT_mean', 'AMT_DOWN_PAYMENT_mean', 'AMT_GOODS_PRICE_mean', 'HOUR_APPR_PROCESS_START_mean',
|
| 29 |
+
'RATE_DOWN_PAYMENT_mean', 'SELLERPLACE_AREA_mean', 'amt_income_total', 'amt_credit', 'amt_goods_price',
|
| 30 |
+
'days_birth', 'days_employed', 'days_registration', 'days_id_publish', 'hour_appr_process_start',
|
| 31 |
+
'days_last_phone_change', 'amt_req_credit_bureau_year', 'NUM_LATE_PAYMENTS_MEAN', 'DIFF_AMOUNT_MORE_OR_LESS_MEAN']
|
| 32 |
+
|
| 33 |
+
cat_cols = ['def_60_cnt_social_circle (0-5)', 'name_contract_type(cash_loans/revolving_loans)',
|
| 34 |
+
'organization_type(check document to know your organisation type in our github page)',
|
| 35 |
+
'loan_purpose(Business development/Medicine/Other/celebration/Cancelled/Unused offer/Unknown)',
|
| 36 |
+
'payment_type(Cashless from the account of the employer/Non-cash from your account/Unknown)',
|
| 37 |
+
'channel_type(AP+(Cash loan)/Contact center/Unknown)']
|
| 38 |
+
|
| 39 |
+
# Encoding dictionaries
|
| 40 |
+
loan_purpose_dict = {'Business development': 0, 'Medicine': 1, 'Other': 2, 'celebration': 3, 'Cancelled': 4, 'Unused offer': 5, 'Unknown': 6}
|
| 41 |
+
payment_type_dict = {'Cashless from the account of the employer': 0, 'Non-cash from your account': 1, 'Unknown': 3}
|
| 42 |
+
channel_type_dict = {'AP+ (Cash loan)': 0, 'Contact center': 1, 'Unknown': 2}
|
| 43 |
+
name_contract_type_dict = {'Cash loans': 0, 'revolving loans': 1}
|
| 44 |
+
|
| 45 |
+
# Initialize session state for random value filling
|
| 46 |
+
if 'random_values_filled' not in st.session_state:
|
| 47 |
+
st.session_state.random_values_filled = False
|
| 48 |
+
|
| 49 |
+
# Collecting user inputs
|
| 50 |
+
inputs = {}
|
| 51 |
+
for i in range(len(fin_cols)):
|
| 52 |
+
if st.session_state.random_values_filled:
|
| 53 |
+
inputs[f"input_{i}"] = st.text_input(f'Enter {fin_cols[i]}', value=st.session_state.get(f"input_{i}", ""))
|
| 54 |
+
else:
|
| 55 |
+
inputs[f"input_{i}"] = st.text_input(f'Enter {fin_cols[i]}')
|
| 56 |
+
|
| 57 |
+
# Function to fill random values
|
| 58 |
+
def fill_random_values():
|
| 59 |
+
st.session_state.random_values_filled = True
|
| 60 |
+
for i in range(len(fin_cols)):
|
| 61 |
+
if fin_cols[i] in num_cols:
|
| 62 |
+
st.session_state[f"input_{i}"] = str(random.uniform(0, 100)) # Random float value for numerical columns
|
| 63 |
+
elif 'def_60_cnt_social_circle' in fin_cols[i]:
|
| 64 |
+
st.session_state[f"input_{i}"] = str(random.randint(0, 5))
|
| 65 |
+
elif 'name_contract_type' in fin_cols[i]:
|
| 66 |
+
st.session_state[f"input_{i}"] = str(random.randint(0, 1))
|
| 67 |
+
elif 'organization_type' in fin_cols[i]:
|
| 68 |
+
st.session_state[f"input_{i}"] = str(random.randint(0, 57))
|
| 69 |
+
elif 'loan_purpose' in fin_cols[i]:
|
| 70 |
+
st.session_state[f"input_{i}"] = str(random.randint(0, 6))
|
| 71 |
+
elif 'payment_type' in fin_cols[i]:
|
| 72 |
+
st.session_state[f"input_{i}"] = str(random.randint(0, 3))
|
| 73 |
+
elif 'channel_type' in fin_cols[i]:
|
| 74 |
+
st.session_state[f"input_{i}"] = str(random.randint(0, 3))
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
# Repopulating the fields if they were randomly filled
|
| 79 |
+
if st.session_state.random_values_filled:
|
| 80 |
+
for i in range(len(fin_cols)):
|
| 81 |
+
inputs[f"input_{i}"] = st.text_input(f'Enter {fin_cols[i]}', value=st.session_state.get(f"input_{i}", ""))
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
# Button to estimate
|
| 86 |
+
if st.button('Estimate'):
|
| 87 |
+
# Encoding categorical variables
|
| 88 |
+
for i in range(len(fin_cols)):
|
| 89 |
+
if 'loan_purpose' in fin_cols[i]:
|
| 90 |
+
inputs[f"input_{i}"] = loan_purpose_dict.get(inputs[f"input_{i}"], 6) # Default to 6 ('Unknown')
|
| 91 |
+
elif 'payment_type' in fin_cols[i]:
|
| 92 |
+
inputs[f"input_{i}"] = payment_type_dict.get(inputs[f"input_{i}"], 3) # Default to 3 ('Unknown')
|
| 93 |
+
elif 'channel_type' in fin_cols[i]:
|
| 94 |
+
inputs[f"input_{i}"] = channel_type_dict.get(inputs[f"input_{i}"], 2) # Default to 2 ('Unknown')
|
| 95 |
+
elif 'name_contract_type' in fin_cols[i]:
|
| 96 |
+
inputs[f"input_{i}"] = name_contract_type_dict.get(inputs[f"input_{i}"], 1) # Default to 1
|
| 97 |
+
elif 'def_60_cnt_social_circle' in fin_cols[i]:
|
| 98 |
+
try:
|
| 99 |
+
inputs[f"input_{i}"] = int(inputs[f"input_{i}"])
|
| 100 |
+
except ValueError:
|
| 101 |
+
inputs[f"input_{i}"] = 0 # Default value
|
| 102 |
+
elif 'organization_type' in fin_cols[i]:
|
| 103 |
+
try:
|
| 104 |
+
inputs[f"input_{i}"] = int(inputs[f"input_{i}"])
|
| 105 |
+
except ValueError:
|
| 106 |
+
inputs[f"input_{i}"] = 0 # Default value
|
| 107 |
+
|
| 108 |
+
# Collecting and validating numerical data
|
| 109 |
+
num_data = []
|
| 110 |
+
for i in range(len(fin_cols)):
|
| 111 |
+
if fin_cols[i] in num_cols:
|
| 112 |
+
value = inputs[f"input_{i}"]
|
| 113 |
+
if value != '':
|
| 114 |
+
try:
|
| 115 |
+
num_data.append(float(value))
|
| 116 |
+
except ValueError:
|
| 117 |
+
num_data.append(0.0) # Default value for invalid inputs
|
| 118 |
+
else:
|
| 119 |
+
num_data.append(0.0) # Default value for empty input
|
| 120 |
+
|
| 121 |
+
# Collecting encoded categorical data
|
| 122 |
+
cat_data = []
|
| 123 |
+
for i in range(len(fin_cols)):
|
| 124 |
+
if fin_cols[i] in cat_cols:
|
| 125 |
+
value = inputs[f"input_{i}"]
|
| 126 |
+
# Ensure the value is numerical
|
| 127 |
+
if value != '':
|
| 128 |
+
try:
|
| 129 |
+
cat_data.append(float(value))
|
| 130 |
+
except ValueError:
|
| 131 |
+
cat_data.append(0.0) # Default value
|
| 132 |
+
else:
|
| 133 |
+
cat_data.append(0.0) # Default value
|
| 134 |
+
|
| 135 |
+
# Standardizing numerical data
|
| 136 |
+
ss = StandardScaler()
|
| 137 |
+
num_tra = ss.fit_transform([num_data])
|
| 138 |
+
|
| 139 |
+
# Merging num_tra and cat_data in the correct order of fin_cols
|
| 140 |
+
final_data = []
|
| 141 |
+
num_idx = 0
|
| 142 |
+
cat_idx = 0
|
| 143 |
+
for col in fin_cols:
|
| 144 |
+
if col in num_cols:
|
| 145 |
+
final_data.append(num_tra[0][num_idx])
|
| 146 |
+
num_idx += 1
|
| 147 |
+
else:
|
| 148 |
+
final_data.append(cat_data[cat_idx])
|
| 149 |
+
cat_idx += 1
|
| 150 |
+
|
| 151 |
+
# Convert final_data to a numpy array with a numeric data type
|
| 152 |
+
import numpy as np
|
| 153 |
+
final_data = np.array(final_data, dtype=np.float32)
|
| 154 |
+
|
| 155 |
+
# Verify data types
|
| 156 |
+
# st.write("Final data types:", final_data.dtype)
|
| 157 |
+
# st.write("Final data:", final_data)
|
| 158 |
+
|
| 159 |
+
# Loading the model from the pickle file
|
| 160 |
+
model = pickle.load(open('stacking_model_dec.pkl', 'rb'))
|
| 161 |
+
|
| 162 |
+
# Making a prediction
|
| 163 |
+
# Making a prediction
|
| 164 |
+
try:
|
| 165 |
+
prediction = model.predict([final_data])
|
| 166 |
+
|
| 167 |
+
# Displaying more descriptive output based on the prediction value
|
| 168 |
+
if prediction[0] == 0:
|
| 169 |
+
st.success("The customer will **NOT** default on the loan.")
|
| 170 |
+
elif prediction[0] == 1:
|
| 171 |
+
st.warning("The customer **WILL** default on the loan.")
|
| 172 |
+
else:
|
| 173 |
+
st.error("Unexpected prediction value.")
|
| 174 |
+
|
| 175 |
+
except Exception as e:
|
| 176 |
+
st.error(f"Error during prediction: {e}")
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
streamlit
|
| 2 |
+
scikit-learn
|
| 3 |
+
pandas
|
| 4 |
+
numpy
|
| 5 |
+
matplotlib
|
| 6 |
+
seaborn
|
| 7 |
+
scipy
|
| 8 |
+
xgboost
|