NIIHAAD commited on
Commit
d8e953f
·
1 Parent(s): 0259f10

updtae app.py

Browse files
Files changed (1) hide show
  1. app.py +180 -24
app.py CHANGED
@@ -10,6 +10,9 @@ import freesound
10
  import gensim.downloader as api
11
  from huggingface_hub import hf_hub_download
12
 
 
 
 
13
  # -------- FreeSound API --------
14
  client = freesound.FreesoundClient()
15
  client.set_token("zE9NjEOgUMzH9K7mjiGBaPJiNwJLjSM53LevarRK", "token")
@@ -111,18 +114,39 @@ effect_avg_rating_le = joblib.load(
111
  )
112
 
113
 
114
- # Liste des colonnes utilisées pour les modèles (même ordre que pendant le training)
 
 
115
  music_model_features = joblib.load(
116
  hf_hub_download(
117
  repo_id="NIIHAAD/freesound-models",
118
  repo_type="model",
119
- filename="model_features_list.joblib",
 
 
 
 
 
 
 
 
 
120
  cache_dir="models_cache"
121
  )
122
  )
123
 
 
 
 
124
 
125
 
 
 
 
 
 
 
 
126
  # EffectSound
127
  scaler_samplerate_effect = joblib.load("effectSound/scaler_effectSamplerate.joblib")
128
  scaler_age_days_effect = joblib.load("effectSound/scaler_effectSound_age_days_log.joblib")
@@ -135,7 +159,17 @@ effect_onehot_tags = joblib.load("effectSound/effect_onehot_tags.joblib")
135
 
136
  # GloVe pour description
137
  glove_model = api.load("glove-wiki-gigaword-100")
 
 
 
 
 
 
 
 
138
 
 
 
139
  # -------- Fonctions --------
140
 
141
  def fetch_sound_metadata(sound_url):
@@ -283,12 +317,21 @@ def preprocess_sound(df):
283
  df["tags_list"] = [["Other"]]
284
 
285
  # One-hot sur toutes les colonnes enregistrées
 
286
  for col in onehot_tags:
287
- tag_name = col.replace("tag_", "").replace("_", " ")
288
- df[col] = int(tag_name in df["tags_list"].iloc[0])
 
 
 
 
 
 
 
 
 
 
289
 
290
- # Supprimer les colonnes temporaires
291
- df.drop(columns=["tags_list", "tags"], inplace=True)
292
 
293
 
294
  # Name
@@ -308,7 +351,7 @@ def preprocess_sound(df):
308
  df.drop(columns=[ "license","category","type","created","subcategory","id","num_downloads","file_path","username"],inplace=True, errors="ignore")
309
 
310
  # --- SAFE REORDER (CRUCIAL) ---
311
-
312
  final_cols = []
313
 
314
  for col in onehot_cols:
@@ -324,87 +367,200 @@ def preprocess_sound(df):
324
  final_cols += [c for c in df.columns if c not in final_cols]
325
 
326
  df = df[final_cols]
 
327
 
328
 
329
 
330
 
331
  return df
332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  # -------- Gradio --------
334
  def predict_with_metadata(url):
 
335
  if url.strip() == "":
 
336
  return "❌ Veuillez entrer une URL FreeSound."
337
 
338
  # 1️ Récupérer les métadonnées brutes
339
  df_raw = fetch_sound_metadata(url)
340
-
341
  # Affichage ligne par ligne pour les métadonnées brutes
342
  raw_lines = ["=== Métadonnées brutes ==="]
 
343
  for col in df_raw.columns:
344
  raw_lines.append(f"{col}: {df_raw[col].iloc[0]}")
345
  raw_str = "\n".join(raw_lines)
346
 
 
347
  # 2️ Vérifier la durée
 
348
  dur = df_raw["duration"].iloc[0]
 
349
  if dur < 0.5:
 
350
  return raw_str + f"\n\n Son trop court ({dur} sec), veuillez entrer un son qui est court (0.5 à 3 s) ou un son long (10 à 60 s)"
 
351
  elif 3 < dur < 10 or dur > 60:
 
352
  return raw_str + f"\n\n Son trop long ou hors plage acceptable ({dur} sec) , veuillez entrer un son qui est court (0.5 à 3 s) ou un son long (10 à 60 s)"
