🎶 Fiche Modèle : ML-Miay-Midi (Générateur de Mélodies Conditionné par le Texte)
| Catégorie | Valeur |
|---|---|
| Auteur | Clemylia |
| Type de Tâche | Génération de Musique (Séquence de Notes MIDI) |
| Architecture | Réseau Neuronal Récurrent (LSTM) à double entrée |
| Framework | TensorFlow / Keras |
| Langue (Prompt) | Français 🇫🇷 |
💖 Vue d'Ensemble Amicale
Bienvenue dans l'univers de ML-Miay-Midi ! Ce modèle est un petit magicien musical 🪄, entraîné pour transformer de simples descriptions textuelles en de véritables séquences mélodiques MIDI. Que vous ayez besoin d'une mélodie "joyeuse et rapide" ou d'une "ballade triste, mineur, lente", ML-Miay essaiera de vous satisfaire !
Il utilise une architecture spéciale à double entrée qui prend en compte à la fois la séquence de notes précédente et votre prompt textuel pour prédire la note suivante.
🛠️ Configuration Technique & Usage
⚙️ Hyperparamètres Clés
Ces valeurs sont critiques pour interagir correctement avec le modèle :
| Paramètre | Valeur | Description |
|---|---|---|
SEQUENCE_LENGTH |
5 |
Longueur de la fenêtre de notes utilisée pour prédire la note suivante. |
MAX_TEXT_LEN |
5 |
Longueur obligatoire pour le padding du prompt textuel (Input 1). |
NUM_PITCHES |
128 |
Étendue des notes MIDI (0-127). |
📝 Vocabulaire (Lexique Compris)
Le modèle a été entraîné spécifiquement sur les mots clés suivants. Utiliser ces termes maximise les chances d'obtenir une mélodie pertinente ! ✨
| Catégorie | Mots Clés |
|---|---|
| Émotion | joyeuse, triste, douce, forte, mélancolique, optimiste |
| Tempo | rapide, lente |
| Théorie | majeur, mineur, rythme, simple, complexe |
| Genre | rock, pop, jazz, ballade |
| Instrument/Texture | guitare, piano, sombre, lumineuse |
💻 Comment Utiliser ML-Miay
Pour générer une nouvelle mélodie, vous devez fournir deux inputs au modèle :
- Séquence de Notes de Départ (
input_notes) : Une liste de 5 entiers MIDI (ex:[60, 62, 64, 65, 67]). - Prompt Textuel Encodé (
input_text) : Votre description encodée en index (basée sur levocab.txt), obligatoirement paddée à la longueur 5 (selon la correction trouvée 💡).
Exemple d'appel Keras (Python) :
predictions = model.predict({
'input_notes': input_sequence_padded, # Shape (1, 5)
'input_text': text_sequence_padded # Shape (1, 5)
})
🚧 Limites et Bienséance
🚫 Limites Connues
- Monophonie : Ce modèle ne génère qu'une seule ligne mélodique (sans accords ni pistes multiples).
- Contrôle du Rythme : Le modèle prédit la hauteur de la note, la durée est ajoutée manuellement (par défaut $0.25$ ou $0.5$ seconde) lors de la création du fichier MIDI.
- Rigidité de la Forme : L'obligation de padder le texte à la longueur 5 est une contrainte imposée par la sauvegarde du modèle, qui peut parfois tronquer les prompts longs.
⚖️ Licence
Ce modèle est publié sous licence MIT. N'hésitez pas à l'utiliser, le modifier et le partager ! 🌍
Nous espérons que ML-Miay vous apportera beaucoup d'inspiration ! Bon codage et bonne musique ! 🎼👋
Exemple de code d'utilisation :
print("--- 🛠️ Installation des dépendances pour le test ---")
!pip install tensorflow numpy mido huggingface_hub -q
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing.sequence import pad_sequences
import mido
import re
import os
from huggingface_hub import hf_hub_download
from google.colab import files # Pour télécharger le fichier MIDI
REPO_ID = "Clemylia/ML-Miay-midi"
MODEL_FILENAME = "ml_miay_model_final.keras"
OUTPUT_MIDI_FILENAME = "test_hf_melodie_generee.mid"
TEXT_VOCABULAIRE = [
"joyeuse", "triste", "douce", "forte", "rapide", "lente",
"mélancolique", "optimiste", "majeur", "mineur", "rock",
"pop", "jazz", "ballade", "rythme", "simple", "complexe",
"guitare", "piano", "sombre", "lumineuse"
]
TEXT_TO_INDEX = {word: i + 1 for i, word in enumerate(TEXT_VOCABULAIRE)}
SEQUENCE_LENGTH = 5
NUM_PITCHES = 128
MAX_TEXT_LEN_REEL = 5 # Longueur de padding OBLIGATOIRE (pour éviter l'erreur de forme !)
TEMPS_DE_GENERATION = 80 # Nombre de notes à générer
print("Configuration chargée.")
def text_to_bow_sequence(text, vocab_map):
"""Convertit la description en une séquence d'index."""
text = re.sub(r'[^\w\s]', '', text).lower()
tokens = text.split()
indexed_sequence = [vocab_map.get(token, 0) for i, token in enumerate(tokens)]
return [i for i in indexed_sequence if i != 0]
def generate_notes(model, start_sequence, description, seq_length, max_text_len, total_notes, temperature=0.8):
"""Génère une séquence de notes en s'assurant du bon routage des inputs."""
current_sequence = start_sequence[:]
generated_notes = start_sequence[:]
text_indices = text_to_bow_sequence(description, TEXT_TO_INDEX)
if not text_indices:
print("Erreur: Le prompt n'a pas été compris.")
return []
text_input = pad_sequences([text_indices], maxlen=max_text_len, padding='post')
for _ in range(total_notes - seq_length):
input_sequence = np.array(current_sequence[-seq_length:]).reshape(1, seq_length)
# Le Dictionnaire est ESSENTIEL pour garantir l'ordre : {'input_notes': 5, 'input_text': 5}
predictions = model.predict({
'input_notes': input_sequence,
'input_text': text_input
}, verbose=0)[0]
# Échantillonnage Stochastique (plus créatif)
predictions = np.log(predictions) / temperature
exp_preds = np.exp(predictions)
predictions = exp_preds / np.sum(exp_preds)
next_note = np.random.choice(NUM_PITCHES, p=predictions)
current_sequence.append(next_note)
generated_notes.append(next_note)
return generated_notes
def create_midi_file(notes, filename, tempo=100, default_duration=0.5):
"""Crée un fichier MIDI corrigé."""
midi_file = mido.MidiFile(type=1)
track = mido.MidiTrack()
midi_file.tracks.append(track)
track.append(mido.MetaMessage('set_tempo', tempo=mido.bpm2tempo(tempo), time=0))
track.append(mido.Message('program_change', program=0, time=0))
ticks_per_beat = midi_file.ticks_per_beat
tick_duration = int(midi_file.ticks_per_beat * default_duration)
for note_pitch in notes:
track.append(mido.Message('note_on', note=note_pitch, velocity=100, time=0))
track.append(mido.Message('note_off', note=note_pitch, velocity=100, time=tick_duration))
track.append(mido.MetaMessage('end_of_track', time=1))
midi_file.save(filename)
return filename
print(f"\n--- Téléchargement du modèle depuis {REPO_ID} ---")
try
model_path = hf_hub_download(
repo_id=REPO_ID,
filename=MODEL_FILENAME,
repo_type="model"
)
print(f"✅ Modèle téléchargé localement.")
ml_miay_model = tf.keras.models.load_model(model_path)
print("✅ Modèle chargé avec succès. Prêt pour le test!")
except Exception as e:
print(f"❌ ERREUR lors du téléchargement/chargement. Assurez-vous que le nom du dépôt ({REPO_ID}) et du fichier ({MODEL_FILENAME}) sont corrects. Détail : {e}")
exit()
user_prompt = "mélodie joyeuse et rapide de style pop"
start_sequence = [30, 43, 54, 15, 43]
tempo_test = 110
print(f"\n--- Exécution du Test ---")
print(f"Prompt : '{user_prompt}'")
generated_pitches = generate_notes(
ml_miay_model,
start_sequence,
user_prompt,
SEQUENCE_LENGTH,
MAX_TEXT_LEN_REEL,
total_notes=TEMPS_DE_GENERATION
)
if generated_pitches:
# Création du fichier MIDI
final_midi_file = create_midi_file(
generated_pitches,
OUTPUT_MIDI_FILENAME,
tempo=tempo_test,
default_duration=0.25 # Durée courte pour un tempo rapide
)
print("\n--- Résultat ---")
print(f"Mélodie générée ({len(generated_pitches)} notes) : {generated_pitches[:15]}...")
print(f"Fichier MIDI créé : {final_midi_file}")
# Téléchargement automatique
try:
files.download(final_midi_file)
print("✅ Téléchargement du fichier MIDI initié. Vérifiez vos téléchargements.")
except Exception:
print("Impossible de télécharger automatiquement. Vérifiez le dossier local.")
else:
print("\n❌ Échec de la génération.")
- Downloads last month
- 4
