Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -100,6 +100,175 @@ def plot_feature_importance(model, feature_names, model_type):
|
|
100 |
plt.title(f"Feature Importance - {model_type}")
|
101 |
return plt.gcf()
|
102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
def app():
|
104 |
st.title("Interpréteur de Modèles ML")
|
105 |
|
@@ -123,7 +292,8 @@ def app():
|
|
123 |
["Performance des modèles",
|
124 |
"Interprétation du modèle",
|
125 |
"Analyse des caractéristiques",
|
126 |
-
"Simulateur de prédictions"
|
|
|
127 |
)
|
128 |
|
129 |
current_model = st.session_state.model_results[selected_model]['model']
|
@@ -195,6 +365,16 @@ def app():
|
|
195 |
fig, ax = plt.subplots(figsize=(10, 8))
|
196 |
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
|
197 |
st.pyplot(fig)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
# Simulateur de prédictions
|
200 |
else:
|
|
|
100 |
plt.title(f"Feature Importance - {model_type}")
|
101 |
return plt.gcf()
|
102 |
|
103 |
+
def prepare_clustering_data(data, numeric_columns):
|
104 |
+
scaler = StandardScaler()
|
105 |
+
scaled_features = scaler.fit_transform(data[numeric_columns])
|
106 |
+
return scaled_features, scaler
|
107 |
+
|
108 |
+
def perform_clustering(scaled_features, n_clusters):
|
109 |
+
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
|
110 |
+
cluster_labels = kmeans.fit_predict(scaled_features)
|
111 |
+
return kmeans, cluster_labels
|
112 |
+
|
113 |
+
def plot_clusters_3d(data, labels, features, product_category):
|
114 |
+
pca = PCA(n_components=3)
|
115 |
+
components = pca.fit_transform(data)
|
116 |
+
|
117 |
+
df_plot = pd.DataFrame({
|
118 |
+
'PC1': components[:, 0],
|
119 |
+
'PC2': components[:, 1],
|
120 |
+
'PC3': components[:, 2],
|
121 |
+
'Cluster': [f"Groupe {i}" for i in labels]
|
122 |
+
})
|
123 |
+
|
124 |
+
fig = px.scatter_3d(
|
125 |
+
df_plot,
|
126 |
+
x='PC1',
|
127 |
+
y='PC2',
|
128 |
+
z='PC3',
|
129 |
+
color='Cluster',
|
130 |
+
title=f'Analyse des sous-groupes pour {product_category}',
|
131 |
+
labels={
|
132 |
+
'PC1': 'Composante 1',
|
133 |
+
'PC2': 'Composante 2',
|
134 |
+
'PC3': 'Composante 3'
|
135 |
+
}
|
136 |
+
)
|
137 |
+
|
138 |
+
fig.update_layout(
|
139 |
+
scene=dict(
|
140 |
+
xaxis_title='Composante 1',
|
141 |
+
yaxis_title='Composante 2',
|
142 |
+
zaxis_title='Composante 3'
|
143 |
+
),
|
144 |
+
legend_title_text='Sous-groupes'
|
145 |
+
)
|
146 |
+
|
147 |
+
return fig
|
148 |
+
|
149 |
+
def analyze_clusters(data, cluster_labels, numeric_columns, product_category):
|
150 |
+
data_with_clusters = data.copy()
|
151 |
+
data_with_clusters['Cluster'] = cluster_labels
|
152 |
+
|
153 |
+
cluster_stats = []
|
154 |
+
for cluster in range(len(np.unique(cluster_labels))):
|
155 |
+
cluster_data = data_with_clusters[data_with_clusters['Cluster'] == cluster]
|
156 |
+
stats = {
|
157 |
+
'Cluster': cluster,
|
158 |
+
'Taille': len(cluster_data),
|
159 |
+
'Product': product_category,
|
160 |
+
'Caractéristiques principales': {}
|
161 |
+
}
|
162 |
+
|
163 |
+
for col in numeric_columns:
|
164 |
+
stats['Caractéristiques principales'][col] = cluster_data[col].mean()
|
165 |
+
|
166 |
+
cluster_stats.append(stats)
|
167 |
+
|
168 |
+
return cluster_stats
|
169 |
+
|
170 |
+
def add_clustering_analysis(data):
|
171 |
+
st.header("Analyse par Clustering des Produits Acceptés")
|
172 |
+
|
173 |
+
if data is None:
|
174 |
+
st.error("Veuillez charger des données pour l'analyse")
|
175 |
+
return
|
176 |
+
|
177 |
+
# Filtrer uniquement les clients ayant accepté un produit
|
178 |
+
accepted_data = data[data['ProdTaken'] == 1]
|
179 |
+
|
180 |
+
if len(accepted_data) == 0:
|
181 |
+
st.error("Aucune donnée trouvée pour les produits acceptés")
|
182 |
+
return
|
183 |
+
|
184 |
+
st.write(f"Nombre total de produits acceptés: {len(accepted_data)}")
|
185 |
+
|
186 |
+
# Obtenir les différents types de produits proposés
|
187 |
+
product_types = accepted_data['ProductPitched'].unique()
|
188 |
+
st.write(f"Types de produits disponibles: {', '.join(product_types)}")
|
189 |
+
|
190 |
+
# Sélection des caractéristiques pour le clustering
|
191 |
+
numeric_columns = st.multiselect(
|
192 |
+
"Sélectionner les caractéristiques pour l'analyse",
|
193 |
+
data.select_dtypes(include=['float64', 'int64']).columns,
|
194 |
+
help="Choisissez les caractéristiques numériques pertinentes pour l'analyse"
|
195 |
+
)
|
196 |
+
|
197 |
+
if numeric_columns:
|
198 |
+
for product in product_types:
|
199 |
+
st.subheader(f"\nAnalyse du produit: {product}")
|
200 |
+
|
201 |
+
product_data = accepted_data[accepted_data['ProductPitched'] == product]
|
202 |
+
st.write(f"Nombre de clients ayant accepté ce produit: {len(product_data)}")
|
203 |
+
|
204 |
+
max_clusters = min(len(product_data) - 1, 10)
|
205 |
+
if max_clusters < 2:
|
206 |
+
st.warning(f"Pas assez de données pour le clustering du produit {product}")
|
207 |
+
continue
|
208 |
+
|
209 |
+
n_clusters = st.slider(
|
210 |
+
f"Nombre de sous-groupes pour {product}",
|
211 |
+
2, max_clusters,
|
212 |
+
min(3, max_clusters),
|
213 |
+
key=f"slider_{product}"
|
214 |
+
)
|
215 |
+
|
216 |
+
scaled_features, _ = prepare_clustering_data(product_data, numeric_columns)
|
217 |
+
kmeans, cluster_labels = perform_clustering(scaled_features, n_clusters)
|
218 |
+
|
219 |
+
silhouette_avg = silhouette_score(scaled_features, cluster_labels)
|
220 |
+
st.write(f"Score de silhouette: {silhouette_avg:.3f}")
|
221 |
+
|
222 |
+
fig = plot_clusters_3d(scaled_features, cluster_labels, numeric_columns, product)
|
223 |
+
st.plotly_chart(fig)
|
224 |
+
|
225 |
+
st.write("### Caractéristiques des sous-groupes")
|
226 |
+
cluster_stats = analyze_clusters(product_data, cluster_labels, numeric_columns, product)
|
227 |
+
|
228 |
+
global_means = product_data[numeric_columns].mean()
|
229 |
+
|
230 |
+
for stats in cluster_stats:
|
231 |
+
st.write(f"\n**Sous-groupe {stats['Cluster']} ({stats['Taille']} clients)**")
|
232 |
+
|
233 |
+
comparison_data = []
|
234 |
+
for feat, value in stats['Caractéristiques principales'].items():
|
235 |
+
global_mean = global_means[feat]
|
236 |
+
diff_percent = ((value - global_mean) / global_mean * 100)
|
237 |
+
comparison_data.append({
|
238 |
+
'Caractéristique': feat,
|
239 |
+
'Valeur moyenne du groupe': f"{value:.2f}",
|
240 |
+
'Moyenne globale': f"{global_mean:.2f}",
|
241 |
+
'Différence (%)': f"{diff_percent:+.1f}%"
|
242 |
+
})
|
243 |
+
|
244 |
+
comparison_df = pd.DataFrame(comparison_data)
|
245 |
+
st.table(comparison_df)
|
246 |
+
|
247 |
+
st.write("### Recommandations marketing")
|
248 |
+
distinctive_features = []
|
249 |
+
for col in numeric_columns:
|
250 |
+
cluster_mean = product_data[cluster_labels == stats['Cluster']][col].mean()
|
251 |
+
global_mean = product_data[col].mean()
|
252 |
+
diff_percent = ((cluster_mean - global_mean) / global_mean * 100)
|
253 |
+
|
254 |
+
if abs(diff_percent) > 10:
|
255 |
+
distinctive_features.append({
|
256 |
+
'feature': col,
|
257 |
+
'diff': diff_percent,
|
258 |
+
'value': cluster_mean
|
259 |
+
})
|
260 |
+
|
261 |
+
if distinctive_features:
|
262 |
+
recommendations = [
|
263 |
+
f"- Groupe avec {feat['feature']} {'supérieur' if feat['diff'] > 0 else 'inférieur'} " \
|
264 |
+
f"à la moyenne ({feat['diff']:+.1f}%)"
|
265 |
+
for feat in distinctive_features
|
266 |
+
]
|
267 |
+
st.write("\n".join(recommendations))
|
268 |
+
else:
|
269 |
+
st.write("- Pas de caractéristiques fortement distinctives identifiées")
|
270 |
+
|
271 |
+
|
272 |
def app():
|
273 |
st.title("Interpréteur de Modèles ML")
|
274 |
|
|
|
292 |
["Performance des modèles",
|
293 |
"Interprétation du modèle",
|
294 |
"Analyse des caractéristiques",
|
295 |
+
"Simulateur de prédictions",
|
296 |
+
"Analyse par Clustering"]
|
297 |
)
|
298 |
|
299 |
current_model = st.session_state.model_results[selected_model]['model']
|
|
|
365 |
fig, ax = plt.subplots(figsize=(10, 8))
|
366 |
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
|
367 |
st.pyplot(fig)
|
368 |
+
|
369 |
+
elif page == "Analyse par Clustering":
|
370 |
+
# Charger les données pour le clustering
|
371 |
+
uploaded_file = st.file_uploader("Charger les données pour le clustering (CSV)", type="csv")
|
372 |
+
if uploaded_file is not None:
|
373 |
+
data = pd.read_csv(uploaded_file)
|
374 |
+
add_clustering_analysis(data)
|
375 |
+
else:
|
376 |
+
st.warning("Veuillez charger un fichier CSV pour l'analyse par clustering")
|
377 |
+
|
378 |
|
379 |
# Simulateur de prédictions
|
380 |
else:
|