353
 
354
- # PRÉDICTIONS
355
- # =======================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
 
357
  if 0.5 <= dur <= 3:
 
 
 
358
  model_nd = effect_model_num_downloads
 
359
  model_ar = effect_model_avg_rating
 
360
  le_ar = effect_avg_rating_le
 
361
  sound_type = "EffectSound"
 
362
  else:
 
 
 
363
  model_nd = music_model_num_downloads
 
364
  model_ar = music_model_avg_rating
 
365
  le_ar = music_avg_rating_le
 
366
  sound_type = "Music"
367
 
368
- # 3️ Prétraitement seulement si durée ok
369
- df_processed = preprocess_sound(df_raw)
370
 
371
- # Supprimer les colonnes inutiles
372
- cols_to_remove = ["avg_rating", "num_downloads_class"]
373
- df_for_model = df_processed.drop(columns=[c for c in cols_to_remove if c in df_processed.columns])
374
 
375
- # Réordonner les colonnes selon la liste sauvegardée pour le training
376
- df_for_model = df_for_model[music_model_features]
377
 
 
378
 
379
- # Num downloads
380
- pred_num_downloads = model_nd.predict(df_for_model)[0]
381
 
382
- # Avg rating
383
- pred_avg_rating_enc = model_ar.predict(df_for_model)[0]
384
- pred_avg_rating = le_ar.inverse_transform([pred_avg_rating_enc])[0]
385
 
386
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
 
389
 
390
  # Affichage ligne par ligne pour les features après preprocessing
 
391
  processed_lines = ["\n=== Features après preprocessing ==="]
 
392
  for col in df_processed.columns:
 
393
  processed_lines.append(f"{col}: {df_processed[col].iloc[0]}")
 
394
  processed_str = "\n".join(processed_lines)
395
-
 
 
396
  prediction_lines = [
 
397
  "\n=== Prédictions ===",
 
398
  f"Type détecté : {sound_type}",
 
399
  f"📥 Num downloads prédit : {pred_num_downloads}",
 
400
  f"⭐ Avg rating prédit : {pred_avg_rating}"
 
401
  ]
402
 
 
 
403
  prediction_str = "\n".join(prediction_lines)
404
 
 
 
405
  return raw_str + processed_str + prediction_str
406
 
407
 
 
 
408
  def preprocess_name(df, vec_dim=8):
409
  df = df.copy()
410
 
 
10
  import gensim.downloader as api
11
  from huggingface_hub import hf_hub_download
12
 
13
+ import xgboost as xgb
14
+
15
+
16
  # -------- FreeSound API --------
17
  client = freesound.FreesoundClient()
18
  client.set_token("zE9NjEOgUMzH9K7mjiGBaPJiNwJLjSM53LevarRK", "token")
 
114
  )
115
 
116
 
117
+
118
+
119
+ # Charger les listes de colonnes exactes utilisées pendant l'entraînement
120
  music_model_features = joblib.load(
121
  hf_hub_download(
122
  repo_id="NIIHAAD/freesound-models",
123
  repo_type="model",
124
+ filename="music_model_features_list.joblib",
125
+ cache_dir="models_cache"
126
+ )
127
+ )
128
+
129
+ effect_model_features = joblib.load(
130
+ hf_hub_download(
131
+ repo_id="NIIHAAD/freesound-models",
132
+ repo_type="model",
133
+ filename="effect_model_features_list.joblib",
134
  cache_dir="models_cache"
135
  )
136
  )
137
 
138
+ # Charger les listes
139
+ music_model_features_raw = music_model_features
140
+ effect_model_features_raw = effect_model_features
141
 
142
 
143
+ # NETTOYAGE : Supprimer les doublons en gardant l'ordre
144
+ music_model_features = list(dict.fromkeys(music_model_features_raw))
145
+ effect_model_features = list(dict.fromkeys(effect_model_features_raw))
146
+
147
+ print(f"Après nettoyage - Music: {len(music_model_features)} features")
148
+ print(f"Après nettoyage - Effect: {len(effect_model_features)} features")
149
+
150
  # EffectSound
