import streamlit as st import pandas as pd import numpy as np import pickle from PIL import Image import plotly.express as px import plotly.graph_objects as go from streamlit_lottie import st_lottie import requests from streamlit_option_menu import option_menu # --------- UTILS --------- @st.cache_resource def load_model(): with open('src/best_regression_model.pkl', 'rb') as f: data = pickle.load(f) return data['model'], data['scaler_X'], data['scaler_y'], data.get('metrics', None) def load_lottieurl(url: str): r = requests.get(url) if r.status_code != 200: return None return r.json() # --------- ANIMATIONS --------- credit_animation = load_lottieurl("https://assets2.lottiefiles.com/packages/lf20_4kx2q32n.json") loading_animation = load_lottieurl("https://assets3.lottiefiles.com/packages/lf20_p8bfn5to.json") about_animation = load_lottieurl("https://assets2.lottiefiles.com/packages/lf20_0yfsb3a1.json") # --------- PAGE CONFIG --------- st.set_page_config( page_title="Credit Card Expenditure Predictor", page_icon="💳", layout="wide", initial_sidebar_state="expanded" ) # --------- CSS --------- st.markdown(""" """, unsafe_allow_html=True) # --------- SIDEBAR --------- with st.sidebar: st_lottie(credit_animation, height=120, key="sidebar_animation") selected = option_menu( menu_title="Navigation", options=["Accueil", "Prédiction", "Analyse", "À propos"], icons=['house', 'credit-card', 'bar-chart', 'info-circle'], menu_icon="cast", default_index=0, styles={ "container": {"padding": "0!important", "background-color": "#ffffff"}, "icon": {"color": "#4b79a1", "font-size": "20px"}, "nav-link": { "font-size": "16px", "text-align": "left", "margin": "0px", "padding": "10px", "--hover-color": "#4b79a1", }, "nav-link-selected": {"background-color": "#4b79a1"}, } ) # --------- ACCUEIL --------- if selected == "Accueil": st.markdown("""

💳 Credit Card Expenditure Predictor

Prédisez les dépenses annuelles de vos clients grâce à l'IA, pour une gestion financière plus intelligente et personnalisée.


Cette application met la puissance du machine learning au service de la finance : analysez, prédisez et optimisez les dépenses de carte de crédit de vos clients en quelques clics.
Pensée pour les professionnels, accessible à tous.

""", unsafe_allow_html=True) col1, col2 = st.columns([1.5, 1]) with col1: st.markdown("""

🎯 Mission

Offrir un outil prédictif fiable et intuitif pour anticiper les dépenses annuelles des clients, en s'appuyant sur leurs caractéristiques financières et personnelles.

🔬 Technologies

Random Forest XGBoost SVR GridSearchCV Scikit-learn Streamlit Plotly
""", unsafe_allow_html=True) with col2: st_lottie(credit_animation, height=220, key="main_animation") st.markdown("""

+2000

Clients analysés

""", unsafe_allow_html=True) # --------- PREDICTION --------- elif selected == "Prédiction": st.markdown("""

🔮 Prédiction de Dépense

Remplissez le formulaire ci-dessous pour estimer la dépense annuelle d'un client

