Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,6 +8,7 @@ import time
|
|
| 8 |
import matplotlib.pyplot as plt
|
| 9 |
import qrcode
|
| 10 |
from io import BytesIO
|
|
|
|
| 11 |
|
| 12 |
# Load the trained models and transformers
|
| 13 |
num_imputer = joblib.load('numerical_imputer.joblib')
|
|
@@ -55,16 +56,34 @@ st.title('π EXPRESSO TELECOM CUSTOMER CHURN PREDICTION APP π')
|
|
| 55 |
|
| 56 |
# Main page - Churn Prediction
|
| 57 |
st.image("banner.png", use_column_width=True)
|
|
|
|
|
|
|
| 58 |
|
| 59 |
# How to use
|
| 60 |
-
st.
|
| 61 |
-
st.
|
| 62 |
-
st.
|
| 63 |
-
st.
|
| 64 |
-
st.
|
| 65 |
-
st.
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
# Define a dictionary of models with their names, actual models, and types
|
| 70 |
models = {
|
|
@@ -73,7 +92,9 @@ models = {
|
|
| 73 |
}
|
| 74 |
|
| 75 |
# Allow the user to select a model from the sidebar
|
| 76 |
-
|
|
|
|
|
|
|
| 77 |
|
| 78 |
# Retrieve the selected model and its type from the dictionary
|
| 79 |
model = models[model_name]['model']
|
|
@@ -158,6 +179,7 @@ def predict_churn(input_data, model):
|
|
| 158 |
# Return churn labels, churn probabilities, churn indices, and churn index
|
| 159 |
return churn_labels, churn_probability, churn_indices, churn_index
|
| 160 |
|
|
|
|
| 161 |
# Predict churn based on user input
|
| 162 |
if st.sidebar.button('Predict Churn'):
|
| 163 |
try:
|
|
@@ -172,9 +194,7 @@ if st.sidebar.button('Predict Churn'):
|
|
| 172 |
#churn_labels, churn_probability = predict_churn(input_features, model) # Pass model1 or model2 based on the selected model
|
| 173 |
churn_labels, churn_probability, churn_indices, churn_index = predict_churn(input_features, model)
|
| 174 |
|
| 175 |
-
st.subheader('Main
|
| 176 |
-
|
| 177 |
-
|
| 178 |
|
| 179 |
col1, col2 = st.columns(2)
|
| 180 |
|
|
@@ -281,6 +301,7 @@ if st.sidebar.button('Predict Churn'):
|
|
| 281 |
else:
|
| 282 |
churn_comparison = "equal"
|
| 283 |
|
|
|
|
| 284 |
explanation = f"This bar chart compares the churn probability of the selected customer " \
|
| 285 |
f"with the average churn rate of all customers. It provides insights into how the " \
|
| 286 |
f"individual customer's churn likelihood ({predicted_churn_prob:.2f}) compares to the " \
|
|
@@ -305,16 +326,21 @@ if st.sidebar.button('Predict Churn'):
|
|
| 305 |
)
|
| 306 |
|
| 307 |
explanation = f"This bar chart compares the churn probability of the selected customer " \
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
|
|
|
|
|
|
|
|
|
| 313 |
|
| 314 |
st.plotly_chart(fig)
|
| 315 |
st.write(explanation)
|
| 316 |
|
| 317 |
# Visualize Feature Importance
|
|
|
|
|
|
|
| 318 |
if hasattr(model, 'coef_'): # Check if the model has attribute 'coef_' to determine importance type
|
| 319 |
feature_importances = model.coef_[0]
|
| 320 |
importance_type = 'Coef'
|
|
@@ -329,8 +355,6 @@ if st.sidebar.button('Predict Churn'):
|
|
| 329 |
importance_df = pd.DataFrame({'Feature': original_feature_names, importance_type: feature_importances})
|
| 330 |
importance_df = importance_df.sort_values(importance_type, ascending=False)
|
| 331 |
|
| 332 |
-
st.subheader('Feature Importance')
|
| 333 |
-
|
| 334 |
# Determine color for each bar based on positive or negative importance
|
| 335 |
colors = ['green' if importance > 0 else 'red' for importance in importance_df[importance_type]]
|
| 336 |
|
|
@@ -357,55 +381,22 @@ if st.sidebar.button('Predict Churn'):
|
|
| 357 |
|
| 358 |
# Explanation of feature importance
|
| 359 |
importance_explanation = f"The feature importance plot shows the relative importance of each feature " \
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
|
|
|
| 372 |
|
| 373 |
st.write(importance_explanation)
|
| 374 |
-
else:
|
| 375 |
-
st.write('Feature importance is not available for this model.')
|
| 376 |
|
| 377 |
-
# def generate_qr_code(churn_labels, churn_probability, average_churn_rate):
|
| 378 |
-
# # Create a string representation of the important results
|
| 379 |
-
# result_string = f"Churn Probability: {churn_probability:.2f}\n" \
|
| 380 |
-
# f"Average Churn Rate: {average_churn_rate:.2f}"
|
| 381 |
-
#
|
| 382 |
-
# # Generate the QR code
|
| 383 |
-
# qr = qrcode.QRCode(
|
| 384 |
-
# version=1,
|
| 385 |
-
# error_correction=qrcode.constants.ERROR_CORRECT_L,
|
| 386 |
-
# box_size=10,
|
| 387 |
-
# border=4,)
|
| 388 |
-
# qr.add_data(result_string)
|
| 389 |
-
# qr.make(fit=True)
|
| 390 |
-
|
| 391 |
-
# Create an image from the QR code
|
| 392 |
-
# qr_image = qr.make_image(fill_color="black", back_color="white")
|
| 393 |
-
|
| 394 |
-
# Resize the image to a smaller size for mobile-friendly display
|
| 395 |
-
# qr_image = qr_image.resize((200, 200))
|
| 396 |
-
|
| 397 |
-
# Create a BytesIO object to store the image data
|
| 398 |
-
# image_stream = BytesIO()
|
| 399 |
-
# qr_image.save(image_stream, format='PNG')
|
| 400 |
-
# image_stream.seek(0)
|
| 401 |
-
|
| 402 |
-
# return image_stream
|
| 403 |
-
|
| 404 |
-
# Generate the QR code for the important results
|
| 405 |
-
# qr_image_stream = generate_qr_code(churn_labels, churn_probability, average_churn_rate)
|
| 406 |
-
|
| 407 |
-
# # Display the QR code using the Streamlit `image` function
|
| 408 |
-
# st.image(qr_image_stream, use_column_width=True)
|
| 409 |
|
| 410 |
except Exception as e:
|
| 411 |
st.error(f"An error occurred: {str(e)}")
|
|
|
|
| 8 |
import matplotlib.pyplot as plt
|
| 9 |
import qrcode
|
| 10 |
from io import BytesIO
|
| 11 |
+
import csv
|
| 12 |
|
| 13 |
# Load the trained models and transformers
|
| 14 |
num_imputer = joblib.load('numerical_imputer.joblib')
|
|
|
|
| 56 |
|
| 57 |
# Main page - Churn Prediction
|
| 58 |
st.image("banner.png", use_column_width=True)
|
| 59 |
+
st.markdown("This app predicts whether a customer will leave your company β or not π. Enter the details of the customer on the left sidebar to see the result")
|
| 60 |
+
|
| 61 |
|
| 62 |
# How to use
|
| 63 |
+
st.title('How to Use')
|
| 64 |
+
st.markdown('1. Select your model of choice on the left sidebar.')
|
| 65 |
+
st.markdown('2. Adjust the input parameters based on customer details')
|
| 66 |
+
st.markdown('3. Click the "Predict" button to initiate the prediction.')
|
| 67 |
+
st.markdown('4. The app will simulate a prediction process with a progress bar.')
|
| 68 |
+
st.markdown('5. Once the prediction is complete, the results will be displayed below.')
|
| 69 |
+
|
| 70 |
+
import csv
|
| 71 |
+
import streamlit as st
|
| 72 |
|
| 73 |
+
# Add context text
|
| 74 |
+
st.sidebar.markdown('**Welcome!**')
|
| 75 |
+
st.sidebar.markdown('This is a work in progress, and we would love to hear your suggestions on how to improve the user experience. Please feel free to provide your feedback in the suggestion box below.')
|
| 76 |
+
|
| 77 |
+
# Create the sidebar with a text input field for suggestions
|
| 78 |
+
correction_text = st.sidebar.text_input('Enter your suggestion')
|
| 79 |
+
|
| 80 |
+
# Button to submit the suggestion
|
| 81 |
+
if st.sidebar.button('Submit'):
|
| 82 |
+
# Perform action on suggestion submission (e.g., save to a CSV file)
|
| 83 |
+
with open('suggestions.csv', 'a', newline='') as file:
|
| 84 |
+
writer = csv.writer(file)
|
| 85 |
+
writer.writerow([correction_text])
|
| 86 |
+
st.sidebar.info('Suggestion submitted successfully')
|
| 87 |
|
| 88 |
# Define a dictionary of models with their names, actual models, and types
|
| 89 |
models = {
|
|
|
|
| 92 |
}
|
| 93 |
|
| 94 |
# Allow the user to select a model from the sidebar
|
| 95 |
+
# Allow the user to select a model from the sidebar
|
| 96 |
+
st.sidebar.title('Select Model')
|
| 97 |
+
model_name = st.sidebar.selectbox('Choose a model', list(models.keys()))
|
| 98 |
|
| 99 |
# Retrieve the selected model and its type from the dictionary
|
| 100 |
model = models[model_name]['model']
|
|
|
|
| 179 |
# Return churn labels, churn probabilities, churn indices, and churn index
|
| 180 |
return churn_labels, churn_probability, churn_indices, churn_index
|
| 181 |
|
| 182 |
+
|
| 183 |
# Predict churn based on user input
|
| 184 |
if st.sidebar.button('Predict Churn'):
|
| 185 |
try:
|
|
|
|
| 194 |
#churn_labels, churn_probability = predict_churn(input_features, model) # Pass model1 or model2 based on the selected model
|
| 195 |
churn_labels, churn_probability, churn_indices, churn_index = predict_churn(input_features, model)
|
| 196 |
|
| 197 |
+
st.subheader('Main Results')
|
|
|
|
|
|
|
| 198 |
|
| 199 |
col1, col2 = st.columns(2)
|
| 200 |
|
|
|
|
| 301 |
else:
|
| 302 |
churn_comparison = "equal"
|
| 303 |
|
| 304 |
+
|
| 305 |
explanation = f"This bar chart compares the churn probability of the selected customer " \
|
| 306 |
f"with the average churn rate of all customers. It provides insights into how the " \
|
| 307 |
f"individual customer's churn likelihood ({predicted_churn_prob:.2f}) compares to the " \
|
|
|
|
| 326 |
)
|
| 327 |
|
| 328 |
explanation = f"This bar chart compares the churn probability of the selected customer " \
|
| 329 |
+
f"with the average churn rate of all customers. It provides insights into how the " \
|
| 330 |
+
f"individual customer's likelihood of churn ({1 - predicted_churn_prob:.2f}) compares to the " \
|
| 331 |
+
f"overall trend. A lower churn probability indicates that the customer is less likely to churn. " \
|
| 332 |
+
f"The chart shows that the churn probability ({1 - predicted_churn_prob:.2f}) is lower than the " \
|
| 333 |
+
f"average churn probability ({main_data_churn_probability:.2f}), suggesting that the customer " \
|
| 334 |
+
f"is predicted to stay with the company. Keep in mind that the prediction is based on the " \
|
| 335 |
+
f"available data and the applied model, and there might still be some uncertainty in the result."
|
| 336 |
+
|
| 337 |
|
| 338 |
st.plotly_chart(fig)
|
| 339 |
st.write(explanation)
|
| 340 |
|
| 341 |
# Visualize Feature Importance
|
| 342 |
+
|
| 343 |
+
st.subheader('Feature Importance')
|
| 344 |
if hasattr(model, 'coef_'): # Check if the model has attribute 'coef_' to determine importance type
|
| 345 |
feature_importances = model.coef_[0]
|
| 346 |
importance_type = 'Coef'
|
|
|
|
| 355 |
importance_df = pd.DataFrame({'Feature': original_feature_names, importance_type: feature_importances})
|
| 356 |
importance_df = importance_df.sort_values(importance_type, ascending=False)
|
| 357 |
|
|
|
|
|
|
|
| 358 |
# Determine color for each bar based on positive or negative importance
|
| 359 |
colors = ['green' if importance > 0 else 'red' for importance in importance_df[importance_type]]
|
| 360 |
|
|
|
|
| 381 |
|
| 382 |
# Explanation of feature importance
|
| 383 |
importance_explanation = f"The feature importance plot shows the relative importance of each feature " \
|
| 384 |
+
f"for predicting churn. The importance is calculated based on the " \
|
| 385 |
+
f"{importance_type} value of each feature in the model. " \
|
| 386 |
+
f"A higher {importance_type} value indicates a stronger influence " \
|
| 387 |
+
f"of the corresponding feature on the prediction of churn.\n\n" \
|
| 388 |
+
f"For logistic regression, positive {importance_type} values indicate " \
|
| 389 |
+
f"features that positively contribute to predicting churn, " \
|
| 390 |
+
f"while negative {importance_type} values indicate features that " \
|
| 391 |
+
f"negatively contribute to predicting churn.\n\n" \
|
| 392 |
+
f"For gradient boosting, higher {importance_type} values " \
|
| 393 |
+
f"indicate features that have a greater importance in predicting churn.\n\n" \
|
| 394 |
+
f"Please note that the feature importance values may vary depending on the model " \
|
| 395 |
+
f"and the data used for training."
|
| 396 |
+
|
| 397 |
|
| 398 |
st.write(importance_explanation)
|
|
|
|
|
|
|
| 399 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
|
| 401 |
except Exception as e:
|
| 402 |
st.error(f"An error occurred: {str(e)}")
|