151
  scaler_samplerate_effect = joblib.load("effectSound/scaler_effectSamplerate.joblib")
152
  scaler_age_days_effect = joblib.load("effectSound/scaler_effectSound_age_days_log.joblib")
 
159
 
160
  # GloVe pour description
161
  glove_model = api.load("glove-wiki-gigaword-100")
162
+ # --- AJOUTE LE CODE ICI ---
163
+ print("--- DIAGNOSTIC DES FEATURES ---")
164
+ print(f"Nombre de features Music : {len(music_model_features)}")
165
+ print(f"Doublons dans Music : {len(music_model_features) - len(set(music_model_features))}")
166
+
167
+ print(f"Nombre de features Effect : {len(effect_model_features)}")
168
+ print(f"Doublons dans Effect : {len(effect_model_features) - len(set(effect_model_features))}")
169
+ print("-------------------------------")
170
 
171
+
172
+ # ---------------------------
173
  # -------- Fonctions --------
174
 
175
  def fetch_sound_metadata(sound_url):
 
317
  df["tags_list"] = [["Other"]]
318
 
319
  # One-hot sur toutes les colonnes enregistrées
320
+ # 1️ Créer toutes les colonnes attendues avec 0
321
  for col in onehot_tags:
322
+ if col not in df.columns:
323
+ df[col] = 0
324
+
325
+ # 2️ Activer seulement les colonnes correspondant aux tags existants
326
+ tags_list = df["tags"].iloc[0].lower().split(",") if df["tags"].iloc[0] else []
327
+ for col in onehot_tags:
328
+ tag_name = col.replace("tag_", "").lower()
329
+ if tag_name in tags_list:
330
+ df[col] = 1
331
+
332
+ # 3️ Supprimer la colonne temporaire
333
+ df.drop(columns=["tags"], inplace=True)
334
 
 
 
335
 
336
 
337
  # Name
 
351
  df.drop(columns=[ "license","category","type","created","subcategory","id","num_downloads","file_path","username"],inplace=True, errors="ignore")
352
 
353
  # --- SAFE REORDER (CRUCIAL) ---
354
+ """
355
  final_cols = []
356
 
357
  for col in onehot_cols:
 
367
  final_cols += [c for c in df.columns if c not in final_cols]
368
 
369
  df = df[final_cols]
370
+ """
371
 
372
 
373
 
374
 
375
  return df
376
 
377
+
378
+
379
+ def xgb_predict_safe(model, X, feature_names, label_encoder=None):
380
+ # sécurité ultime
381
+ X = X[feature_names].astype(np.float32)
382
+
383
+ dmatrix = xgb.DMatrix(
384
+ X.values,
385
+ feature_names=feature_names
386
+ )
387
+
388
+ pred = model.get_booster().predict(dmatrix)[0]
389
+
390
+ if label_encoder is not None:
391
+ return label_encoder.inverse_transform([int(round(pred))])[0]
392
+
393
+ return pred
394
+
395
+
396
  # -------- Gradio --------
397
  def predict_with_metadata(url):
398
+
399
  if url.strip() == "":
400
+
401
  return "❌ Veuillez entrer une URL FreeSound."
402
 
403
  # 1️ Récupérer les métadonnées brutes
404
  df_raw = fetch_sound_metadata(url)
 
405
  # Affichage ligne par ligne pour les métadonnées brutes
406
  raw_lines = ["=== Métadonnées brutes ==="]
407
+
408
  for col in df_raw.columns:
409
  raw_lines.append(f"{col}: {df_raw[col].iloc[0]}")
410
  raw_str = "\n".join(raw_lines)
411
 
412
+
413
  # 2️ Vérifier la durée
414
+
415
  dur = df_raw["duration"].iloc[0]
416
+
417
  if dur < 0.5:
418
+
419
  return raw_str + f"\n\n Son trop court ({dur} sec), veuillez entrer un son qui est court (0.5 à 3 s) ou un son long (10 à 60 s)"
420
+
421
  elif 3 < dur < 10 or dur > 60:
422
+
423
  return raw_str + f"\n\n Son trop long ou hors plage acceptable ({dur} sec) , veuillez entrer un son qui est court (0.5 à 3 s) ou un son long (10 à 60 s)"
424
 