""", unsafe_allow_html=True) with st.form("prediction_form"): st.markdown("
", unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: st.markdown("

Informations personnelles

", unsafe_allow_html=True) age = st.number_input("Âge", min_value=18, max_value=100, value=35) owner = st.selectbox("Propriétaire d'une maison", ["Non", "Oui"]) selfemp = st.selectbox("Travailleur indépendant", ["Non", "Oui"]) dependents = st.number_input("Nombre de personnes à charge", min_value=0, max_value=10, value=0) with col2: st.markdown("

Informations financières

", unsafe_allow_html=True) income = st.number_input("Revenu annuel ($)", min_value=0, max_value=500000, value=50000) share = st.slider("Part de revenu allouée à la carte (%)", min_value=0, max_value=100, value=10) reports = st.number_input("Nombre de rapports de crédit", min_value=0, max_value=20, value=2) months = st.number_input("Ancienneté (mois)", min_value=0, max_value=240, value=12) majorcards = st.number_input("Nombre de cartes principales", min_value=0, max_value=5, value=1) active = st.number_input("Nombre de comptes actifs", min_value=0, max_value=10, value=2) st.markdown("
", unsafe_allow_html=True) real_expenditure = st.number_input("Valeur réelle de la dépense (optionnel)", min_value=0, max_value=100000, value=0) submit_button = st.form_submit_button("💡 Prédire la dépense", use_container_width=True) st.markdown("
", unsafe_allow_html=True) if submit_button: with st.spinner("Prédiction en cours..."): st_lottie(loading_animation, height=100, key="loading") # Préparation des données input_df = pd.DataFrame({ 'income': [income], 'share': [share], 'age': [age], 'owner_No': [1 if owner == "Non" else 0], 'owner_Yes': [1 if owner == "Oui" else 0], 'selfemp_No': [1 if selfemp == "Non" else 0], 'selfemp_Yes': [1 if selfemp == "Oui" else 0], 'reports': [reports], 'dependents': [dependents], 'months': [months], 'majorcards': [majorcards], 'active': [active] }) # Charger modèle et scalers model, scaler_X, scaler_y, metrics = load_model() # Adapter les colonnes à l'ordre attendu X_cols = scaler_X.feature_names_in_ input_df = input_df.reindex(columns=X_cols, fill_value=0) # Normaliser X_scaled = scaler_X.transform(input_df) y_pred_scaled = model.predict(X_scaled) y_pred = scaler_y.inverse_transform(y_pred_scaled.reshape(-1, 1)).ravel()[0] # Affichage st.markdown("""

Résultat de la Prédiction

""", unsafe_allow_html=True) st.metric("Dépense prédite ($)", f"{y_pred:,.2f}") if real_expenditure > 0: st.metric("Valeur réelle ($)", f"{real_expenditure:,.2f}", delta=f"{y_pred-real_expenditure:,.2f}") fig = go.Figure() fig.add_trace(go.Bar( x=["Prédiction", "Réel"], y=[y_pred, real_expenditure], marker_color=["#4b79a1", "#283e51"] )) fig.update_layout(title="Comparaison Prédiction vs Réel", yaxis_title="Dépense ($)") st.plotly_chart(fig, use_container_width=True) st.markdown("
", unsafe_allow_html=True) # --------- ANALYSE --------- elif selected == "Analyse": st.markdown("""

📊 Tableau de Bord Analytique

Explorez la performance du modèle et les tendances clés du dataset.

""", unsafe_allow_html=True) # Charger le dataset et le modèle df = pd.read_csv('AER_credit_card_data.csv') X = df.drop(['expenditure', 'card'], axis=1) y = df['expenditure'] X = pd.get_dummies(X, columns=['owner', 'selfemp']) model, scaler_X, scaler_y, metrics = load_model() X = X.reindex(columns=scaler_X.feature_names_in_, fill_value=0) X_scaled = scaler_X.transform(X) y_pred_scaled = model.predict(X_scaled) y_pred = scaler_y.inverse_transform(y_pred_scaled.reshape(-1, 1)).ravel() from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score mse = mean_squared_error(y, y_pred) rmse = np.sqrt(mse) mae = mean_absolute_error(y, y_pred) r2 = r2_score(y, y_pred) # --- Bloc Performance du Modèle --- if metrics: # On affiche uniquement les vraies métriques du best model st.markdown(f"""

✨ Performance du Meilleur Modèle


Analyse Visuelle
""", unsafe_allow_html=True) else: # fallback si jamais metrics n'est pas dispo st.markdown("""

✨ Performance du Modèle

(Métriques calculées sur tout le dataset, à titre indicatif)


Analyse Visuelle
""".format(rmse, mae, r2), unsafe_allow_html=True) # --- 1. Scatter plot Prédiction vs Réel --- st.markdown("""

1. Prédictions vs Valeurs réelles

Chaque point représente un client. Plus les points sont proches de la diagonale, plus la prédiction est précise.

