Ade1ola commited on
Commit
90b0598
·
verified ·
1 Parent(s): 11d8e1e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +206 -0
app.py ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import joblib
5
+ import os
6
+
7
+ # Load the saved model pipeline
8
+ model_path = 'credit_risk_assessment_model.pkl'
9
+ if os.path.exists(model_path):
10
+ model = joblib.load(model_path)
11
+ print(f"✅ Model loaded successfully from {model_path}")
12
+ else:
13
+ print(f"⚠️ Model file not found at {model_path}. Upload it to this Space.")
14
+ model = None
15
+
16
+ # ---- HELPER FUNCTIONS ----
17
+ def get_age_group(age):
18
+ if age < 30: return '20-30'
19
+ elif age < 40: return '30-40'
20
+ elif age < 50: return '40-50'
21
+ elif age < 60: return '50-60'
22
+ elif age < 70: return '60-70'
23
+ else: return '70+'
24
+
25
+ def get_credit_amount_group(amount):
26
+ if amount < 2000: return 'Low'
27
+ elif amount < 5000: return 'Medium'
28
+ elif amount < 10000: return 'High'
29
+ else: return 'Very High'
30
+
31
+ def get_duration_group(duration):
32
+ if duration <= 12: return 'Short'
33
+ elif duration <= 36: return 'Medium'
34
+ else: return 'Long'
35
+
36
+ def get_employment_stability(emp):
37
+ return {
38
+ 'A71': 'Unstable', 'A72': 'Unstable', 'A73': 'Moderate',
39
+ 'A74': 'Stable', 'A75': 'Very Stable'
40
+ }.get(emp, 'Moderate')
41
+
42
+ def get_savings_status(savings):
43
+ return {
44
+ 'A61': 'None/Low', 'A62': 'Moderate', 'A63': 'Moderate',
45
+ 'A64': 'High', 'A65': 'None/Low'
46
+ }.get(savings, 'None/Low')
47
+
48
+ def get_credit_history_simple(history):
49
+ return {
50
+ 'A30': 'Poor', 'A31': 'Good', 'A32': 'Good',
51
+ 'A33': 'Fair', 'A34': 'Poor'
52
+ }.get(history, 'Fair')
53
+
54
+ def calculate_risk_flags(age, credit_amount, duration, checking_account):
55
+ return {
56
+ 'young_high_credit_flag': int(age < 30 and credit_amount > 5000),
57
+ 'high_exposure_flag': int(credit_amount > 7500 and duration > 24),
58
+ 'critical_high_amount_flag': int(credit_amount > 10000),
59
+ 'no_checking_high_credit_flag': int(checking_account == 'A14' and credit_amount > 5000),
60
+ 'checking_risk': int(checking_account in ['A13', 'A14'])
61
+ }
62
+
63
+ def calculate_additional_risk_flags(credit_history, savings_account):
64
+ history_risk = int(credit_history in ['A30', 'A34'])
65
+ savings_risk = int(savings_account in ['A61', 'A65'])
66
+ combined_account_risk = history_risk + savings_risk
67
+ return {
68
+ 'history_risk': history_risk,
69
+ 'savings_risk': savings_risk,
70
+ 'combined_account_risk': combined_account_risk
71
+ }
72
+
73
+ # ---- PREDICTION WRAPPER ----
74
+ def predict_credit_risk(checking_account, duration, credit_history, purpose, credit_amount, savings_account, employment_since, installment_rate, personal_status_sex, other_debtors, present_residence, property, age, other_installment_plans, housing, number_credits, job, people_liable, telephone, foreign_worker):
75
+ # If model isn't loaded, show error
76
+ if model is None:
77
+ return """
78
+ <div style='padding: 1rem; border-radius: 0.5rem; background-color: #f44336; color: white;'>
79
+ <h2>Error: Model not loaded</h2>
80
+ <p>The credit risk model has not been loaded. Please check the server logs.</p>
81
+ </div>
82
+ """
83
+
84
+ try:
85
+ # Calculate derived features
86
+ age_group = get_age_group(age)
87
+ credit_amount_group = get_credit_amount_group(credit_amount)
88
+ duration_group = get_duration_group(duration)
89
+ employment_stability = get_employment_stability(employment_since)
90
+ savings_status = get_savings_status(savings_account)
91
+ credit_history_simple = get_credit_history_simple(credit_history)
92
+ credit_per_month = credit_amount / duration if duration > 0 else 0
93
+ age_to_credit_ratio = credit_amount / age if age > 0 else 0
94
+ debt_burden = credit_per_month * 100 / 2000
95
+ credit_to_duration_ratio = credit_amount / duration if duration > 0 else 0
96
+
97
+ # Calculate risk flags
98
+ risk_flags = calculate_risk_flags(age, credit_amount, duration, checking_account)
99
+ additional_flags = calculate_additional_risk_flags(credit_history, savings_account)
100
+
101
+ # Create input data dictionary with all features
102
+ input_data = {
103
+ 'index': 0, # Add index column to fix the error
104
+ 'checking_account': checking_account,
105
+ 'duration': duration,
106
+ 'credit_history': credit_history,
107
+ 'purpose': purpose,
108
+ 'credit_amount': credit_amount,
109
+ 'savings_account': savings_account,
110
+ 'employment_since': employment_since,
111
+ 'installment_rate': installment_rate,
112
+ 'personal_status_sex': personal_status_sex,
113
+ 'other_debtors': other_debtors,
114
+ 'present_residence': present_residence,
115
+ 'property': property,
116
+ 'age': age,
117
+ 'other_installment_plans': other_installment_plans,
118
+ 'housing': housing,
119
+ 'number_credits': number_credits,
120
+ 'job': job,
121
+ 'people_liable': people_liable,
122
+ 'telephone': telephone,
123
+ 'foreign_worker': foreign_worker,
124
+ 'age_group': age_group,
125
+ 'credit_amount_group': credit_amount_group,
126
+ 'duration_group': duration_group,
127
+ 'credit_per_month': credit_per_month,
128
+ 'employment_stability': employment_stability,
129
+ 'savings_status': savings_status,
130
+ 'credit_history_simple': credit_history_simple,
131
+ 'age_to_credit_ratio': age_to_credit_ratio,
132
+ 'debt_burden': debt_burden,
133
+ 'credit_to_duration_ratio': credit_to_duration_ratio,
134
+ 'duration_history_interaction': int(duration > 24 and credit_history in ['A30', 'A33', 'A34']),
135
+ 'amount_checking_interaction': int(credit_amount > 5000 and checking_account in ['A13', 'A14']),
136
+ **risk_flags,
137
+ **additional_flags
138
+ }
139
+
140
+ # Convert to DataFrame for prediction
141
+ df = pd.DataFrame([input_data])
142
+
143
+ # Make prediction using the pipeline
144
+ try:
145
+ # For debugging
146
+ print(f"Input DataFrame shape: {df.shape}")
147
+ print(f"Input DataFrame columns: {df.columns.tolist()}")
148
+
149
+ y_proba = model.predict_proba(df)[0][1]
150
+
151
+ # Determine risk level based on probability
152
+ if y_proba > 0.7:
153
+ risk = "High Risk"
154
+ color = "#f44336" # Red
155
+ approval = "Loan Rejected"
156
+ icon = "❌"
157
+ elif y_proba > 0.4:
158
+ risk = "Medium Risk"
159
+ color = "#ff9800" # Orange
160
+ approval = "Further Review Required"
161
+ icon = "⚠️"
162
+ else:
163
+ risk = "Low Risk"
164
+ color = "#4caf50" # Green
165
+ approval = "Loan Approved"
166
+ icon = "✅"
167
+
168
+ # Format a detailed response
169
+ return f"""
170
+ <div style='padding: 1.5rem; border-radius: 0.5rem; background-color: {color}; color: white;'>
171
+ <h2 style='margin-top: 0;'>{icon} {risk}: {approval}</h2>
172
+ <p style='font-size: 1.2rem;'>Risk Score: {y_proba:.2%}</p>
173
+ <hr style='border-color: rgba(255,255,255,0.3);'>
174
+ <div style='margin-top: 1rem;'>
175
+ <p><strong>Key Risk Factors:</strong></p>
176
+ <ul>
177
+ <li>Credit Amount: £{credit_amount:,.2f} ({credit_amount_group})</li>
178
+ <li>Loan Duration: {duration} months ({duration_group})</li>
179
+ <li>Monthly Payment: £{credit_per_month:,.2f}</li>
180
+ <li>Credit History: {credit_history_simple}</li>
181
+ <li>Debt Burden: {debt_burden:.2f}%</li>
182
+ </ul>
183
+ </div>
184
+ </div>
185
+ """
186
+
187
+ except Exception as inner_e:
188
+ print(f"Prediction error: {inner_e}")
189
+ print(f"DataFrame columns: {df.columns.tolist()}")
190
+ return f"""
191
+ <div style='padding: 1rem; border-radius: 0.5rem; background-color: #f44336; color: white;'>
192
+ <h2>Error in Prediction</h2>
193
+ <p>{str(inner_e)}</p>
194
+ <p>Please check the server logs for details.</p>
195
+ </div>
196
+ """
197
+
198
+ except Exception as e:
199
+ print(f"Error in processing: {e}")
200
+ return f"""
201
+ <div style='padding: 1rem; border-radius: 0.5rem; background-color: #f44336; color: white;'>
202
+ <h2>Error Processing Request</h2>
203
+ <p>{str(e)}</p>
204
+ <p>Please check the server logs for details.</p>
205
+ </div>
206
+ """