425
+
426
+
427
+ # 3️ Prétraitement seulement si durée ok
428
+
429
+ df_processed = preprocess_sound(df_raw)
430
+
431
+
432
+
433
+ # Supprimer les colonnes inutiles
434
+
435
+ cols_to_remove = ["avg_rating", "num_downloads_class"]
436
+
437
+ df_for_model = df_processed.drop(columns=[c for c in cols_to_remove if c in df_processed.columns])
438
+
439
+
440
+
441
+ # Choix modèle
442
 
443
  if 0.5 <= dur <= 3:
444
+
445
+ model_features = effect_model_features
446
+
447
  model_nd = effect_model_num_downloads
448
+
449
  model_ar = effect_model_avg_rating
450
+
451
  le_ar = effect_avg_rating_le
452
+
453
  sound_type = "EffectSound"
454
+
455
  else:
456
+
457
+ model_features = music_model_features
458
+
459
  model_nd = music_model_num_downloads
460
+
461
  model_ar = music_model_avg_rating
462
+
463
  le_ar = music_avg_rating_le
464
+
465
  sound_type = "Music"
466
 
 
 
467
 
 
 
 
468
 
469
+ # 🔹 Forcer exactement les colonnes du modèle
 
470
 
471
+ expected_n_cols = len(model_features)
472
 
 
 
473
 
 
 
 
474
 
475
+ # Supprimer tout ce qui n'est pas dans le modèle
476
+
477
+ df_for_model = df_for_model[[c for c in model_features if c in df_for_model.columns]]
478
+
479
+
480
+
481
+ # Ajouter les colonnes manquantes avec 0
482
+
483
+ for col in model_features:
484
+
485
+ if col not in df_for_model.columns:
486
+
487
+ df_for_model[col] = 0.0
488
+
489
+
490
+
491
+ # Réordonner exactement
492
+
493
+ df_for_model = df_for_model.reindex(columns=model_features, fill_value=0.0).astype(float)
494
+
495
+
496
+
497
+ # Dernière sécurité : si encore mismatch, tronquer ou ajouter des colonnes fictives
498
+ """
499
+ if df_for_model.shape[1] != expected_n_cols:
500
+ diff = expected_n_cols - df_for_model.shape[1]
501
+ if diff > 0:
502
+ for i in range(diff):
503
+ df_for_model[f"extra_col_{i}"] = 0.0
504
+ elif diff < 0:
505
+ df_for_model = df_for_model.iloc[:, :expected_n_cols]
506
+ """
507
+ # Prédictions
508
+ pred_num_downloads = xgb_predict_safe(
509
+ model_nd,
510
+ df_for_model,
511
+ model_features
512
+ )
513
+
514
+ pred_avg_rating = xgb_predict_safe(
515
+ model_ar,
516
+ df_for_model,
517
+ model_features,
518
+ label_encoder=le_ar
519
+ )
520
+
521
+ #pred_num_downloads = model_nd.predict(df_for_model)[0]
522
+
523
+ #pred_avg_rating_enc = model_ar.predict(df_for_model)[0]
524
+
525
+ #pred_avg_rating = le_ar.inverse_transform([pred_avg_rating_enc])[0]
526
 
527
 
528
 
529
  # Affichage ligne par ligne pour les features après preprocessing
530
+
531
  processed_lines = ["\n=== Features après preprocessing ==="]
532
+
533
  for col in df_processed.columns:
534
+
535
  processed_lines.append(f"{col}: {df_processed[col].iloc[0]}")
536
+
537
  processed_str = "\n".join(processed_lines)
538
+
539
+
540
+
541
  prediction_lines = [
542
+
543
  "\n=== Prédictions ===",
544
+
545
  f"Type détecté : {sound_type}",
546
+
547
  f"📥 Num downloads prédit : {pred_num_downloads}",
548
+
549
  f"⭐ Avg rating prédit : {pred_avg_rating}"
550
+
551
  ]
552
 
553
+
554
+
555
  prediction_str = "\n".join(prediction_lines)
556
 
557
+
558
+
559
  return raw_str + processed_str + prediction_str
560
 
561
 
562
+
563
+
564
  def preprocess_name(df, vec_dim=8):
565
  df = df.copy()
566