""", unsafe_allow_html=True) fig1 = px.scatter( x=y, y=y_pred, labels={'x': 'Valeur réelle', 'y': 'Prédiction'}, color_discrete_sequence=["#4b79a1"], title=None ) fig1.add_shape( type="line", x0=y.min(), y0=y.min(), x1=y.max(), y1=y.max(), line=dict(color="#e74c3c", dash="dash") ) fig1.update_layout(showlegend=False, height=350, margin=dict(l=20, r=20, t=30, b=20)) st.plotly_chart(fig1, use_container_width=True) st.markdown("
", unsafe_allow_html=True) # --- 2. Distribution des Dépenses Réelles --- st.markdown("""

2. Distribution des dépenses réelles

Visualisation de la répartition des dépenses annuelles des clients.

""", unsafe_allow_html=True) fig2 = px.histogram(df, x="expenditure", nbins=40, color_discrete_sequence=["#283e51"]) fig2.update_layout( xaxis_title="Dépense annuelle ($)", yaxis_title="Nombre de clients", height=300, margin=dict(l=20, r=20, t=30, b=20) ) st.plotly_chart(fig2, use_container_width=True) st.markdown("
", unsafe_allow_html=True) # --- 3. Importance des variables --- st.markdown("""

3. Importance des variables

Les variables les plus influentes dans la prédiction selon le modèle.

""", unsafe_allow_html=True) if hasattr(model, "feature_importances_"): importances = model.feature_importances_ features = X.columns imp_df = pd.DataFrame({"Variable": features, "Importance": importances}) imp_df = imp_df.sort_values("Importance", ascending=True) fig3 = px.bar( imp_df, x="Importance", y="Variable", orientation="h", color="Importance", color_continuous_scale="blues", height=350 ) fig3.update_layout(margin=dict(l=20, r=20, t=30, b=20), coloraxis_showscale=False) st.plotly_chart(fig3, use_container_width=True) else: st.info("L'importance des variables n'est pas disponible pour ce modèle.") st.markdown("
", unsafe_allow_html=True) # --- 4. Dépense moyenne par statut de propriétaire --- st.markdown("""

4. Dépense moyenne selon le statut de propriétaire

Comparaison des dépenses annuelles entre propriétaires et non-propriétaires.

""", unsafe_allow_html=True) fig4 = px.box( df, x="owner", y="expenditure", color="owner", color_discrete_sequence=["#4b79a1", "#283e51"], points="all", height=320 ) fig4.update_layout( xaxis_title="Statut de propriétaire", yaxis_title="Dépense annuelle ($)", showlegend=False, margin=dict(l=20, r=20, t=30, b=20) ) st.plotly_chart(fig4, use_container_width=True) st.markdown("
", unsafe_allow_html=True) # --- 5. Matrice de corrélation --- st.markdown("""

5. Corrélation entre variables

Les relations linéaires entre les principales variables du dataset.

""", unsafe_allow_html=True) corr = df.select_dtypes(include=[np.number]).corr() fig5 = px.imshow( corr, text_auto=True, color_continuous_scale="blues", aspect="auto", height=400 ) fig5.update_layout(margin=dict(l=20, r=20, t=30, b=20)) st.plotly_chart(fig5, use_container_width=True) st.markdown("
", unsafe_allow_html=True) # --------- A PROPOS --------- elif selected == "À propos": st.markdown("""

À propos

Découvrez le créateur, le projet et les technologies utilisées

""", unsafe_allow_html=True) col1, col2 = st.columns([1, 2]) with col1: st_lottie(about_animation, height=220, key="about_animation") st.image( "https://avatars.githubusercontent.com/u/TheBeyonder237", width=180, caption="Ngoue David", output_format="auto", use_column_width=False, channels="RGB" ) st.markdown("""
""", unsafe_allow_html=True) with col2: st.markdown("""

Qui suis-je ?

Je suis un passionné de l'intelligence artificielle et de la donnée.
Actuellement en Master 2 en IA et Big Data, je travaille sur des solutions innovantes dans le domaine de l'Intelligence Artificielle appliquée à la finance et à la santé.

Compétences

Python Machine Learning Deep Learning NLP Data Science Cloud Computing Streamlit Scikit-learn XGBoost Pandas Plotly SQL

Projets Récents

""", unsafe_allow_html=True) st.markdown("""
Développé avec ❤️ par Ngoue David
""", unsafe_allow_html=True)