Remplacement modèle classification par genre

This commit is contained in:
2025-12-22 14:29:05 +01:00
parent 90c841310c
commit d67d5ecadd
3 changed files with 29 additions and 21 deletions

1
.gitignore vendored
View File

@@ -95,3 +95,4 @@ htmlcov/
.AppleDouble .AppleDouble
.LSOverride .LSOverride
._* ._*
nul

View File

@@ -1,5 +1,6 @@
"""Music classification using Essentia-TensorFlow models.""" """Music classification using Essentia-TensorFlow models."""
import os import os
import json
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional from typing import Dict, List, Optional
import numpy as np import numpy as np
@@ -28,7 +29,7 @@ class EssentiaClassifier:
# Model URLs (for documentation) # Model URLs (for documentation)
MODEL_URLS = { MODEL_URLS = {
"genre": "https://essentia.upf.edu/models/classification-heads/mtg_jamendo_genre/mtg_jamendo_genre-discogs-effnet-1.pb", "genre": "https://essentia.upf.edu/models/classification-heads/genre_discogs400/genre_discogs400-discogs-effnet-1.pb",
"mood": "https://essentia.upf.edu/models/classification-heads/mtg_jamendo_moodtheme/mtg_jamendo_moodtheme-discogs-effnet-1.pb", "mood": "https://essentia.upf.edu/models/classification-heads/mtg_jamendo_moodtheme/mtg_jamendo_moodtheme-discogs-effnet-1.pb",
"instrument": "https://essentia.upf.edu/models/classification-heads/mtg_jamendo_instrument/mtg_jamendo_instrument-discogs-effnet-1.pb", "instrument": "https://essentia.upf.edu/models/classification-heads/mtg_jamendo_instrument/mtg_jamendo_instrument-discogs-effnet-1.pb",
} }
@@ -68,7 +69,7 @@ class EssentiaClassifier:
# Model file names for classification heads # Model file names for classification heads
model_files = { model_files = {
"genre": "mtg_jamendo_genre-discogs-effnet-1.pb", "genre": "genre_discogs400-discogs-effnet-1.pb",
"mood": "mtg_jamendo_moodtheme-discogs-effnet-1.pb", "mood": "mtg_jamendo_moodtheme-discogs-effnet-1.pb",
"instrument": "mtg_jamendo_instrument-discogs-effnet-1.pb", "instrument": "mtg_jamendo_instrument-discogs-effnet-1.pb",
} }
@@ -90,21 +91,20 @@ class EssentiaClassifier:
def _load_class_labels(self) -> None: def _load_class_labels(self) -> None:
"""Load class labels for models.""" """Load class labels for models."""
# These are the actual class labels from MTG-Jamendo dataset # Load genre labels from Discogs400 JSON file
# In production, these should be loaded from JSON files genre_json_path = self.models_path / "genre_discogs400-discogs-effnet-1.json"
if genre_json_path.exists():
self.class_labels["genre"] = [ try:
"rock", "pop", "alternative", "indie", "electronic", with open(genre_json_path, 'r', encoding='utf-8') as f:
"female vocalists", "dance", "00s", "alternative rock", "jazz", genre_metadata = json.load(f)
"beautiful", "metal", "chillout", "male vocalists", "classic rock", self.class_labels["genre"] = genre_metadata.get("classes", [])
"soul", "indie rock", "Mellow", "electronica", "80s", logger.info(f"Loaded {len(self.class_labels['genre'])} genre labels from JSON")
"folk", "90s", "chill", "instrumental", "punk", except Exception as e:
"oldies", "blues", "hard rock", "ambient", "acoustic", logger.error(f"Failed to load genre labels from JSON: {e}")
"experimental", "female vocalist", "guitar", "Hip-Hop", "70s", self.class_labels["genre"] = []
"party", "country", "easy listening", "sexy", "catchy", else:
"funk", "electro", "heavy metal", "Progressive rock", "60s", logger.warning(f"Genre labels JSON not found: {genre_json_path}")
"rnb", "indie pop", "sad", "House", "happy" self.class_labels["genre"] = []
]
self.class_labels["mood"] = [ self.class_labels["mood"] = [
"action", "adventure", "advertising", "background", "ballad", "action", "adventure", "advertising", "background", "ballad",
@@ -159,10 +159,11 @@ class EssentiaClassifier:
embeddings_mean = np.mean(embeddings, axis=0) embeddings_mean = np.mean(embeddings, axis=0)
# Step 2: Feed embeddings to classification head # Step 2: Feed embeddings to classification head
# Discogs400 uses different node names than MTG-Jamendo
classifier = TensorflowPredict2D( classifier = TensorflowPredict2D(
graphFilename=self.models["genre"], graphFilename=self.models["genre"],
input="model/Placeholder", input="serving_default_model_Placeholder",
output="model/Sigmoid" output="PartitionedCall:0"
) )
predictions = classifier(embeddings_mean.reshape(1, -1)) predictions = classifier(embeddings_mean.reshape(1, -1))
predictions = predictions[0] # Remove batch dimension predictions = predictions[0] # Remove batch dimension

View File

@@ -47,9 +47,15 @@ download_model "discogs-effnet-bs64-1.pb" \
# Download classification heads # Download classification heads
echo "" echo ""
echo "Downloading classification heads..." echo "Downloading classification heads..."
download_model "mtg_jamendo_genre-discogs-effnet-1.pb" \
"$CLASS_HEADS_URL/mtg_jamendo_genre/mtg_jamendo_genre-discogs-effnet-1.pb"
# Genre: Discogs400 (professional taxonomy with 400 genres)
download_model "genre_discogs400-discogs-effnet-1.pb" \
"$CLASS_HEADS_URL/genre_discogs400/genre_discogs400-discogs-effnet-1.pb"
download_model "genre_discogs400-discogs-effnet-1.json" \
"$CLASS_HEADS_URL/genre_discogs400/genre_discogs400-discogs-effnet-1.json"
# Mood & Instrument: MTG-Jamendo
download_model "mtg_jamendo_moodtheme-discogs-effnet-1.pb" \ download_model "mtg_jamendo_moodtheme-discogs-effnet-1.pb" \
"$CLASS_HEADS_URL/mtg_jamendo_moodtheme/mtg_jamendo_moodtheme-discogs-effnet-1.pb" "$CLASS_HEADS_URL/mtg_jamendo_moodtheme/mtg_jamendo_moodtheme-discogs-effnet-1.pb"