# Audio-Course

## Docs

- [Finetuner un modèle de classification musicale](https://huggingface.co/learn/audio-course/fr/chapter4/fine-tuning.md)
- [Modèles et jeux de données pré-entraînés pour la classification d’audio](https://huggingface.co/learn/audio-course/fr/chapter4/classification_models.md)
- [Exercice pratique](https://huggingface.co/learn/audio-course/fr/chapter4/hands_on.md)
- [Unité 4 : Construire un classifieur de genres musicaux](https://huggingface.co/learn/audio-course/fr/chapter4/introduction.md)
- [Construire une démo avec Gradio](https://huggingface.co/learn/audio-course/fr/chapter4/demo.md)
- [Comment finetuner un système de reconnaissance automatique de la parole avec l'API Trainer](https://huggingface.co/learn/audio-course/fr/chapter5/fine-tuning.md)
- [Exercice pratique](https://huggingface.co/learn/audio-course/fr/chapter5/hands_on.md)
- [Ce que vous allez apprendre et construire](https://huggingface.co/learn/audio-course/fr/chapter5/introduction.md)
- [Construire une démo avec Gradio](https://huggingface.co/learn/audio-course/fr/chapter5/demo.md)
- [Lectures et ressources complémentaires](https://huggingface.co/learn/audio-course/fr/chapter5/supplemental_reading.md)
- [Modèles pré-entraînés pour la reconnaissance automatique de la parole](https://huggingface.co/learn/audio-course/fr/chapter5/asr_models.md)
- [Choisir un jeu de données](https://huggingface.co/learn/audio-course/fr/chapter5/choosing_dataset.md)
- [Évaluation et métriques pour la reconnaissance automatique de la parole](https://huggingface.co/learn/audio-course/fr/chapter5/evaluation.md)
- [Se préparer à suivre le cours](https://huggingface.co/learn/audio-course/fr/chapter0/get_ready.md)
- [Bienvenue dans le cours d'audio d'Hugging Face !](https://huggingface.co/learn/audio-course/fr/chapter0/introduction.md)
- [Rejoignez la communauté !](https://huggingface.co/learn/audio-course/fr/chapter0/community.md)
- [Sessions en direct et ateliers](https://huggingface.co/learn/audio-course/fr/events/introduction.md)
- [Classification audio avec un pipeline](https://huggingface.co/learn/audio-course/fr/chapter2/audio_classification_pipeline.md)
- [Reconnaissance automatique de la parole avec pipeline](https://huggingface.co/learn/audio-course/fr/chapter2/asr_pipeline.md)
- [Exercice pratique](https://huggingface.co/learn/audio-course/fr/chapter2/hands_on.md)
- [Unité 2 : Une introduction en douceur aux applications audio](https://huggingface.co/learn/audio-course/fr/chapter2/introduction.md)
- [Finetuning du SpeechT5](https://huggingface.co/learn/audio-course/fr/chapter6/fine-tuning.md)
- [Exercice pratique](https://huggingface.co/learn/audio-course/fr/chapter6/hands_on.md)
- [Jeux de données de synthèse vocale](https://huggingface.co/learn/audio-course/fr/chapter6/tts_datasets.md)
- [Unité 6 : Du texte à la parole](https://huggingface.co/learn/audio-course/fr/chapter6/introduction.md)
- [Lectures et ressources complémentaires](https://huggingface.co/learn/audio-course/fr/chapter6/supplemental_reading.md)
- [Modèles pré-entraînés pour la synthèse vocale](https://huggingface.co/learn/audio-course/fr/chapter6/pre-trained_models.md)
- [Évaluation des modèles de synthèse vocale](https://huggingface.co/learn/audio-course/fr/chapter6/evaluation.md)
- [Traduction parole-à-parole](https://huggingface.co/learn/audio-course/fr/chapter7/speech-to-speech.md)
- [Exercice pratique](https://huggingface.co/learn/audio-course/fr/chapter7/hands-on.md)
- [Transcrire une réunion](https://huggingface.co/learn/audio-course/fr/chapter7/transcribe-meeting.md)
- [Unité 7. Rassemblement de tous les éléments](https://huggingface.co/learn/audio-course/fr/chapter7/introduction.md)
- [Créer un assistant vocal](https://huggingface.co/learn/audio-course/fr/chapter7/voice-assistant.md)
- [Lectures et ressources complémentaires](https://huggingface.co/learn/audio-course/fr/chapter7/supplemental_reading.md)
- [Architectures Seq2Seq](https://huggingface.co/learn/audio-course/fr/chapter3/seq2seq.md)
- [Unité 3 : Architectures de transformers pour l'audio](https://huggingface.co/learn/audio-course/fr/chapter3/introduction.md)
- [Lectures et ressources supplémentaires](https://huggingface.co/learn/audio-course/fr/chapter3/supplemental_reading.md)
- [Architectures avec CTC](https://huggingface.co/learn/audio-course/fr/chapter3/ctc.md)
- [Architectures de classification d’audio](https://huggingface.co/learn/audio-course/fr/chapter3/classification.md)
- [Introduction aux données audio](https://huggingface.co/learn/audio-course/fr/chapter1/audio_data.md)
- [Streaming de données audio](https://huggingface.co/learn/audio-course/fr/chapter1/streaming.md)
- [Prétraitement d'un jeu de données audio](https://huggingface.co/learn/audio-course/fr/chapter1/preprocessing.md)
- [Unité 1 : Travailler avec des données audio](https://huggingface.co/learn/audio-course/fr/chapter1/introduction.md)
- [Charger et explorer un jeu de données audio](https://huggingface.co/learn/audio-course/fr/chapter1/load_and_explore.md)
- [En apprendre encore plus](https://huggingface.co/learn/audio-course/fr/chapter1/supplemental_reading.md)
- [Vérifier votre compréhension de l'unité](https://huggingface.co/learn/audio-course/fr/chapter1/quiz.md)

### Finetuner un modèle de classification musicale
https://huggingface.co/learn/audio-course/fr/chapter4/fine-tuning.md

# Finetuner un modèle de classification musicale

Dans cette section, nous présenterons un guide étape par étape sur le *finetuning* d'un *transformer* encodeur pour la classification de la musique.
Nous utiliserons un modèle léger pour cette démonstration et un jeu de données assez petit, ce qui signifie que le code est exécutable de bout en bout sur n'importe quel GPU grand public, y compris le GPU T4 16GB fourni gratuitement par Google Colab. La section comprend divers conseils que vous pouvez essayer si vous avez un GPU plus petit et rencontrez des problèmes de mémoire en cours de route.

## Le de données

Pour entraîner notre modèle, nous utiliserons le jeu de données [GTZAN](https://huggingface.co/datasets/marsyas/gtzan), qui est un jeu de données populaire de 1 000 chansons pour la classification des genres musicaux. Chaque chanson dure 30 secondes et fait partie de l'un des 10 genres de musique disponible, allant du disco au métal. Nous pouvons obtenir les fichiers audio et leurs étiquettes correspondantes à partir du *Hub* avec la fonction `load_dataset()`  de 🤗 *Datasets* :

```python
from datasets import load_dataset

gtzan = load_dataset("marsyas/gtzan", "all")
gtzan
``` 

**Sortie :**

```out
Dataset({
    features: ['file', 'audio', 'genre'],
    num_rows: 999
})
``` 

L'un des enregistrements dans GTZAN est corrompu, il a donc été supprimé du jeu de données. C'est pourquoi nous avons 999 exemples au lieu de 1 000.

GTZAN ne fournit pas de jeu de validation prédéfini, nous devrons donc en créer un nous-mêmes. Le jeu de données est équilibré entre les genres, nous pouvons donc utiliser la méthode `train_test_split()` pour créer rapidement une répartition 90/10 comme suit :

```python
gtzan = gtzan["train"].train_test_split(seed=42, shuffle=True, test_size=0.1)
gtzan
``` 

**Sortie :**

```out
DatasetDict({
    train: Dataset({
        features: ['file', 'audio', 'genre'],
        num_rows: 899
    })
    test: Dataset({
        features: ['file', 'audio', 'genre'],
        num_rows: 100
    })
})
``` 

Maintenant que nous avons nos jeux d’entraînement et de validation, jetons un coup d'œil à l'un des fichiers audio :

```python
gtzan["train"][0]
``` 

**Sortie :**

```out
{
    "file": "~/.cache/huggingface/datasets/downloads/extracted/fa06ce46130d3467683100aca945d6deafb642315765a784456e1d81c94715a8/genres/pop/pop.00098.wav",
    "audio": {
        "path": "~/.cache/huggingface/datasets/downloads/extracted/fa06ce46130d3467683100aca945d6deafb642315765a784456e1d81c94715a8/genres/pop/pop.00098.wav",
        "array": array(
            [
                0.10720825,
                0.16122437,
                0.28585815,
                ...,
                -0.22924805,
                -0.20629883,
                -0.11334229,
            ],
            dtype=float32,
        ),
        "sampling_rate": 22050,
    },
    "genre": 7,
}
``` 

Comme nous l'avons vu dans [Unité 1](.. /chapter1/audio_data), les fichiers audio sont représentés sous forme de tableaux NumPy à 1 dimension, où la valeur du tableau représente l'amplitude à ce pas de temps. Pour ces chansons, la fréquence d'échantillonnage est de 22 050 Hz, ce qui signifie qu'il y a 22 050 valeurs d'amplitude échantillonnées par seconde. Nous devrons garder cela à l'esprit lorsque nous utiliserons un modèle pré-entraîné avec un taux d'échantillonnage différent, en convertissant nous-mêmes les taux d'échantillonnage pour nous assurer qu'ils correspondent. Nous pouvons également voir que le genre est représenté sous la forme d'un entier, ou _class label_, qui est le format dans lequel le modèle fera ses prédictions. Utilisons la méthode `int2str()` de la caractéristique `genre` pour associer ces entiers à des noms lisibles par l'homme :

```python
id2label_fn = gtzan["train"].features["genre"].int2str
id2label_fn(gtzan["train"][0]["genre"])
``` 

**Sortie :**

```out
'pop'
```

Cette étiquette semble correcte, car elle correspond au nom de fichier du fichier audio. Écoutons maintenant quelques exemples supplémentaires en utilisant Gradio pour créer une interface simple avec l'API `Blocks` :

```python
def generate_audio():
    example = gtzan["train"].shuffle()[0]
    audio = example["audio"]
    return (
        audio["sampling_rate"],
        audio["array"],
    ), id2label_fn(example["genre"])

with gr.Blocks() as demo:
    with gr.Column():
        for _ in range(4):
            audio, label = generate_audio()
            output = gr.Audio(audio, label=label)

demo.launch(debug=True)
```

À partir de ces échantillons, nous pouvons certainement entendre la différence entre les genres, mais un *transformer* peut-il le faire aussi ? Entraînons un modèle pour le découvrir ! Tout d'abord, nous devrons trouver un modèle pré-entraîné approprié pour cette tâche. Voyons comment nous pouvons le faire.

## Choisir un modèle pré-entraîné pour la classification audio

Pour commencer, choisissons un modèle pré-entraîné approprié pour la classification audio. Dans ce domaine, le pré-entraînement est généralement effectuée sur de grandes quantités de données audio non étiquetées, en utilisant des jeux de données tels que [LibriSpeech](https://huggingface.co/datasets/librispeech_asr) et [Voxpopuli](https://huggingface.co/datasets/facebook/voxpopuli). La meilleure façon de trouver ces modèles sur le *Hub* est d'utiliser le filtre « classification audio », comme décrit dans la section précédente. Bien que des modèles comme Wav2Vec2 et HuBERT soient très populaires, nous utiliserons un modèle appelé _DistilHuBERT_. Il s'agit d'une version beaucoup plus petite (ou distillée) du modèle [HuBERT](https://huggingface.co/docs/transentraîners/model_doc/hubert), qui s’entraîne environ 73% plus vite, tout en préservant la plupart des performances.

## De l'audio aux caractéristiques d'apprentissage automatique

## Prétraitement des données

À l'instar de la tokenisation en NLP, les modèles audio et vocaux nécessitent que l'entrée soit encodée dans un format que le modèle peut traiter. Dans 🤗 *Transformers*, la conversion de l'audio au format d'entrée est gérée par l’extracteur de caractéristique du modèle. 🤗 *Transformers* fournit une classe pratique `AutoFeatureExtractor` qui peut sélectionner automatiquement le bon extracteur de caractéristiques pour un modèle donné. Pour voir comment nous pouvons traiter nos fichiers audio, commençons par instancier l'extracteur de caractéristiques pour DistilHuBERT à partir du *checkpoint* pré-entraîné :

```python
from transformers import AutoFeatureExtractor

model_id = "ntu-spml/distilhubert"
feature_extractor = AutoFeatureExtractor.from_pretrained(
    model_id, do_normalize=True, return_attention_mask=True
)
``` 

Comme le taux d'échantillonnage du modèle et de le jeu de données est différent, nous devons rééchantillonner le fichier audio à 16 000 Hz avant de le transmettre à l'extracteur de caractéristiques. Nous pouvons le faire en obtenant d'abord la fréquence d'échantillonnage du modèle à partir de l'extracteur de caractéristiques :

```python
sampling_rate = feature_extractor.sampling_rate
sampling_rate
```

**Sortie :**

```out
16000
``` 

Ensuite, nous rééchantillonnons le jeu de données à l'aide de la méthode `cast_column()` et de la fonction `Audio`  de 🤗 *Datasets* :

```python
from datasets import Audio

gtzan = gtzan.cast_column("audio", Audio(sampling_rate=sampling_rate))
``` 

Nous pouvons maintenant vérifier le premier échantillon de l’échantillon d’entraînement de notre jeu de données pour vérifier qu'il est bien à 16 000 Hz. 🤗 *Datasets* rééchantillonnent le fichier audio *à la volée* lorsque nous chargeons chaque échantillon audio :

```python
gtzan["train"][0]
``` 

**Sortie :**

```out
{
    "file": "~/.cache/huggingface/datasets/downloads/extracted/fa06ce46130d3467683100aca945d6deafb642315765a784456e1d81c94715a8/genres/pop/pop.00098.wav",
    "audio": {
        "path": "~/.cache/huggingface/datasets/downloads/extracted/fa06ce46130d3467683100aca945d6deafb642315765a784456e1d81c94715a8/genres/pop/pop.00098.wav",
        "array": array(
            [
                0.0873509,
                0.20183384,
                0.4790867,
                ...,
                -0.18743178,
                -0.23294401,
                -0.13517427,
            ],
            dtype=float32,
        ),
        "sampling_rate": 16000,
    },
    "genre": 7,
}
``` 

Bien. Nous pouvons voir que le taux d'échantillonnage a été sous-échantillonné à 16kHz. Les valeurs de tableau sont également différentes car nous n'avons maintenant qu'environ une valeur d'amplitude pour chaque 1,5 pas que nous avions auparavant.
Une caractéristique de conception des modèles de type Wav2Vec2 et HuBERT est qu'ils acceptent un tableau de flottants correspondant à la forme d'onde brute du signal vocal comme entrée. Cela contraste avec d'autres modèles, comme Whisper, où nous prétraitons la forme d'onde audio brute au format spectrogramme.
Nous avons mentionné que les données audio sont représentées comme un tableau à 1 dimension, elles sont donc déjà dans le bon format pour être lues par le modèle (un ensemble d'entrées continues à pas de temps discrets). Alors, que fait exactement l'extracteur de caractéristiques ?
Eh bien, les données audio sont dans le bon format, mais nous n'avons imposé aucune restriction sur les valeurs qu'elles peuvent prendre. Pour que notre modèle fonctionne de manière optimale, nous voulons conserver toutes les entrées dans la même plage dynamique. Cela va nous assurer d'obtenir une plage similaire d'activations et de gradients pour nos échantillons, ce qui nous aidera à la stabilité et à la convergence pendant l'entraînement.
Pour ce faire, nous *normalisons* nos données audio, en redimensionnant chaque échantillon à une moyenne nulle et une variance unitaire pour avoir des variables centrées réduites. C'est exactement cette normalisation des caractéristiques que notre extracteur de caractéristiques effectue.
Nous pouvons jeter un coup d'œil à l'extracteur de caractéristiques en fonctionnement en l'appliquant à notre premier échantillon audio. Tout d'abord, calculons la moyenne et la variance de nos données audio brutes :

```python
import numpy as np

sample = gtzan["train"][0]["audio"]

print(f"Mean: {np.mean(sample['array']):.3}, Variance: {np.var(sample['array']):.3}")
```

**Sortie :**

```out
Mean: 0.000185, Variance: 0.0493
``` 

Nous pouvons voir que la moyenne est déjà proche de 0, mais la variance est plus proche de 0,05. Si la variance de l'échantillon était plus grande, cela pourrait causer des problèmes à notre modèle, car la plage dynamique des données audio serait très petite et donc difficile à séparer. Appliquons l'extracteur de caractéristiques et voyons à quoi ressemblent les sorties:

```python
inputs = feature_extractor(sample["array"], sampling_rate=sample["sampling_rate"])

print(f"inputs keys: {list(inputs.keys())}")

print(
    f"Mean: {np.mean(inputs['input_values']):.3}, Variance: {np.var(inputs['input_values']):.3}"
)
``` 

**Sortie :**

```out
inputs keys: ['input_values', 'attention_mask']
Mean: -4.53e-09, Variance: 1.0
``` 

Notre extracteur de caractéristiques renvoie un dictionnaire de deux tableaux : `input_values` et `attention_mask`. Les `input_values` sont les entrées audio prétraitées que nous passerons au modèle HuBERT. L’[`attention_mask`](https://huggingface.co/docs/transentraîners/glossary#attention-mask) est utilisé lorsque nous traitons un _batch_ d'entrées audio à la fois. Il est utilisé pour indiquer au modèle où nous avons des entrées rembourrées de différentes longueurs.
Nous pouvons voir que la valeur moyenne est maintenant beaucoup plus proche de 0, et la variance est à 1 ! C'est exactement la forme sous laquelle nous voulons que nos échantillons audio soient avant de les passer dans notre HuBERT.

Notez comment nous avons transmis le taux d'échantillonnage de nos données audio à notre extracteur de caractéristiques. Il s'agit d'une bonne pratique, car l'extracteur de caractéristiques effectue une vérification sous le capot pour s'assurer que le taux d'échantillonnage de nos données audio correspond au taux d'échantillonnage attendu par le modèle. Si le taux d'échantillonnage de nos données audio ne correspondait pas au taux d'échantillonnage de notre modèle, nous aurions besoin de suréchantillonner ou de sous-échantillonner les données audio au taux d'échantillonnage correct.

Alors maintenant que nous savons comment traiter nos fichiers audio rééchantillonnés, la dernière chose à faire est de définir une fonction que nous pouvons appliquer à tous les exemples du jeu de données. Étant donné que nous nous attendons à des échantillons de 30 secondes, nous tronquerons aussi les échantillons plus longs en utilisant les arguments `max_length` et `truncation` de l'extracteur de caractéristiques comme suit :

```python
max_duration = 30.0

def preprocess_function(examples):
    audio_arrays = [x["array"] for x in examples["audio"]]
    inputs = feature_extractor(
        audio_arrays,
        sampling_rate=feature_extractor.sampling_rate,
        max_length=int(feature_extractor.sampling_rate * max_duration),
        truncation=True,
        return_attention_mask=True,
    )
    return inputs
```

Une fois cette fonction définie, nous pouvons maintenant l'appliquer au jeu de données à l'aide de la méthode `map()`.

```python
gtzan_encoded = gtzan.map(
    preprocess_function, remove_columns=["audio", "file"], batched=True, num_proc=1
)
gtzan_encoded
```

**Sortie :**

```out
DatasetDict({
    train: Dataset({
        features: ['genre', 'input_values'],
        num_rows: 899
    })
    test: Dataset({
        features: ['genre', 'input_values'],
        num_rows: 100
    })
})
```

Pour simplifier l’entraînement, nous avons supprimé les colonnes `audio` et `file` du jeu de données. La colonne `input_values` contient les fichiers audio encodés, la colonne `attention_mask` est un masque binaire de valeurs 0/1 qui indique où nous avons rempli l'entrée audio, et la colonne `genre` contient les étiquettes (ou cibles) correspondantes. Pour permettre au `Trainer` de traiter les étiquettes de classe, nous devons renommer la colonne `genre` en `label` :

```python
gtzan_encoded = gtzan_encoded.rename_column("genre", "label")
```

Enfin, nous devons obtenir les associations d'étiquettes à partir du jeu de données. L’association nous mènera des identifiants entiers (par exemple `7`) aux étiquettes de classe lisibles par l'homme (par exemple `pop`) et inversement. Ce faisant, nous pouvons convertir la prédiction de notre modèle dans un format lisible par l'homme, ce qui nous permet d'utiliser le modèle dans n'importe quelle application en aval. Nous pouvons le faire en utilisant la méthode `int2str()` comme suit:

```python
id2label = {
    str(i): id2label_fn(i)
    for i in range(len(gtzan_encoded["train"].features["label"].names))
}
label2id = {v: k for k, v in id2label.items()}

id2label["7"]
```

**Sortie :**

```out
'pop'
```

Nous avons maintenant un jeu de données prêt pour l’entraînement. Voyons comment nous pouvons entraîner un modèle sur ce jeu de données.

## Finetuner le modèle

Pour affiner le modèle, nous utiliserons la classe 'Trainer' de 🤗 *Transformers*. Comme nous l'avons vu dans d'autres chapitres, le « Trainer » est une API de haut niveau conçue pour gérer les scénarios de formation les plus courants. Dans ce cas, nous utiliserons le 'Trainer' pour affiner le modèle sur GTZAN. Pour ce faire, nous devons d'abord charger un modèle pour cette tâche. Nous pouvons le faire en utilisant la classe 'AutoModelForAudioClassification', qui ajoutera automatiquement la tête de classification appropriée à notre modèle DistilHuBERT préentraîné. Allons de l'avant et instancions le modèle :

'''python
from transformers import AutoModelForAudioClassification

num_labels = len(id2label)

modèle = AutoModelForAudioClassification.from_pretrained(
    model_id,
    num_labels=num_labels,
    label2id=label2id,
    id2label=id2label,
)
```

Nous vous conseillons fortement de télécharger les *checkpoints* du modèle directement sur le [*Hub*](https://huggingface.co/) pendant l'entraînement.
Le *Hub* fournit :
- Un contrôle de version intégré : vous pouvez être sûr qu'aucun *checkpoint* du modèle n'est perdu pendant l’entraînement.
- Tensorboard : suivez les métriques importantes au cours de l’entraînement.
- La carte du modèle : documentant ce que fait un modèle et ses cas d'utilisation prévus.
- Communauté : un moyen facile de partager et de collaborer avec la communauté ! 
Lier le *notebook* au *Hub* est simple. Il suffit d'entrer votre *token* d'authentification au *Hub* lorsque vous y êtes invité.
Vous pouvez trouver votre *token* d'authentification [ici](https://huggingface.co/settings/tokens) et le saisir dans

```python
from huggingface_hub import notebook_login

notebook_login()
```

**Sortie :**

```bash
Login successful
Your token has been saved to /root/.huggingface/token
```

L'étape suivante consiste à définir les arguments d'apprentissage, y compris la taille du batch, les étapes d'accumulation du gradient, le nombre d'époques d'apprentissage et le taux d'apprentissage :

```python
from transformers import TrainingArguments

model_name = model_id.split("/")[-1]
batch_size = 8
gradient_accumulation_steps = 1
num_train_epochs = 10

training_args = TrainingArguments(
    f"{model_name}-finetuned-gtzan",
    evaluation_strategy="epoch",
    save_strategy="epoch",
    learning_rate=5e-5,
    per_device_train_batch_size=batch_size,
    gradient_accumulation_steps=gradient_accumulation_steps,
    per_device_eval_batch_size=batch_size,
    num_train_epochs=num_train_epochs,
    warmup_steps=100,
    logging_steps=5,
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
    fp16=True,
    push_to_hub=True,
)
```

Ici, nous avons défini `push_to_hub=True` pour activer le téléchargement automatique de nos *checkpoints* *finetunés* pendant l'entraînement. Si vous ne souhaitez pas que vos *checkpoints*  soient téléchargés sur le *Hub*, vous pouvez définir cette option sur `False`.

La dernière chose que nous devons faire est de définir les métriques. Étant donné que le jeu de données est équilibré, nous utiliserons la précision comme métrique et le chargerons à l'aide de la bibliothèque 🤗 *Evaluate* :

```python
import evaluate

metric = evaluate.load("accuracy")

def compute_metrics(eval_pred):
    """Computes accuracy on a batch of predictions"""
    predictions = np.argmax(eval_pred.predictions, axis=1)
    return metric.compute(predictions=predictions, references=eval_pred.label_ids)
``` 

Nous avons maintenant toutes les pièces ! Instancions le `Trainer` et entraînons le modèle :

```python
from transformers import Trainer

trainer = Trainer(
    model,
    training_args,
    train_dataset=gtzan_encoded["train"],
    eval_dataset=gtzan_encoded["test"],
    tokenizer=feature_extractor,
    compute_metrics=compute_metrics,
)

trainer.train()
``` 

Selon votre GPU, il est possible que vous rencontriez une erreur CUDA `"out-of-memory"` lorsque vous commencez à vous entraîner.
Dans ce cas, vous pouvez réduire la taille du batch de manière incrémentielle par des facteurs de 2 et utiliser ['gradient_accumulation_steps'](https://huggingface.co/docs/transentraîners/main_classes/trainer#transentraîners.TrainingArguments.gradient_accumulation_steps) pour compenser.

**Sortie :**

```out
| Training Loss | Epoch | Step | Validation Loss | Accuracy |
|:-------------:|:-----:|:----:|:---------------:|:--------:|
| 1.7297        | 1.0   | 113  | 1.8011          | 0.44     |
| 1.24          | 2.0   | 226  | 1.3045          | 0.64     |
| 0.9805        | 3.0   | 339  | 0.9888          | 0.7      |
| 0.6853        | 4.0   | 452  | 0.7508          | 0.79     |
| 0.4502        | 5.0   | 565  | 0.6224          | 0.81     |
| 0.3015        | 6.0   | 678  | 0.5411          | 0.83     |
| 0.2244        | 7.0   | 791  | 0.6293          | 0.78     |
| 0.3108        | 8.0   | 904  | 0.5857          | 0.81     |
| 0.1644        | 9.0   | 1017 | 0.5355          | 0.83     |
| 0.1198        | 10.0  | 1130 | 0.5716          | 0.82     |
``` 

L’entraînement durera environ 1 heure en fonction de votre GPU ou de celui alloué par Google Colab. Notre meilleure précision d'évaluation est de 83%. Pas mal pour seulement 10 époques avec 899 exemples d'entraînement ! Nous pourrions certainement améliorer ce résultat en entraînant sur plus d'époques, en utilisant des techniques de régularisation telles que le *dropout*, ou en découpant chaque segment d’audio de 30s en segments de 15s pour utiliser une stratégie de prétraitement de données plus efficace.
La grande question est de savoir comment ce système se compare à d'autres systèmes de classification de musique 🤔
Pour cela, nous pouvons afficher le [classement *autoevaluate*](https://huggingface.co/spaces/autoevaluate/leaderboards?dataset=marsyas%2Fgtzan&only_verified=0&task=audio-classification&config=all&split=train&metric=accuracy), un classement qui catégorise les modèles par langue et jeu de données, puis les classe en fonction de leur précision.
Nous pouvons automatiquement soumettre notre *checkpoint* au classement lorsque nous transmettons les résultats de l'entraînement au *Hub*. Nous devons simplement définir les arguments appropriés (kwargs). Vous pouvez modifier ces valeurs pour qu'elles correspondent à votre jeu de données, à votre langue et au nom de votre modèle en conséquence :

```python
kwargs = {
    "dataset_tags": "marsyas/gtzan",
    "dataset": "GTZAN",
    "model_name": f"{model_name}-finetuned-gtzan",
    "finetuned_from": model_id,
    "tasks": "audio-classification",
}
``` 

Les résultats de l’entraînement peuvent maintenant être téléchargés sur le *Hub*. Pour ce faire, exécutez la commande `.push_to_hub` :

```python
trainer.push_to_hub(**kwargs)
```

Cela enregistrera les logs d'entraînement et les poids du modèle sous `"your-username/distilhubert-finetuned-gtzan"`. Pour cet exemple, consultez [`"sanchit-gandhi/distilhubert-finetuned-gtzan"`](https://huggingface.co/sanchit-gandhi/distilhubert-finetuned-gtzan).

## Partager le modèle

Vous pouvez désormais partager votre modèle avec n'importe qui en utilisant le lien sur le *Hub*. Il sera utilisable avec l'identifiant `"your-username/distilhubert-finetuned-gtzan"` directement dans la classe `pipeline()`. Par exemple, pour charger le *checkpoint* *finetuné* ['"sanchit-gandhi/distilhubert-finetuned-gtzan"'](https://huggingface.co/sanchit-gandhi/distilhubert-finetuned-gtzan):

```python
from transformers import pipeline

pipe = pipeline(
    "audio-classification", model="sanchit-gandhi/distilhubert-finetuned-gtzan"
)
```

## Conclusion

Dans cette section, nous avons couvert un guide étape par étape pour *finetuner* le modèle DistilHuBERT pour la tâche de classification de la musique. Bien que nous nous soyons concentrés sur cette tâche et le jeu de données GTZAN, les étapes présentées ici s'appliquent plus généralement à toute tâche de classification audio. Le même script peut être utilisé pour les tâches de détection de mots-clés ou l'identification de la langue. Il vous suffit de changer le jeu de données avec celui de votre tâche d'intérêt ! Si vous souhaitez *finetuner* d'autres modèles du *Hub* pour la classification d’audio, nous vous encourageons à consulter les [exemples](https://github.com/huggingface/transformers/tree/main/examples/pytorch/audio-classification) trouvables sur le dépôt 🤗 *Transformers*.
Dans la section suivante, nous prendrons le modèle que nous venons de *finetuner* et construirons une démo avec *Gradio* que nous pourrons partager sur le Hub.

### Modèles et jeux de données pré-entraînés pour la classification d’audio
https://huggingface.co/learn/audio-course/fr/chapter4/classification_models.md

# Modèles et jeux de données pré-entraînés pour la classification d’audio

Le *Hub* abrite [plusieurs centaines de modèles pré-entraînés pour la classification d’audio](https://huggingface.co/models?pipeline_tag=audio-classification). Dans cette section, nous passerons en revue certaines des tâches de classification d’audio les plus courantes et suggérerons des modèles pré-entraînés appropriés pour chacune. En utilisant la classe `pipeline()`, la commutation entre les modèles et les tâches est simple : une fois que vous savez comment utiliser `pipeline()` pour un modèle, vous pourrez l'utiliser pour n'importe quel modèle sur le *Hub*, sans modification du code ! Cela rend l'expérimentation de la classe `pipeline()` extrêmement rapide, ce qui vous permet de sélectionner rapidement le meilleur modèle pré-entraîné pour vos besoins.
Avant de passer aux différents problèmes de classification d’audio, récapitulons rapidement les architectures de *transformers* généralement utilisées. L'architecture standard de classification d’audio est motivée par la nature de la tâche. Nous voulons transformer une séquence d'entrées audio (c'est-à-dire notre réseau audio d'entrée) en une prédiction d'étiquette de classe unique. Les modèles d'encodeur associent d'abord la séquence audio d'entrée dans une séquence de représentations à l'état caché en faisant passer les entrées à travers un bloc *transformer*. La séquence de représentations d'états masqués est ensuite associée à une sortie d'étiquette de classe en prenant la moyenne sur les états masqués et en faisant passer le vecteur résultant à travers une couche de classification linéaire. Par conséquent, il y a une préférence pour les modèles *encodeur* pour la classification d’audio.
Les modèles de décodeur introduisent une complexité inutile à la tâche car ils supposent que les sorties peuvent également être une *séquence* de prédictions (plutôt qu'une prédiction d'étiquette de classe unique), et génèrent ainsi plusieurs sorties. Par conséquent, ils ont une vitesse d'inférence plus lente et ont tendance à ne pas être utilisés. Les modèles encodeur-décodeur sont largement omis pour la même raison. Ces choix d'architecture sont analogues à ceux de NLP, où les modèles d'encodeur tels que BERT sont privilégiés pour les tâches de classification de séquences, et les modèles de décodeur tels que GPT réservés aux tâches de génération de séquences.
Maintenant que nous avons récapitulé l'architecture du *transformer* standard pour la classification d’audio, passons aux différents sous-ensembles de la classification d’audio et couvrons les modèles les plus populaires !

## 🤗 Installation de Transformers

Au moment de la rédaction de cette section, les dernières mises à jour requises pour le pipeline de classification d’audio se trouvent uniquement sur la version « principale » du dépôt 🤗 Transformers, plutôt que sur la dernière version de PyPi. Pour nous assurer que nous avons ces mises à jour localement, nous allons installer Transformers à partir de la branche `main` avec la commande suivante :

```
pip install git+https://github.com/huggingface/transformers
```

## Repérage de mots-clés

Le repérage de mots clés (KWS pour *Keyword spotting*) est la tâche d'identifier un mot-clé dans un discours. L'ensemble des mots-clés possibles forme l'ensemble des étiquettes de classe prédites. Par conséquent, pour utiliser un modèle de repérage de mots clés pré-entraîné, vous devez vous assurer que vos mots-clés correspondent à ceux sur lesquels le modèle a été pré-entraîné. Ci-dessous, nous présenterons deux jeux de données et modèles pour la détection de mots clés.

### MINDS-14

Commençons en utilisant le même jeu de données [MINDS-14](https://huggingface.co/datasets/PolyAI/minds14) exploré dans l'unité précédente. Si vous vous souvenez, MINDS-14 contient des enregistrements de personnes posant des questions à un système bancaire électronique dans plusieurs langues et dialectes, et a indique une classe d’intention pour chaque enregistrement. Nous pouvons donc classer les enregistrements par intention de l'appel.

```python
from datasets import load_dataset

minds = load_dataset("PolyAI/minds14", name="en-AU", split="train")
```

Nous allons charger le *checkpoint* [`"anton-l/xtreme_s_xlsr_300m_minds14"`](https://huggingface.co/anton-l/xtreme_s_xlsr_300m_minds14), qui est un modèle XLS-R *finetuné* sur MINDS-14 pendant environ 50 époques. Il atteint une précision de 90% sur toutes les langues de MINDS-14 sur l'ensemble d'évaluation.

```python
from transformers import pipeline

classifier = pipeline(
    "audio-classification",
    model="anton-l/xtreme_s_xlsr_300m_minds14",
)
```

Enfin, nous pouvons passer un échantillon au pipeline de classification pour faire une prédiction :

```python
classifier(minds[0]["path"])
```

**Sortie :**

```
[
    {"score": 0.9631525278091431, "label": "pay_bill"},
    {"score": 0.02819698303937912, "label": "freeze"},
    {"score": 0.0032787492964416742, "label": "card_issues"},
    {"score": 0.0019414445850998163, "label": "abroad"},
    {"score": 0.0008378693601116538, "label": "high_value_payment"},
]
```

Nous avons identifié que l'intention de l'appel était de payer une facture, avec une probabilité de 96%. Vous pouvez imaginer que ce type de système de repérage de mots-clés soit utilisé comme première étape d'un centre d'appels automatisé, où nous voulons catégoriser les appels entrants des clients en fonction de leur requête et leur offrir un support contextualisé en conséquence.

### Speech Commands

Speech Commands est un jeu de données de mots parlés conçu pour évaluer les modèles de classification d’audio sur des mots de commande simples.
Le jeu de données se compose de 15 classes de mots-clés, d'une classe pour le silence et d'une classe inconnue pour inclure le faux positif.
Les 15 mots-clés sont des mots uniques qui seraient généralement utilisés dans les paramètres sur l'appareil pour contrôler les tâches de base ou lancer d'autres processus.
Un modèle similaire fonctionne en continu sur votre téléphone mobile. Ici, au lieu d'avoir des mots de commande uniques, nous avons des mots de réveil spécifiques à votre appareil, tels que « Hey Google » ou « Hey Siri ». Lorsque le modèle de classification d’audio détecte ces mots de réveil, il déclenche votre téléphone pour commencer à écouter le microphone et transcrire votre discours à l'aide d'un modèle de reconnaissance vocale.
Le modèle de classification d’audio est beaucoup plus petit et plus léger que le modèle de reconnaissance vocale, souvent seulement quelques millions de paramètres contre plusieurs centaines de millions pour la reconnaissance vocale. Ainsi, il peut fonctionner en continu sur votre appareil sans vider votre batterie ! Ce n'est que lorsque le mot de réveil est détecté que le modèle de reconnaissance vocale plus large est lancé, puis qu'il est à nouveau arrêté. Nous couvrirons les modèles de *transformers* pour la reconnaissance vocale dans la prochaine unité, donc à la fin du cours, vous devriez avoir les outils dont vous avez besoin pour construire votre propre assistant à commande vocale !
Comme pour tout jeu de données sur le *Hub*, nous pouvons avoir une idée de la tête des données sans avoir à les télécharger ou les avoir en mémoire. Après avoir accédé à la [carte du jeu de données Speech Commands](https://huggingface.co/datasets/speech_commands) sur le *Hub*, nous pouvons utiliser la visionneuse de données pour faire défiler les 100 premiers échantillons du jeu de données, écouter les fichiers audio et vérifier toute autre information de métadonnées :

     
 

L'aperçu du jeu de données est un moyen de découvrir les jeux de données audio avant de s'engager à les utiliser. Vous pouvez choisir n'importe quel jeu de données sur le *Hub*, faire défiler les échantillons et écouter l'audio pour les différents sous-ensembles et échantillons, en évaluant s'il s'agit du bon jeu de données pour vos besoins. Une fois que vous avez sélectionné un jeu de données, il est trivial de télécharger les données afin de pouvoir commencer à les utiliser.
Faisons cela et chargeons un échantillon du jeu de données Speech Commands en utilisant le mode streaming :

```python
speech_commands = load_dataset(
    "speech_commands", "v0.02", split="validation", streaming=True
)
sample = next(iter(speech_commands))
``` 

Nous allons charger un *checkpoint* d’un [*transformer* d’audio sous la forme de spectrogramme](https://huggingface.co/docs/transformers/model_doc/audio-spectrogramme-transformer) *finetuné* sur le jeu de données Speech Commands :

```python
classifier = pipeline(
    "audio-classification", model="MIT/ast-finetuned-speech-commands-v2"
)
classifier(sample["audio"].copy())
``` 

**Sortie :**

```
[{'score': 0.9999892711639404, 'label': 'backward'},
 {'score': 1.7504888774055871e-06, 'label': 'happy'},
 {'score': 6.703040185129794e-07, 'label': 'follow'},
 {'score': 5.805884484288981e-07, 'label': 'stop'},
 {'score': 5.614546694232558e-07, 'label': 'up'}]
``` 

On dirait que l'exemple contient le mot `backward` avec une forte probabilité. Nous pouvons écouter l'échantillon et vérifier qu'il est correct:

```
from IPython.display import Audio

Audio(sample["audio"]["array"], rate=sample["audio"]["sampling_rate"])
```

Vous vous demandez peut-être comment nous avons sélectionné les modèles pré-entraînés montrés dans ces exemples de classification d’audio.
C’est très simple ! La première chose que nous devons faire est de nous diriger sur le *Hub* et de cliquer sur l'onglet « *Models* »: https://huggingface.co/models
Cela va faire apparaître tous les modèles sur le *Hub* :

     
 

Vous remarquerez sur le côté gauche que nous avons plusieurs onglets que nous pouvons sélectionner pour filtrer les modèles par tâche, bibliothèque, jeu de données, etc. Faites défiler vers le bas et sélectionnez la tâche « Classification d’audio » dans la liste des tâches audio:

     
 

Nous voyons alors le sous-ensemble de modèles de classification d’audio présent sur le *Hub*. Pour affiner davantage cette sélection, nous pouvons filtrer les modèles par jeu de données. Cliquez sur l'onglet « Jeux de données », et dans la zone de recherche, tapez « speech_commands ». Lorsque vous commencez à taper, vous verrez la sélection pour 'speech_commands' apparaître sous l'onglet de recherche. Vous pouvez cliquer sur ce bouton pour filtrer tous les modèles de classification d’audio *finetuné* sur le jeu de données Speech Commands :

     
  

Bien, nous voyons que nous avons 6 modèles pré-entraînés à notre disposition pour ce jeu de données et cette tâche spécifiques. Le premier listé est celui que nous avons utilisé dans l'exemple précédent. Ce processus de filtrage des modèles du *Hub* est exactement la façon dont nous avons procédé pour choisir ce modèle.

## Identification de la langue

L'identification de la langue est la tâche d'identifier la langue parlée dans un échantillon audio à partir d'une liste de langues candidates. Cette tâche peut jouer un rôle important dans de nombreux pipelines de parole. Par exemple, étant donné un échantillon audio dans une langue inconnue, un modèle d’identification de langue peut être utilisé pour catégoriser la ou les langues parlées dans l'échantillon audio, puis sélectionner un modèle de reconnaissance vocale approprié entraîné sur cette langue pour transcrire l'audio.

### FLEURS

FLEURS (*Few-shot Learning Evaluation of Universal Representations of Speech*) est un jeu de données permettant d'évaluer les systèmes de reconnaissance vocale dans 102 langues, dont beaucoup sont classées comme à faibles ressources. Jetez un coup d'œil à la carte de FLEURS sur le *Hub* et explorez les différentes langues présentes : [google/fleurs](https://huggingface.co/datasets/google/fleurs).
Pouvez-vous trouver votre langue maternelle ici ? Si ce n'est pas le cas, quelle est la langue la plus proche ?
Chargeons un échantillon à partir de l’échantillon de validation de FLEURS en utilisant le mode streaming :

```python
fleurs = load_dataset("google/fleurs", "all", split="validation", streaming=True)
sample = next(iter(fleurs))
``` 

Génial ! Nous pouvons maintenant charger notre modèle de classification d’audio. Pour cela, nous utiliserons une version de [Whisper](https://arxiv.org/pdf/2212.04356.pdf) *finetuné* sur FLEURS, qui est actuellement le modèle de détection de langue le plus performant sur le Hub:

```python
classifier = pipeline(
    "audio-classification", model="sanchit-gandhi/whisper-medium-fleurs-lang-id"
)
``` 

Nous pouvons ensuite passer l'audio à travers notre classifieur et générer une prédiction :

```python
classifier(sample["audio"])
``` 

**Sortie :**

```
[{'score': 0.9999330043792725, 'label': 'Afrikaans'},
 {'score': 7.093023668858223e-06, 'label': 'Northern-Sotho'},
 {'score': 4.269149485480739e-06, 'label': 'Icelandic'},
 {'score': 3.2661141631251667e-06, 'label': 'Danish'},
 {'score': 3.2580724109720904e-06, 'label': 'Cantonese Chinese'}]
```

Nous pouvons voir que le modèle a prédit que l'audio était en Afrikaans avec une probabilité extrêmement élevée. FLEURS contient des données audio provenant d'un large éventail de langues : nous pouvons voir que les étiquettes de classe possibles incluent le sotho du Nord, l'islandais, le danois et le cantonais, entre autres. Vous pouvez trouver la liste complète des langues ici : [google/fleurs](https://huggingface.co/datasets/google/fleurs).
À vous de jouer ! Quels autres *checkpoints* pouvez-vous trouver sur le *Hub*  afin de détecter les langues présentes dans FLEURS ? Quels modèles de *transformers* utilisent-ils sous le capot ?

## Classification d’audio en zéro-shot

Dans le paradigme traditionnel de la classification d’audio, le modèle prédit une étiquette de classe à partir d'un ensemble de classes prédéfinies possibles. Cela constitue un obstacle à l'utilisation de modèles pré-entraînés pour la classification d’audio, car les étiquettes du modèle pré-entraîné doit correspondre à celui de la tâche en aval. Pour l'exemple précédent de détection de langues, le modèle doit prédire l'une des 102 classes de langue sur lesquelles il a été entraîné. Si la tâche en aval nécessite en fait 110 langues, le modèle ne serait pas en mesure de prédire 8 des 110 langues, et nécessiterait donc un nouvel entraînement pour atteindre une couverture complète. Cela limite l'efficacité de l'apprentissage par transfert pour les tâches de classification d’audio.
La classification d’audio zéro-shot est une méthode permettant de prendre un modèle de classification d’audio pré-entraîné entraîné sur un ensemble d'exemples étiquetés et de lui permettre de classer de nouveaux exemples de classes inédites. Voyons comment nous pouvons y parvenir.
Actuellement, 🤗 *Transformers* prend en charge un type de modèle pour la classification d’audio en zéro-shot : le [modèle CLAP](https://huggingface.co/docs/transformers/model_doc/clap).
CLAP est un modèle basé sur un *transformer* qui prend à la fois l'audio et le texte comme entrées, et calcule la *similitude* entre les deux.
Si nous passons une entrée de texte fortement corrélée à une entrée audio, nous obtiendrons un score de similarité élevé. Inversement, passer une entrée de texte qui n'a aucun rapport avec l'entrée audio renverra une faible similitude.
Nous pouvons utiliser cette prédiction de similarité pour la classification d’audio en zéro-shot en passant une entrée audio au modèle et plusieurs étiquettes candidates. Le modèle renverra un score de similarité pour chacune des étiquettes candidates, et nous pouvons choisir celle qui a le score le plus élevé comme prédiction.

Prenons un exemple où nous utilisons une entrée audio du jeu de données [Environmental Speech Challenge (ESC)](https://huggingface.co/datasets/ashraq/esc50) :

```python
dataset = load_dataset("ashraq/esc50", split="train", streaming=True)
audio_sample = next(iter(dataset))["audio"]["array"]
``` 

Nous définissons ensuite nos étiquettes candidates, qui forment l'ensemble des étiquettes de classification possibles. Le modèle renverra une probabilité de classification pour chacune des étiquettes que nous définissons. Cela signifie que nous devons connaître _a-priori_ l'ensemble des étiquettes possibles dans notre problème de classification, de sorte que l'étiquette correcte soit contenue dans l'ensemble et se voie donc attribuer un score de probabilité valide. Notez que nous pouvons soit transmettre l'ensemble complet des étiquettes au modèle, soit un sous-ensemble sélectionné à la main qui, selon nous, contient l'étiquette correcte. Passer l'ensemble complet des étiquettes sera plus exhaustif, mais se fait au détriment d'une précision de classification plus faible puisque l'espace de classification est plus grand (à condition que l'étiquette correcte soit notre sous-ensemble d'étiquettes choisi):

```python
candidate_labels = ["Sound of a dog", "Sound of vacuum cleaner"]
``` 

Nous pouvons parcourir les deux modèles pour trouver l'étiquette candidate qui est la plus similaire à l'entrée audio:

```python
classifier = pipeline(
    task="zero-shot-audio-classification", model="laion/clap-htsat-unfused"
)
classifier(audio_sample, candidate_labels=candidate_labels)
``` 

**Sortie :**

```
[{'score': 0.9997242093086243, 'label': 'Sound of a dog'}, {'score': 0.0002758323971647769, 'label': 'Sound of vacuum cleaner'}]
```
Le modèle semble assez confiant (probabilité de 99,97%) que nous ayons le son d'un chien .Nous allons donc prendre cela comme notre prédiction. Confirmons si nous avions raison en écoutant l'échantillon audio (n'augmentez pas trop le volume, sinon vous risquez de sursauter !):

```python
Audio(audio, rate=16000)
``` 

Parfait ! Nous avons le son d'un chien qui aboie 🐕, ce qui correspond à la prédiction du modèle. Jouez avec différents échantillons audio et différentes étiquettes candidates. Pouvez-vous définir un ensemble d'étiquettes qui donnent une bonne généralisation à travers le jeu de données ESC ? Astuce : pensez à l'endroit où vous pourriez trouver des informations sur les sons possibles dans ESC et construisez vos étiquettes en conséquence.
Vous vous demandez peut-être pourquoi nous n'utilisons pas le pipeline de classification d’audio zero-shot pour **toutes** les tâches de classification d’audio ? 
Il semble que nous puissions faire des prédictions pour n'importe quel problème de classification d’audio en définissant des étiquettes de classe appropriées _à priori_, contournant ainsi la contrainte dont notre tâche de classification a besoin pour correspondre aux étiquettes sur lesquelles le modèle a été pré-entraîné.
Cela se résume à la nature du modèle CLAP utilisé dans le pipeline zéro-shot. CLAP est pré-entraîné sur des données de classification d’audio _génériques_, similaires aux sons environnementaux dans le jeu de données ESC, plutôt que sur des données vocales spécifiques, comme nous l'avions dans la tâche de détection de langue. Si vous lui donnez un discours en anglais et un discours en espagnol, CLAP saurait que les deux exemples étaient des données vocales.  Mais il ne serait pas capable de différencier les langues de la même manière qu'un modèle de détection de langue dédié à cette tâche.

## Et ensuite ?

Nous avons couvert un certain nombre de tâches de classification d’audio, présenté les jeux de données et les modèles les plus pertinents que vous pouvez télécharger à partir du *Hub* et comment les utiliser en quelques lignes de code à l'aide de la classe `pipeline()`. Ces tâches comprenent la détection de mots-clés, l'identification de la langue et la classification d’audio en zéro-shot.
Mais que se passe-t-il si nous voulons faire quelque chose de **nouveau** ? Nous avons beaucoup travaillé sur les tâches de traitement de la parole, mais ce n'est qu'un aspect de la classification d’audio. Un autre domaine populaire du traitement d’audio est la **musique**. Bien que la musique ait des caractéristiques intrinsèquement différentes à la parole, bon nombre des mêmes principes que nous avons déjà appris peuvent être appliqués.
Dans la section suivante, nous allons passer en revue un guide étape par étape sur la façon dont vous pouvez *finetuner* un *transformer* avec 🤗 *Transformers* sur la tâche de classification de la musique. À la fin, vous aurez un *checkpoint* *finetuné* que vous pourrez brancher dans la classe `pipeline()`, vous permettant de classer les chansons exactement de la même manière que nous avons classé la parole ici.

### Exercice pratique
https://huggingface.co/learn/audio-course/fr/chapter4/hands_on.md

# Exercice pratique

Il est temps de manipuler les modèles audio et d'appliquer ce que vous avez appris jusqu'à présent. Cet exercice est l'un des quatre exercices pratiques requis pour obtenir un certificat de fin de cours.

Voici les instructions.
Dans cette unité, nous avons démontré comment *finetuner* un modèle HuBERT sur le jeu de données `marsyas/gtzan` pour de la classification de musique. Notre exemple a atteint une précision de 83%. 
Votre tâche consiste à améliorer cette mesure de précision. 

Vous pouvez choisir n'importe quel modèle sur le [🤗 *Hub*](https://huggingface.co/models) que vous pensez adapté à la classification audio, et utiliser exactement le même jeu de données [`marsyas/gtzan`](https://huggingface.co/datasets/marsyas/gtzan) pour construire votre propre classifieur.

Votre objectif est d'atteindre une précision de 87% sur ce jeu de données. Vous pouvez choisir exactement le même modèle, et jouer avec les hyperparamètres d'entraînement, ou choisir un modèle complètement différent. A vous de décider ! 

Pour que votre résultat soit pris en compte dans votre certificat, n'oubliez pas de pousser votre modèle sur le  *Hub* comme cela a été montré dans cette unité avec les `**kwargs` suivants à la fin de l'entraînement :

```python
kwargs = {
    "dataset_tags": "marsyas/gtzan",
    "dataset": "GTZAN",
    "model_name": f"{model_name}-finetuned-gtzan",
    "finetuned_from": model_id,
    "tasks": "audio-classification",
}

trainer.push_to_hub(**kwargs)
```

Voici quelques ressources supplémentaires qui pourraient vous être utiles dans le cadre de cet exercice :
* [Guide de classification audio dans la documentation de 🤗 Transformers](https://huggingface.co/docs/transformers/tasks/audio_classification)
* [Documentation du modèle HuBERT](https://huggingface.co/docs/transformers/model_doc/hubert)
* [Documentation du modèle M-CTC-T](https://huggingface.co/docs/transformers/model_doc/mctct)
* [Audio Spectrogram Transformer documentation](https://huggingface.co/docs/transformers/model_doc/audio-spectrogram-transformer)
* [Documentation du Wav2Vec2](https://huggingface.co/docs/transformers/model_doc/wav2vec2)

N'hésitez pas à créer une démo de votre modèle et à la partager sur Discord ! Si vous avez des questions, posez-les dans le canal `#audio-study-group`.

### Unité 4 : Construire un classifieur de genres musicaux
https://huggingface.co/learn/audio-course/fr/chapter4/introduction.md

# Unité 4 : Construire un classifieur de genres musicaux

## Ce que vous allez apprendre et construire

La classification d'audio est l'une des applications les plus courantes des *transformers* dans le traitement du son et de la parole. Comme d'autres tâches de classification dans l'apprentissage automatique, cette tâche consiste à attribuer une ou plusieurs étiquettes à un enregistrement audio en fonction de son contenu. Par exemple, dans le cas de la parole, nous pourrions vouloir détecter quand des mots de réveil comme « Hey Siri » sont prononcés, ou déduire un mot clé comme « température » d'une requête vocale comme « Quel temps fait-il aujourd'hui ? ». Les sons environnementaux constituent un autre exemple : nous pourrions vouloir distinguer automatiquement des sons tels que « klaxon de voiture », « sirène », « aboiement de chien », etc.

Dans cette section, nous verrons comment les *transformers* audio pré-entraînés peuvent être appliqués à une série de tâches de classification d'audio.
Nous allons ensuite *finetuner* un *transformer* sur la tâche de classification de la musique, en classant les chansons dans des genres comme « pop » et « rock ». Il s'agit d'une partie importante des plateformes de streaming musical, qui recommandent des chansons similaires à celles que l'utilisateur est en train d'écouter.
À la fin de cette section, vous saurez comment :

* Trouver des modèles pré-entraînés appropriés pour les tâches de classification d'audio
* Utiliser la bibliothèque 🤗 *Datasets* et le *Hub* pour sélectionner des jeux de données de classification d'audio
* *Finetuner * un modèle pré-entraîné pour classer les chansons par genre
* Construire une démo *Gradio* permettant de classer vos propres chansons

### Construire une démo avec Gradio
https://huggingface.co/learn/audio-course/fr/chapter4/demo.md

# Construire une démo avec Gradio

Dans cette dernière section sur la classification audio, nous allons construire une démo avec [*Gradio*](https://gradio.app) pour présenter le modèle de classification musicale que nous venons d'entraîner sur le jeu de données [GTZAN](https://huggingface.co/datasets/marsyas/gtzan). 
La première chose à faire est de charger le *checkpoint* *finetuné* en utilisant la classe `pipeline()` que vous connaissez grâce à la section sur les [modèles pré-entraînés](classification_models). Vous pouvez changer le `model_id` avec le nom de votre modèle *finetuné* et présent sur *Hub* :

```python
from transformers import pipeline

model_id = "sanchit-gandhi/distilhubert-finetuned-gtzan"
pipe = pipeline("audio-classification", model=model_id)
```

Deuxièmement, nous allons définir une fonction qui prend le chemin du fichier d'une entrée audio et le passe à travers le pipeline. 
Ici, le pipeline s'occupe automatiquement de charger le fichier audio, de le ré-échantillonner à la bonne fréquence d'échantillonnage, et de lancer l'inférence avec le modèle. 
Nous prenons les prédictions de `preds` du modèle et les formatons en tant qu'objet dictionnaire à afficher sur la sortie :

```python
def classify_audio(filepath):
    preds = pipe(filepath)
    outputs = {}
    for p in preds:
        outputs[p["label"]] = p["score"]
    return outputs
```

Enfin, nous lançons la démo Gradio en utilisant la fonction que nous venons de définir :

```python
import gradio as gr

demo = gr.Interface(
    fn=classify_audio, inputs=gr.Audio(type="filepath"), outputs=gr.outputs.Label()
)
demo.launch(debug=True)
```

Ceci lancera une démo similaire à celle qui tourne sur le *Space* :

### Comment finetuner un système de reconnaissance automatique de la parole avec l'API Trainer
https://huggingface.co/learn/audio-course/fr/chapter5/fine-tuning.md

# Comment finetuner un système de reconnaissance automatique de la parole avec l'API Trainer

Dans cette section, nous allons couvrir un guide étape par étape pour *finetuner* Whisper pour la reconnaissance automatique de la parole sur le jeu de données Common Voice 13. Nous utiliserons la version "*small*" du modèle et un jeu de données relativement léger, vous permettant d'exécuter le *finetuning* assez rapidement sur n'importe quel GPU de plus de 16 Go avec de faibles besoins en espace disque, comme le GPU T4 de 16 Go fourni dans le volet gratuit de Google Colab.

Si vous disposez d'un GPU plus petit ou si vous rencontrez des problèmes de mémoire pendant l'entraînement, vous pouvez suivre les suggestions fournies pour réduire l'utilisation de la mémoire. À l'inverse, si vous avez accès à un GPU plus puissant, vous pouvez modifier les arguments d'entraînement pour maximiser votre capacité de traitement. Ce guide est donc accessible quelles que soient les spécifications de votre GPU !

De même, ce guide porte plus précisément sur le *finetuning* sur la langue Dhivehi mais les étapes couvertes ici se généralisent à n'importe quelle langue du jeu de données Common Voice, et plus généralement à n'importe quel jeu de données d'ASR disponible sur le *Hub*.
Vous pouvez modifier le code pour passer rapidement à la langue de votre choix et *finetuner* un modèle Whisper dans votre langue maternelle 🌍.

Commençons et donnons le coup d'envoi de notre pipeline de *finetuning* !

## Préparer l'environnement

Nous vous conseillons vivement de télécharger les *checkpoints* du modèle directement sur le [*Hub*](https://huggingface.co/).
Le *Hub* offre les avantages suivants :
- Un contrôle de version intégré : vous pouvez être sûr qu'aucun *checkpoint* n'est perdu pendant l'entraînement.
- Tensorboard : suivi des mesures importantes au cours de l'entraînement.
- Cartes de modèle : documenter ce que fait un modèle et ses cas d'utilisation prévus.
- Communauté : un moyen facile de partager et de collaborer avec la communauté ! 🤗

Lier le *notebook* au *Hub* est très simple, il suffit d'entrer votre *token* d'authentification au *Hub* lorsque l'on vous y invite.
Votre *token* d'authentification est trouvable [ici](https://huggingface.co/settings/tokens).

```python
from huggingface_hub import notebook_login

notebook_login()
```

**Sortie :**

```bash
Login successful
Your token has been saved to /root/.huggingface/token
```

## Charger le jeu de données

[Common Voice 13](https://huggingface.co/datasets/mozilla-foundation/common_voice_13_0) contient environ dix heures de données Dhivehi étiquetées, dont trois sont des données de test. Il s'agit de très peu de données pour un *finetuning*, nous nous appuierons donc sur la connaissance multilingue acquise par Whisper pendant le pré-entraînement.

En utilisant les 🤗 *Datasets*, le téléchargement et la préparation des données sont extrêmement simples. Nous pouvons télécharger et préparer les ensembles de Common Voice 13 en une seule ligne de code. Puisque le Dhivehi est très pauvre en ressources, nous combinerons les splits `train` et `validation` pour obtenir environ sept heures de données d'entraînement. Nous utiliserons les trois heures de données `test` comme notre ensemble de test :

```python
from datasets import load_dataset, DatasetDict

common_voice = DatasetDict()

common_voice["train"] = load_dataset(
    "mozilla-foundation/common_voice_13_0", "dv", split="train+validation"
)
common_voice["test"] = load_dataset(
    "mozilla-foundation/common_voice_13_0", "dv", split="test"
)

print(common_voice)
```

**Sortie :**

```
DatasetDict({
    train: Dataset({
        features: ['client_id', 'path', 'audio', 'sentence', 'up_votes', 'down_votes', 'age', 'gender', 'accent', 'locale', 'segment', 'variant'],
        num_rows: 4904
    })
    test: Dataset({
        features: ['client_id', 'path', 'audio', 'sentence', 'up_votes', 'down_votes', 'age', 'gender', 'accent', 'locale', 'segment', 'variant'],
        num_rows: 2212
    })
})
```

    Vous pouvez changer l'identifiant de langue de `"dv"` pour un identifiant de langue de votre choix. Pour voir toutes les langues possibles dans Common Voice 13, consultez la carte du jeu de données sur le *Hub* : https://huggingface.co/datasets/mozilla-foundation/common_voice_13_0

La plupart des jeux de données d'ASR ne fournissent que des échantillons audio en entrée (`audio`) et le texte transcrit correspondant (`sentence`).
Common Voice contient des métadonnées supplémentaires, telles que `accent` et `locale`, que nous pouvons ignorer pour l'ASR.
En gardant le *notebook* aussi général que possible, nous ne considérons que l'audio d'entrée et le texte transcrit en écartant les informations de métadonnées supplémentaires :

```python
common_voice = common_voice.select_columns(["audio", "sentence"])
```

## Extracteur de caractéristiques, tokeniser et processeur

Le pipeline d'ASR peut être décomposé en trois étapes :

1. L'extracteur de caractéristiques qui pré-traite les entrées audio brutes en spectrogrammes log-mél.
2. Le modèle qui effectue l'association séquence-séquence
3. Le tokenizer qui post-traite les *tokens* prédits en texte.

Dans 🤗 *Transformers*, le modèle Whisper est associé à un extracteur de caractéristiques et à un tokenizer, appelés respectivement [WhisperFeatureExtractor](https://huggingface.co/docs/transformers/main/model_doc/whisper#transformers.WhisperFeatureExtractor) et [WhisperTokenizer](https://huggingface.co/docs/transformers/main/model_doc/whisper#transformers.WhisperTokenizer).
Pour nous simplifier la vie, ces deux objets sont regroupés dans une seule classe, appelée [WhisperProcessor](https://huggingface.co/docs/transformers/model_doc/whisper#transformers.WhisperProcessor).
Nous pouvons appeler le WhisperProcessor pour effectuer à la fois le prétraitement audio et le post-traitement des *tokens* de texte. Ce faisant, nous n'avons besoin de suivre que deux objets pendant l'entraîningment : le processeur et le modèle.

Lors d'un *finetuné* multilingue, nous devons définir la `"language"` et la `"task"` lors de l'instanciation du processeur.
La `"language"` doit être fixée à la langue audio source, et la tâche à `"translate"` pour la reconnaissance vocale ou à `"translate"` pour la traduction vocale. Ces arguments modifient le comportement du *tokens*, et doivent être définis correctement pour s'assurer que les étiquettes cibles sont encodées correctement.

Nous pouvons voir toutes les langues possibles supportées par Whisper en important la liste des langues :

```python
from transformers.models.whisper.tokenization_whisper import TO_LANGUAGE_CODE

TO_LANGUAGE_CODE
```

Si vous parcourez cette liste, vous remarquerez que de nombreuses langues sont présentes, mais que le dhivehi est l'une des rares à ne pas l'être !
Cela signifie que Whisper n'a pas été pré-entraîné sur le dhivehi. Cependant, cela ne signifie pas que nous ne pouvons pas *finetuner* Whisper sur cette langue.
En faisant cela, nous allons entraîner Whisper dans une nouvelle langue, une langue non supportée par le *checkpoint* pré-entraîné. C'est plutôt cool, non ?

Lorsque vous le *finetunez* sur une nouvelle langue, Whisper fait un bon travail en tirant parti de sa connaissance des 96 autres langues sur lesquelles il a été pré-entraîné. En général, toutes les langues modernes seront linguistiquement similaires à au moins l'une des 96 langues que Whisper connaît déjà, nous nous inscrivons donc dans ce paradigme de représentation des connaissances interlinguistiques.

Ce que nous devons faire pour cette nouvelle langue, est de trouver la langue **la plus similaire** sur laquelle Whisper a été pré-entraîné. L'article de Wikipédia sur le dhivehi indique que cette langue est étroitement liée à la langue cinghalaise du Sri Lanka.
Si nous vérifions à nouveau les codes de langue, nous pouvons voir que le cinghalais est présent dans le jeu de langues de Whisper, nous pouvons donc en toute sécurité mettre notre argument de langue à `"sinhalese"`.

Nous allons charger notre processeur à partir du *checkpoint* pré-entraîné, en fixant la langue à `"sinhalese"` et la tâche à `"transcribe"` comme expliqué ci-dessus :

```python
from transformers import WhisperProcessor

processor = WhisperProcessor.from_pretrained(
    "openai/whisper-small", language="sinhalese", task="transcribe"
)
```

Il est utile de rappeler que dans la plupart des cas, vous constaterez que la langue sur laquelle vous souhaitez effectuer un *finetuning* se trouve dans l'ensemble des langues de pré-entraînement, auquel cas vous pouvez simplement définir cette langue directement comme langue audio source ! Notez que ces deux arguments doivent être omis pour le *finetuning* en anglais où il n'y a qu'une seule option pour la langue (`"English"`) et la tâche (`"transcribe"`).

## Prétraitement des données

Jetons un coup d'oeil aux caractéristiques du jeu de données. Portez une attention particulière à la colonne `"audio"`, elle détaille le taux d'échantillonnage de nos entrées audio :

```python
common_voice["train"].features
```

**Sortie :**

```
{'audio': Audio(sampling_rate=48000, mono=True, decode=True, id=None),
 'sentence': Value(dtype='string', id=None)}
```

Puisque notre audio d'entrée est échantillonné à 48kHz, nous devons le sous-échantillonner à 16kHz avant de le passer à l'extracteur de caractéristiques de Whisper qui est la fréquence d'échantillonnage attendue par le modèle.

Nous allons régler les entrées audio à la bonne fréquence d'échantillonnage en utilisant la méthode [`cast_column`](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.cast_column) du jeu de données. Cette opération ne modifie pas l'audio sur place, mais signale aux jeux de données de rééchantillonner les échantillons audio à la volée lorsqu'ils sont chargés :

```python
from datasets import Audio

sampling_rate = processor.feature_extractor.sampling_rate
common_voice = common_voice.cast_column("audio", Audio(sampling_rate=sampling_rate))
```

Nous pouvons maintenant écrire une fonction pour préparer nos données pour le modèle :

1. Nous chargeons et rééchantillonnons les données audio échantillon par échantillon en appelant `sample["audio"]`. Comme expliqué ci-dessus, 🤗 *Datasets* effectue toutes les opérations de rééchantillonnage nécessaires à la volée.
2. Nous utilisons l'extracteur de caractéristiques pour calculer les caractéristiques d'entrée du spectrogramme log-mel à partir de notre tableau audio unidimensionnel.
3. Nous encodons les transcriptions en identifiants d'étiquettes à l'aide d'un *tokenizer*.

```python
def prepare_dataset(example):
    audio = example["audio"]

    example = processor(
        audio=audio["array"],
        sampling_rate=audio["sampling_rate"],
        text=example["sentence"],
    )

    # compute input length of audio sample in seconds
    example["input_length"] = len(audio["array"]) / audio["sampling_rate"]

    return example
```

Nous pouvons appliquer la fonction de préparation des données à tous nos exemples d'entraînement en utilisant la méthode `.map` de 🤗 *Datasets*. Nous allons supprimer les colonnes des données d'entraînement brutes (l'audio et le texte), en ne laissant que les colonnes renvoyées par la fonction `prepare_dataset` :

```python
common_voice = common_voice.map(
    prepare_dataset, remove_columns=common_voice.column_names["train"], num_proc=1
)
```

Enfin, nous filtrons toutes les données d'entraînement contenant des échantillons audio de plus de 30 secondes. Ces échantillons seraient sinon tronqués par l'extracteur de caractéristiques de Whisper, ce qui pourrait affecter la stabilité de l'entraînement. Nous définissons une fonction qui renvoie `True` pour les échantillons de moins de 30 secondes, et `False` pour ceux qui sont plus longs :

```python
max_input_length = 30.0

def is_audio_in_length_range(length):
    return length  Dict[str, torch.Tensor]:
        # diviser les entrées et les étiquettes car elles doivent être de longueurs différentes et nécessitent des méthodes de remplissage différentes
        # traiter d'abord les entrées audio en renvoyant simplement des tenseurs Torch
        input_features = [
            {"input_features": feature["input_features"][0]} for feature in features
        ]
        batch = self.processor.feature_extractor.pad(input_features, return_tensors="pt")

        # obtenir les séquences d'étiquettes tokenisées
        label_features = [{"input_ids": feature["labels"]} for feature in features]
        # rembourrer les étiquettes à la longueur maximale
        labels_batch = self.processor.tokenizer.pad(label_features, return_tensors="pt")

        # remplacer le remplissage par -100 pour ignorer correctement les pertes
        labels = labels_batch["input_ids"].masked_fill(
            labels_batch.attention_mask.ne(1), -100
        )

        # si le token bos est ajouté lors de l'étape de tokenisation précédente, couper le token bos ici puisqu'il sera de toute façon ajouté plus tard
        if (labels[:, 0] == self.processor.tokenizer.bos_token_id).all().cpu().item():
            labels = labels[:, 1:]

        batch["labels"] = labels

        return batch
```

Nous pouvons maintenant initialiser l'assembleur de données que nous venons de définir :

```python
data_collator = DataCollatorSpeechSeq2SeqWithPadding(processor=processor)
```

En avant !

### Métriques d'évaluation

Ensuite, nous définissons la métrique d'évaluation que nous utiliserons sur notre ensemble d'évaluation. Nous utiliserons le taux d'erreur au niveaud du mot (WER) introduit dans la section [évaluation](évaluation), la métrique "de-facto" pour évaluer les systèmes d'ASR.

Nous chargerons la métrique WER à partir d' 🤗 *Evaluate* :

```python
import evaluate

metric = evaluate.load("wer")
```

Il suffit ensuite de définir une fonction qui prend les prédictions de notre modèle et renvoie la métrique WER. Cette fonction, appelée `compute_metrics`, remplace d'abord `-100` par le `pad_token_id` dans `label_ids` (annulant l'étape que nous avons appliquée dans l'assembleur de données pour ignorer correctement les *tokens* rembourrés dans la perte). Il décode ensuite les identifiants prédits et les identifiants d'étiquettes en chaînes de caractères. Enfin, il calcule le WER entre les prédictions et les étiquettes de référence. Ici, nous avons la possibilité d'évaluer les transcriptions et les prédictions "normalisées", dont la ponctuation et la casse ont été supprimées. Nous vous recommandons de procéder ainsi pour bénéficier de l'amélioration du WER obtenue par la normalisation des transcriptions.

```python
from transformers.models.whisper.english_normalizer import BasicTextNormalizer

normalizer = BasicTextNormalizer()

def compute_metrics(pred):
    pred_ids = pred.predictions
    label_ids = pred.label_ids

    # remplacer -100 par pad_token_id
    label_ids[label_ids == -100] = processor.tokenizer.pad_token_id

    # nous ne voulons pas grouper les *tokens* lors du calcul des métriques
    pred_str = processor.batch_decode(pred_ids, skip_special_tokens=True)
    label_str = processor.batch_decode(label_ids, skip_special_tokens=True)

    # calculer le Wer orthographique
    wer_ortho = 100 * metric.compute(predictions=pred_str, references=label_str)

    # calculer le WER normalisé
    pred_str_norm = [normalizer(pred) for pred in pred_str]
    label_str_norm = [normalizer(label) for label in label_str]
    # afin de n'évaluer que les échantillons correspondant à des références non nulles
    pred_str_norm = [
        pred_str_norm[i] for i in range(len(pred_str_norm)) if len(label_str_norm[i]) > 0
    ]
    label_str_norm = [
        label_str_norm[i]
        for i in range(len(label_str_norm))
        if len(label_str_norm[i]) > 0
    ]

    wer = 100 * metric.compute(predictions=pred_str_norm, references=label_str_norm)

    return {"wer_ortho": wer_ortho, "wer": wer}
```

### Charger un *checkpoint* pré-entraîné

Chargeons maintenant le *checkpoint* pré-entraîné de Whisper small. Encore une fois, ceci est trivial grâce à l'utilisation de 🤗 *Transformers* !

```python
from transformers import WhisperForConditionalGeneration

model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-small")
```

Nous allons mettre `use_cache` à `False` pour l'entraînement puisque nous utilisons [*gradient checkpointing*] (https://huggingface.co/docs/transformers/v4.18.0/en/performance#gradient-checkpointing) et que les deux sont incompatibles. Nous allons aussi surcharger deux arguments de génération pour contrôler le comportement du modèle pendant l'inférence : nous allons forcer la langue et les *tokens* de tâche pendant la génération en définissant les arguments `language` et `task`, et aussi réactiver le cache pour la génération afin d'accélérer le temps d'inférence :

```python
from functools import partial

# désactiver le cache pendant l'entraînement car il est incompatible avec le checkpointing du gradient
model.config.use_cache = False

# définir la langue et la tâche pour la génération et réactiver le cache
model.generate = partial(
    model.generate, language="sinhalese", task="transcribe", use_cache=True
)
```

## Définir la configuration de l'entraînement

Dans la dernière étape, nous définissons tous les paramètres liés à l'entraînement. Ici, nous fixons le nombre d'étapes d'entraînement à 500.
Cela représente suffisamment d'étapes pour voir une grande amélioration du WER par rapport au modèle pré-entraîné, tout en s'assurant que le *finetuning* peut être exécuté en environ 45 minutes sur un niveau gratuit de Google Colab. Pour plus de détails sur les arguments d'entraînement, reportez-vous à la documentation de [Seq2SeqTrainingArguments] (https://huggingface.co/docs/transformers/main_classes/trainer#transformers.Seq2SeqTrainingArguments).

```python
from transformers import Seq2SeqTrainingArguments

training_args = Seq2SeqTrainingArguments(
    output_dir="./whisper-small-dv",  # nom sur le Hub
    per_device_train_batch_size=16,
    gradient_accumulation_steps=1,  # à x2  pour chaque diminution de 2x de la taille du batch
    learning_rate=1e-5,
    lr_scheduler_type="constant_with_warmup",
    warmup_steps=50,
    max_steps=500,  # augmenter jusqu'à 4000 si vous disposez de votre propre GPU ou d'un plan Colab payant
    gradient_checkpointing=True,
    fp16=True,
    fp16_full_eval=True,
    evaluation_strategy="steps",
    per_device_eval_batch_size=16,
    predict_with_generate=True,
    generation_max_length=225,
    save_steps=500,
    eval_steps=500,
    logging_steps=25,
    report_to=["tensorboard"],
    load_best_model_at_end=True,
    metric_for_best_model="wer",
    greater_is_better=False,
    push_to_hub=True,
)
```

    Si vous ne voulez pas télécharger les *checkpoints* du modèle vers le *Hub*, mettez `push_to_hub=False`.

Nous pouvons transmettre les arguments d'entraînement au *Trainer* avec notre modèle, notre jeu de données, notre assembleur de données et la fonction `compute_metrics` :

```python
from transformers import Seq2SeqTrainer

trainer = Seq2SeqTrainer(
    args=training_args,
    model=model,
    train_dataset=common_voice["train"],
    eval_dataset=common_voice["test"],
    data_collator=data_collator,
    compute_metrics=compute_metrics,
    tokenizer=processor,
)
```

Et voilà, nous sommes prêts à entraîner !

#### Entraînement

Pour lancer l'entraînement, il suffit d'exécuter :

```python
trainer.train()
```

L'entraînement prendra environ 45 minutes en fonction de votre GPU ou de celui alloué par Google Colab. En fonction de votre GPU, il est possible que vous rencontriez une erreur CUDA `"out-of-memory"` lorsque vous commencez à entraîner. Dans ce cas, vous pouvez réduire le `per_device_train_batch_size` par incréments d'un facteur 2 et utiliser [`gradient_accumulation_steps`](https://huggingface.co/docs/transformers/main_classes/trainer#transformers.Seq2SeqTrainingArguments.gradient_accumulation_steps) pour compenser.

**Sortie :**

| Training Loss | Epoch | Step | Validation Loss | Wer Ortho | Wer     |
|:-------------:|:-----:|:----:|:---------------:|:---------:|:-------:|
| 0.136         | 1.63  | 500  | 0.1727          | 63.8972   | 14.0661 |

Notre WER final est de 14,1 % ce qui n'est pas mal pour sept heures de données d'entraînement et seulement 500 étapes d'entraînement ! Cela représente une amélioration de 112 % par rapport au modèle pré-entraîné ! Cela signifie que nous avons pris un modèle qui n'avait aucune connaissance du dhivehi et que nous l'avons *finetuné* pour reconnaître l'dhivehi avec une précision adéquate en moins d'une heure 🤯.

La grande question est de savoir comment cela se compare à d'autres systèmes ASR. Pour cela, nous pouvons consulter le [classement autoevaluate] (https://huggingface.co/spaces/autoevaluate/leaderboards?dataset=mozilla-foundation%2Fcommon_voice_13_0&only_verified=0&task=automatic-speech-recognition&config=dv&split=test&metric=wer) qui catégorise les modèles par langue et par jeu de données, et les classe ensuite en fonction de leur WER.

En regardant le classement, nous voyons que notre modèle entraîné pour 500 étapes bat de manière convaincante le *checkpoint* [Whisper Small](https://huggingface.co/openai/whisper-small) pré-entraîné que nous avons évalué dans la section précédente. Bon travail 👏

Nous voyons qu'il y a quelques *checkpoints* qui font mieux que celui que nous avons entraîné. La beauté du *Hub* est qu'il s'agit d'une plateforme *collaborative*. Si nous n'avons pas le temps ou les ressources pour effectuer un entraînement plus long nous-mêmes, nous pouvons charger un *checkpoint* que quelqu'un d'autre dans la communauté a entraîné et a eu la gentillesse de partager (en s'assurant de le remercier pour cela !).
Vous pourrez charger ces *checkpoints* exactement de la même manière que les pré-entraînés en utilisant la classe `pipeline` comme nous l'avons fait précédemment ! Ainsi, rien ne vous empêche de sélectionner le meilleur modèle du leaderboard pour l'utiliser dans le cadre de votre tâche !

Nous pouvons automatiquement soumettre notre *checkpoint* au classement lorsque nous envoyons les résultats de l'entraînement au *Hub*. Nous devons simplement définir les arguments de mot-clé appropriés (kwargs). Vous pouvez modifier ces valeurs pour qu'elles correspondent à votre jeu de données, à votre langue et au nom de votre modèle en conséquence :

```python
kwargs = {
    "dataset_tags": "mozilla-foundation/common_voice_13_0",
    "dataset": "Common Voice 13",  # a 'pretty' name for the training dataset
    "language": "dv",
    "model_name": "Whisper Small Dv - Sanchit Gandhi",  # a 'pretty' name for your model
    "finetuned_from": "openai/whisper-small",
    "tasks": "automatic-speech-recognition",
}
```

Les résultats de l'entraînement peuvent maintenant être téléchargés vers le *Hub*. Pour ce faire, exécutez la commande `push_to_hub` :

```python
trainer.push_to_hub(**kwargs)
```

Ceci sauvegardera les logs d'entraînement et les poids des modèles sous `"votre-nom-d'utilisateur/le-nom-que-vous-avez-choisi"`. Pour cet exemple, regardez le téléchargement à `sanchit-gandhi/whisper-small-dv`.

Bien que le modèle *finetuné* donne des résultats satisfaisants sur les données de test de Common Voice 13, il n'est en aucun cas optimal.
Le but de ce guide est de démontrer comment *finetuner* un modèle ASR en utilisant le *Trainer* pour la reconnaissance automatique de la parole multilingue.

Si vous avez accès à votre propre GPU ou si vous êtes abonné à un plan payant de Google Colab, vous pouvez augmenter `max_pas` à 4000 pas pour améliorer davantage le WER en entraînant plus de pas. Entraîner 4000 pas prendra environ 3 à 5 heures en fonction de votre GPU et donnera des résultats WER inférieurs d'environ 3 % à l'entraînement de 500 pas. Si vous décidez d'entraîner sur 4000 pas, nous vous recommandons également de changer le planificateur de taux d'apprentissage pour un plan *linéaire* (set `lr_scheduler_type="linear"`), car cela permettra d'augmenter les performances sur de longues périodes d'entraînement.

Les résultats pourraient probablement être améliorés en optimisant les hyperparamètres d'entraînement, tels que _learning rate_ et _dropout_, et en utilisant un *checkpoint* pré-entraîné plus grand (`medium` ou `large`). Nous laissons cet exercice au lecteur.

## Partager votre modèle

Vous pouvez maintenant partager ce modèle avec n'importe qui en utilisant le lien sur le *Hub*. Ils peuvent le charger avec l'identifiant `"votre-nom-d'utilisateur/le-nom-que-vous-avez-choisi"` directement dans l'objet `pipeline()`. Par exemple, pour charger le *checkpoint* *finetuné* ["sanchit-gandhi/whisper-small-dv"](https://huggingface.co/sanchit-gandhi/whisper-small-dv) :

```python
from transformers import pipeline

pipe = pipeline("automatic-speech-recognition", model="sanchit-gandhi/whisper-small-dv")
```

## Conclusion

Dans cette section, nous avons couvert un guide étape par étape sur le *finetuning* du modèle Whisper pour la reconnaissance vocale en utilisants 🤗 *Jeux de données*, 🤗 *Transformers* et le *Hub*. Nous avons d'abord chargé le sous-ensemble Dhivehi du jeu de données Common Voice 13 et l'avons prétraité en calculant des spectrogrammes log-mel et en tokenisant le texte. Nous avons ensuite défini un assembleur de données, une métrique d'évaluation et des arguments d'entraînement, avant d'utiliser le *Trainer* pour entraîner et évaluer notre modèle. Nous avons terminé en téléchargeant le modèle *finetuné* sur le *Hub*, et nous avons montré comment le partager et l'utiliser avec la classe `pipeline()`.

Si vous avez suivi jusqu'à ce point, vous devriez maintenant avoir un *checkpoint* *finetuné* pour la reconnaissance automatique de la parole, bien joué ! 🥳
Plus important encore, vous êtes équipé de tous les outils nécessaires pour *finetuner* le modèle Whisper sur n'importe quel jeu de données ou domaine de reconnaissance vocale. Alors, qu'attendez-vous ? Choisissez l'un des jeux de données couverts dans la section [Choisir un jeu de données](choosing_dataset) ou sélectionnez un jeu de données de votre choix, et voyez si vous pouvez obtenir des performances de pointe ! Le classement vous attend...

### Exercice pratique
https://huggingface.co/learn/audio-course/fr/chapter5/hands_on.md

# Exercice pratique

Dans cette unité, nous avons exploré les défis du *finetuning* des modèles d'ASR, en mettant en avant le temps et les ressources nécessaires pour *finetuner* un modèle comme Whisper (même un petit *checkpoint*) sur une nouvelle langue. 
Afin de fournir une expérience pratique, nous avons conçu un exercice qui vous permet de naviguer dans le processus de *finetuning* d'un modèle d'ASR tout en utilisant un jeu de données plus petit.
L'objectif principal de cet exercice est de vous familiariser avec le processus plutôt que de vous attendre à des résultats de niveau production.
Nous avons délibérément fixé une métrique basse pour que vous puissiez l'atteindre, même avec des ressources limitées.

Voici les instructions :
* *Finetuner* le modèle `"openai/whisper-tiny"` en utilisant le sous-échantillon anglais américain ("en-US") du jeu de données `"PolyAI/minds14"`.
* Utilisez les premiers **450 exemples pour l'entraînement**, et le reste pour l'évaluation. Assurez-vous de mettre `num_proc=1` lors du pré-traitement du jeu de données en utilisant la méthode `.map` (ceci assurera que votre modèle est soumis correctement lors de l'évaluation).
* Pour évaluer le modèle, utilisez les métriques `wer` et `wer_ortho` comme décrit dans cette unité. Cependant, *ne convertissez pas* la métrique en pourcentages en la multipliant par 100 (par exemple, si WER est de 42%, nous nous attendons à voir la valeur de 0,42 dans cet exercice).

Une fois que vous avez *finetuné* un modèle, assurez-vous de le télécharger sur le 🤗 *Hub* avec les `kwargs` suivants :

```
kwargs = {
    "dataset_tags" : "PolyAI/minds14",
    "finetuned_from" : "openai/whisper-tiny",
    "tasks" : "automatic-speech-recognition",
}
```

Nous considérons cet exercice réussi si le WER normalisé (`wer`) de votre modèle est inférieur à **0.37**.

N'hésitez pas à construire une démo de votre modèle obtenu et à la partager sur Discord ! Si vous avez des questions, posez-les dans le canal ``#audio-study-group`.

### Ce que vous allez apprendre et construire
https://huggingface.co/learn/audio-course/fr/chapter5/introduction.md

# Ce que vous allez apprendre et construire

Dans cette section, nous verrons comment les *transformers* peuvent être utilisés pour convertir la parole en texte, une tâche connue sous le nom de _reconnaissance de la parole_.

    

La reconnaissance de la parole, également connue sous le nom de reconnaissance automatique de la parole (ASR pour *automatic speech recognition* ou STT pour *speech-to-text*), est l'une des tâches de traitement d'audio les plus populaires et les plus excitantes. Elle est utilisée dans un large éventail d'applications, y compris la dictée, les assistants vocaux, le sous-titrage vidéo et les transcriptions de réunions.

Vous avez probablement utilisé un système de reconnaissance de la parole  plusieurs fois auparavant sans vous en rendre compte. Considérez l'assistant numérique de votre smartphone (Siri, Google Assistant, Alexa). Lorsque vous utilisez ces assistants, la première chose qu'ils font est de transcrire votre discours parlé en texte écrit, prêt à être utilisé pour toutes les tâches en aval (comme trouver la météo 🌤️).

Jouez avec la démo de reconnaissance de la parole ci-dessous. Vous pouvez soit vous enregistrer à l'aide de votre microphone, soit glisser-déposer un échantillon audio pour en obtenir la transcription : 

 

La reconnaissance de la parole est une tâche difficile car elle nécessite une connaissance conjointe de l'audio et du texte. L'audio d'entrée peut contenir beaucoup de bruit de fond et être prononcé par des haut-parleurs avec des accents différents, ce qui rend l'identification de la parole difficile. Le texte écrit peut contenir des caractères qui n'ont pas de son acoustique, tels que la ponctuation, qui sont difficiles à déduire de l'audio seul. Ce sont tous des obstacles que nous devons surmonter lors de la construction de systèmes de efficaces!

Maintenant que nous avons défini notre tâche, nous pouvons commencer à l'examiner plus en détail. À la fin de cette unité, vous aurez une bonne compréhension fondamentale des différents modèles pré-entraînés disponibles et de la façon de les utiliser avec la 🤗 bibliothèque *Transformers*. Vous connaîtrez également la procédure pour *finetuner* un modèle sur un domaine ou une langue de votre choix, ce qui vous permettra de construire un système puissant pour toutes les tâches que vous rencontrez. Vous pourrez montrer votre modèle à vos amis et à votre famille en créant une démo prenant n'importe quel discours et le convertissant en texte !

Plus précisément, nous couvrirons les points suivants :

* [Modèles pré-entraînés pour la reconnaissance de la parole](asr_models)
* [Choix d'un jeu de données](choosing_dataset)
* [Évaluation et métriques pour la reconnaissance de la parole](evaluation)
* [Comment *finetuner* un système d'ASR avec l'API *Trainer*](fine-tuning)
* [Création d'une démo](demo)
* [Exercice pratique](hands_on)

### Construire une démo avec Gradio
https://huggingface.co/learn/audio-course/fr/chapter5/demo.md

# Construire une démo avec Gradio

Maintenant que nous avons *finetuné* un Whisper pour le Dhivehi, construisons une démo [Gradio](https://gradio.app) pour le présenter à la communauté !

La première chose à faire est de charger le *checkpoint* en utilisant la classe `pipeline()` - vous êtes maintenant familier avec la section sur les [modèles pré-entraînés](asr_models). Vous pouvez changer le `model_id` pour l'espace de noms de votre modèle *finetuné* sur le Hugging Face Hub, ou l'un des [modèles Whisper](https://huggingface.co/models?sort=downloads&search=openai%2Fwhisper-) pré-entraînés pour effectuer de la reconnaissance vocale à partir de zéro :

```python
from transformers import pipeline

model_id = (
    "sanchit-gandhi/whisper-small-dv"  # mettre à jour avec l'identifiant de votre modèle
)
pipe = pipeline("automatic-speech-recognition", model=model_id)
```

Deuxièmement, nous allons définir une fonction qui prend le chemin du fichier d'une entrée audio et le passe à travers le pipeline. 
Ici, le pipeline se charge automatiquement de charger le fichier audio, de le rééchantillonner à la bonne fréquence d'échantillonnage et d'exécuter l'inférence.
Nous pouvons alors simplement renvoyer le texte transcrit en tant que sortie de la fonction. 
Pour s'assurer que notre modèle puisse gérer des entrées audio de longueur arbitraire, nous activons le *chunking* comme décrit dans la section sur les [modèles pré-entraînés](asr_models) :

```python
def transcribe_speech(filepath):
    output = pipe(
        filepath,
        max_new_tokens=256,
        generate_kwargs={
            "task": "transcribe",
            "language": "sinhalese",
        },  # mettre à jour avec la langue sur laquelle vous avez finetuné
        chunk_length_s=30,
        batch_size=8,
    )
    return output["text"]
```

Nous allons utiliser la fonctionnalité [blocks](https://gradio.app/docs/#blocks) de Gradio pour lancer deux onglets sur notre démo : l'un pour la transcription par microphone et l'autre pour le chargement de fichiers.

```python
import gradio as gr

demo = gr.Blocks()

mic_transcribe = gr.Interface(
    fn=transcribe_speech,
    inputs=gr.Audio(source="microphone", type="filepath"),
    outputs=gr.outputs.Textbox(),
)

file_transcribe = gr.Interface(
    fn=transcribe_speech,
    inputs=gr.Audio(source="upload", type="filepath"),
    outputs=gr.outputs.Textbox(),
)
```

Enfin, nous lançons la démo en utilisant les deux blocs que nous venons de définir :

```python
with demo:
    gr.TabbedInterface(
        [mic_transcribe, file_transcribe],
        ["Transcrire le microphone", "Transcrire le fichier audio"],
    )

demo.launch(debug=True)
```

Ceci lancera une démo Gradio similaire à celle qui tourne sur le *Space* suivant :

Si vous souhaitez héberger votre démo sur le *Hub*, vous pouvez utiliser ce *Space* comme exemple pour votre modèle *finetuné*.

Cliquez sur le lien pour dupliquer le *Space* sur votre compte : [https://huggingface.co/spaces/course-demos/whisper-small?duplicate=true](https://huggingface.co/spaces/course-demos/whisper-small?duplicate=true).

Nous vous recommandons de donner à votre *Space* un nom similaire à celui de votre modèle *finetuné* (par exemple whisper-small-dv-demo) et de régler la visibilité sur *Public*.

Une fois que vous avez dupliqué le *Space* sur votre compte, cliquez sur *Files and versions* -> *app.py* -> *edit*. Changez ensuite l'identifiant du modèle par le votre (ligne 6). 
Descendez au bas de la page et cliquez sur *Commit changes to main*.
La démo redémarre, cette fois en utilisant votre modèle *finetuné*. Vous pouvez partager cette démo avec vos amis et votre famille afin qu'ils puissent utiliser le modèle que vous avez entraîné !

Alternativement, vous pouvez consulter notre tutoriel vidéo pour mieux comprendre comment dupliquer un *Space* : [vidéo YouTube](https://www.youtube.com/watch?v=VQYuvl6-9VE).

### Lectures et ressources complémentaires
https://huggingface.co/learn/audio-course/fr/chapter5/supplemental_reading.md

# Lectures et ressources complémentaires

Cette unité est une introduction pratique à la reconnaissance automatique de la parole, l'une des tâches les plus populaires dans le domaine audio.
Vous voulez en savoir plus ? Vous trouverez ici des ressources supplémentaires (en anglais) qui vous aideront à approfondir votre compréhension du sujet et à améliorer votre expérience d'apprentissage.

* [Whisper Talk](https://www.youtube.com/live/fZMiD8sDzzg?feature=share) par Jong Wook Kim : une présentation du modèle Whisper, expliquant la motivation, l'architecture, l'entraînement et les résultats, par l'auteur du modèle.
* [End-to-End Speech Benchmark (ESB)](https://arxiv.org/abs/2210.13352) : un papier qui plaide en faveur de l'utilisation du WER orthographique plutôt que du WER normalisé pour l'évaluation des systèmes de reconnaissance automatique de la parole et qui présente un benchmark correspondant.
* [Fine-Tuning Whisper for Multilingual ASR](https://huggingface.co/blog/fine-tune-whisper) : un article de blog qui explique le fonctionnement du modèle Whisper de manière plus détaillée, ainsi que les étapes de pré- et post-traitement impliquées dans l'extracteur de caractéristiques et le *tokenizer*.
* [Fine-tuning MMS Adapter Models for Multi-Lingual ASR](https://huggingface.co/blog/mms_adapters) : un guide complet pour *finetuner* les nouveaux modèles de reconnaissance vocale [MMS](https://ai.facebook.com/blog/multilingual-model-speech-recognition/) de Meta, en gelant les poids du modèle de base et en ne finetunant qu'un petit nombre de couches.
* Boosting Wav2Vec2 with n-grams in 🤗 Transformers](https://huggingface.co/blog/wav2vec2-with-ngram) : un article de blog pour combiner les modèles CTC avec des modèles de langage externes pour combattre les erreurs d'orthographe et de ponctuation.

### Modèles pré-entraînés pour la reconnaissance automatique de la parole
https://huggingface.co/learn/audio-course/fr/chapter5/asr_models.md

# Modèles pré-entraînés pour la reconnaissance automatique de la parole

Dans cette section, nous verrons comment utiliser le `pipeline()` pour tirer parti des modèles pré-entraînés pour la reconnaissance automatique de la parole. Dans l’[unité 2](.. /chapter2/asr_pipeline), nous avons introduit le `pipeline()` comme un moyen facile d'exécuter des tâches de reconnaissance de la parole, avec tout le prétraitement et le post-traitement gérés sous le capot et la flexibilité d'expérimenter rapidement avec n'importe quel *checkpoint* pré-entraîné disponible sur le *Hub*.
Dans cette unité, nous irons plus loin et explorerons les différents attributs des modèles de reconnaissance automatique de la parole et comment nous pouvons les utiliser pour aborder une gamme de tâches différentes.

Comme détaillé dans l'unité 3, le modèle de reconnaissance automatique de la parole se divise généralement dans l'une des deux catégories suivantes :

1. Modèle avec Classification temporelle connexionniste (CTC) : modèles avec que l’encodeur du *transformer* avec une tête de classification linéaire sur le dessus
2. Modèle de séquence à séquence (Seq2Seq) : modèles encodeur-décodeur, avec un mécanisme d'attention croisée entre l'encodeur et le décodeur

Avant 2022, la variante avec CTC était la plus populaire des deux architectures, avec des modèles tels que Wav2Vec2, HuBERT et XLSR réalisant des percées dans le paradigme de pré-entraînement / *finetuning* de la parole. 
De grandes entreprises, telles que Meta et Microsoft, ont pré-entraîné l'encodeur sur de grandes quantités de données audio non étiquetées pendant plusieurs jours ou semaines. 
Les utilisateurs pouvent ensuite prendre un *checkpoint* pré-entraîné et le finetuner avec une tête CTC sur à peine **10 minutes** de données audio étiquetées pour obtenir de solides performances sur une tâche en aval de reconnaissance automatique de la parole.
Cependant, les modèles CTC ont des lacunes. L'ajout d'une simple couche linéaire à un encodeur donne un petit modèle global rapide, mais peut être sujet à des fautes d'orthographe phonétiques. Nous allons le démontrer ci-dessous pour le modèle Wav2Vec2.

## Sonder les modèles CTC

Chargeons un petit extrait du jeu de données [LibriSpeech ASR](hf-internal-testing/librispeech_asr_dummy) pour démontrer les capacités de transcription de Wav2Vec2 :

```python
from datasets import load_dataset

dataset = load_dataset(
    "hf-internal-testing/librispeech_asr_dummy", "clean", split="validation"
)
dataset
```

**Sortie :**

```
Dataset({
    features: ['file', 'audio', 'text', 'speaker_id', 'chapter_id', 'id'],
    num_rows: 73
})
```

Nous pouvons choisir l'un des 73 échantillons audio et en inspecter l’audio ainsi que la transcription :

```python
from IPython.display import Audio

sample = dataset[2]

print(sample["text"])
Audio(sample["audio"]["array"], rate=sample["audio"]["sampling_rate"])
```

**Sortie :**

```
HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH CHRISTMAS AND ROAST BEEF LOOMING BEFORE US SIMILES DRAWN FROM EATING AND ITS RESULTS OCCUR MOST READILY TO THE MIND
```

Noël et rôti de bœuf, ça sonne bien! 🎄 Après avoir choisi un échantillon de données, nous chargeons maintenant un *checkpoint* *finetuné* dans le `pipeline()`. 
Pour cela, nous utiliserons le *checkpoint* officiel [base Wav2Vec2] (facebook/wav2vec2-base-100h) *finetuné* sur 100 heures de données LibriSpeech :

```python
from transformers import pipeline

pipe = pipeline("automatic-speech-recognition", model="facebook/wav2vec2-base-100h")
```

Ensuite, nous allons prendre un exemple du jeu de données et transmettre ses données brutes au pipeline. 
Puisque le pipeline *consomme* n'importe quel dictionnaire que nous lui passons (ce qui signifie qu'il ne peut pas être réutilisé), nous transmettrons une copie des données. De cette façon, nous pouvons réutiliser en toute sécurité le même échantillon audio dans les exemples suivants:

```python
pipe(sample["audio"].copy())
{
    "text": "HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH CHRISTMAUS AND ROSE BEEF LOOMING BEFORE US SIMALYIS DRAWN FROM EATING AND ITS RESULTS OCCUR MOST READILY TO THE MIND"
}
```

Nous pouvons voir que le modèle Wav2Vec2 fait un assez bon travail pour transcrire cet échantillon. A première vue, il semble généralement correct.
Mettons la cible et la prédiction côte à côte et mettons en évidence les différences:

```
Target:      HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH CHRISTMAS AND ROAST BEEF LOOMING BEFORE US SIMILES DRAWN FROM EATING AND ITS RESULTS OCCUR MOST READILY TO THE MIND
Prediction:  HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH **CHRISTMAUS** AND **ROSE** BEEF LOOMING BEFORE US **SIMALYIS** DRAWN FROM EATING AND ITS RESULTS OCCUR MOST READILY TO THE MIND
```

En comparant le texte cible à la transcription prévue, nous pouvons voir que tous les mots _sonnent_ correctement mais que certains ne sont pas orthographiés avec précision. Par exemple :

* _CHRISTMAUS_ vs. _CHRISTMAS_
* _ROSE_ vs. _ROAST_
* _SIMALYIS_ vs. _SIMILES_
Cela met en évidence les lacunes d'un modèle CTC. Un modèle CTC est essentiellement uniquement un modèle « acoustique» : il se compose d'un encodeur qui forme des représentations d'états cachés à partir des entrées audio, et d'une couche linéaire qui associe les états cachés aux caractères :

     

Cela signifie que le système base presque entièrement sa prédiction sur l'entrée acoustique qui lui a été donnée (les sons phonétiques de l'audio), et a donc tendance à transcrire l'audio de manière phonétique.
Il donne moins d'importance au contexte de modélisation linguistique des lettres précédentes et successives, et est donc sujet aux fautes d'orthographe phonétique. 
Un modèle plus intelligent identifierait que _CHRISTMAUS_ n'est pas un mot valide dans le vocabulaire anglais, et le corrigerait en _CHRISTMAS_ lors de ses prédictions. Il nous manque également deux grandes fonctionnalités dans notre prédiction, la casse et la ponctuation, ce qui limite l'utilité des transcriptions du modèle aux applications réelles.

## Passage à Seq2Seq

Comme indiqué dans l'unité 3, les modèles Seq2Seq sont formés d'un codeur et d'un décodeur reliés par un mécanisme d'attention croisée. L'encodeur joue le même rôle qu'auparavant, calculant des représentations d’états cachés des entrées audio, tandis que le décodeur joue le rôle d'un **modèle de langage**. Le décodeur traite toute la séquence de représentations d’états cachés de l'encodeur et génère les transcriptions de texte correspondantes. Avec le contexte global de l'entrée audio, le décodeur est capable d'utiliser le contexte du modèle de langage lorsqu'il fait ses prédictions, corrigeant les fautes d'orthographe à la volée et contournant ainsi le problème des prédictions phonétiques.
Les modèles Seq2Seq présentent deux inconvénients :
1. Ils sont intrinsèquement plus lents lors du décodage puisqu’il se produit une étape à la fois, plutôt que tout à la fois 2. Ils nécessitent beaucoup plus de données d'entraînement pour converger

Le besoin de grandes quantités de données d'apprentissage a été un goulot d'étranglement dans l'avancement des architectures Seq2Seq pour la parole. Les données audios étiquetées sont difficiles à obtenir, les plus grands jeux de données annotées à l'époque ne totalisant que 10 000 heures. Tout cela a changé en 2022 avec la sortie de **Whisper**. Whisper est un modèle pré-entraîné pour la reconnaissance automatique de la parole publié en [septembre 2022](https://openai.com/blog/whisper/) par Alec Radford et al. d'OpenAI. Contrairement à ses prédécesseurs CTC, qui étaient entièrement pré-entraînés sur des données audio **non étiquetées**, Whisper est pré-entraîné sur une grande quantité de données de transcription audio **étiquetées**, 680 000 heures pour être précis.
Il s'agit d'un ordre de grandeur de données plus grand que les données audio non étiquetées utilisées pour entraîner Wav2Vec 2.0 (60 000 heures). De plus, 117 000 heures de ces données de pré-entraînement sont des données multilingues. Il en résulte des *checkpoints* qui peuvent être appliqués à plus de 96 langues, dont beaucoup sont considérées comme _à faible ressource_.
Lorsqu'ils sont passés à l'échelle, les modèles Whisper démontrent une forte capacité à généraliser sur de nombreux jeux de données et domaines. Obtenant des résultats compétitifs de pointe, avec un taux d'erreur de mots (WER) de près de 3% sur le sous-ensemble de test LibriSpeech et de 4,7% WER  sur le sous-ensemble de test TED-LIUM (_cf._ Tableau 8 du [papier de Whisper](https://cdn.openai.com/papers/whisper.pdf)).
La capacité de Whisper à gérer de longs échantillons audio, sa robustesse au bruit et sa capacité à prédire les transcriptions en casse et ponctuées revêtent une importance particulière. Cela en fait un candidat viable pour les systèmes de reconnaissance automatique de la parole du monde réel.
Le reste de cette section vous montrera comment utiliser les modèles Whisper pré-entraînés pour la reconnaissance automatique de la parole à l'aide de 🤗 *Transformers*. Dans de nombreuses situations, les *checkpoints* pré-entraînés sont extrêmement performants et donnent d'excellents résultats, nous vous encourageons donc à essayer de les utiliser comme première étape pour résoudre tout problème de reconnaissance automatique de la parole.
Grâce à un *finetuning*, les *checkpoints* peuvent être adaptés à des jeux de données et à des langues spécifiques afin d'améliorer encore ces résultats. Nous montrerons comment faire cela dans la section sur [le *finetuning*](fine-tuning).
Whisper est disponible en cinq tailles différentes de modèles. Les quatre plus petits sont entraînés soit sur des données en anglais soit sur des données multilingues. Le *checkpoint* le plus grand est uniquement multilingue. Les neuf *checkpoints* pré-entraînés sont disponibles sur le [*Hub*](https://huggingface.co/models?search=openai/whisper). Ils sont résumés dans le tableau suivant. « VRAM » indique la mémoire GPU requise pour exécuter le modèle avec une taille de batch minimale de 1. « *Rel Speed* » est la vitesse relative d'un *checkpoint* par rapport au plus grand modèle.
Sur la base de ces informations, vous pouvez sélectionner le *checkpoint* le plus adapté à votre matériel.

| Taille   | Paramètres | VRAM / Go | *Rel Speed* | Anglais                                         | Multilingue                                        |
|--------|------------|-----------|-----------|------------------------------------------------------|-----------------------------------------------------|
| tiny   | 39 M       | 1.4       | 32        | [✓](https://huggingface.co/openai/whisper-tiny.en)   | [✓](https://huggingface.co/openai/whisper-tiny)     |
| base   | 74 M       | 1.5       | 16        | [✓](https://huggingface.co/openai/whisper-base.en)   | [✓](https://huggingface.co/openai/whisper-base)     |
| small  | 244 M      | 2.3       | 6         | [✓](https://huggingface.co/openai/whisper-small.en)  | [✓](https://huggingface.co/openai/whisper-small)    |
| medium | 769 M      | 4.2       | 2         | [✓](https://huggingface.co/openai/whisper-medium.en) | [✓](https://huggingface.co/openai/whisper-medium)   |
| large  | 1550 M     | 7.5       | 1         | x                                                    | [✓](https://huggingface.co/openai/whisper-large-v2) |

Chargeons le [Whisper Base](https://huggingface.co/openai/whisper-base), qui est de taille comparable au Wav2Vec2 que nous avons utilisé précédemment. Anticipant notre passage à la reconnaissance automatique de la parole multilingue, nous allons charger la variante multilingue du *checkpoint* de base. Nous chargons également le modèle sur le GPU s'il est disponible, ou sur le CPU dans le cas contraire. Le `pipeline()` se chargera ensuite de déplacer toutes les entrées / sorties du CPU vers le GPU selon les besoins:

```python
import torch
from transformers import pipeline

device = "cuda:0" if torch.cuda.is_available() else "cpu"
pipe = pipeline(
    "automatic-speech-recognition", model="openai/whisper-base", device=device
)
```

Bien, maintenant, transcrivons l'audio comme avant. Le seul changement que nous apportons est de passer un argument supplémentaire, `max_new_tokens`, qui indique au modèle le nombre maximum de *tokens* à générer lors de sa prédiction :

```python
pipe(sample["audio"], max_new_tokens=256)
```

**Sortie :**

```
{'text': ' He tells us that at this festive season of the year, with Christmas and roast beef looming before us, similarly is drawn from eating and its results occur most readily to the mind.'}
```

La première chose que vous remarquerez est la présence de la casse et de la ponctuation. Cela rend immédiatement la transcription plus facile à lire par rapport à la transcription non casée et non ponctuée de Wav2Vec2. Mettons la transcription côte à côte avec la cible :

```
Target:     HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH CHRISTMAS AND ROAST BEEF LOOMING BEFORE US SIMILES DRAWN FROM EATING AND ITS RESULTS OCCUR MOST READILY TO THE MIND
Prediction: He tells us that at this festive season of the year, with **Christmas** and **roast** beef looming before us, **similarly** is drawn from eating and its results occur most readily to the mind.
```

Whisper a fait un excellent travail pour corriger les erreurs phonétiques que nous avons vues avec Wav2Vec2 : _Christmas_ et _roast_ sont orthographiés correctement. Nous voyons que le modèle a encore du mal avec _SIMILES_, étant incorrectement transcrit comme _similarly_, mais cette fois la prédiction est un mot valide du vocabulaire anglais. L'utilisation d'un Whisper plus grand peut aider à réduire davantage les erreurs de transcription, au détriment d'un calcul plus important et d'un temps de transcription plus long.
On nous a promis un modèle capable de gérer 96 langues, alors passons à de la reconnaissance automatique multilingue 🌎 !
Le jeu de données [Multilingual LibriSpeech](https://huggingface.co/datasets/facebook/multilingual_librispeech) (MLS) est l'équivalent multilingue du jeu de données LibriSpeech, avec des données audio étiquetées en six langues. Nous allons charger un échantillon de l’échantillon espagnol de MLS, en utilisant le mode _streaming_ afin de ne pas avoir à télécharger l'ensemble de données :

```python
dataset = load_dataset(
    "facebook/multilingual_librispeech", "spanish", split="validation", streaming=True
)
sample = next(iter(dataset))
```

Encore une fois, nous allons inspecter la transcription du texte et écouter le segment audio:

```python
print(sample["text"])
Audio(sample["audio"]["array"], rate=sample["audio"]["sampling_rate"])
```

**Sortie :**

```
entonces te delelitarás en jehová y yo te haré subir sobre las alturas de la tierra y te daré á comer la heredad de jacob tu padre porque la boca de jehová lo ha hablado
```

C'est le texte cible que nous visons avec notre transcription Whisper. Bien que nous sachions maintenant que nous pouvons probablement faire mieux, puisque notre modèle va aussi prédire la ponctuation et la casse, qui ne sont pas présents dans la référence. Transmettons l'échantillon audio au pipeline pour obtenir notre prédiction de texte. Une chose à noter est que le pipeline _consomme_ le dictionnaire des entrées audio que nous entrons, ce qui signifie que le dictionnaire ne peut pas être réutilisé. Pour contourner ce problème, nous allons passer une _copie_ de l'échantillon audio, afin de pouvoir réutiliser le même échantillon audio dans les exemples de code suivants :

```python
pipe(sample["audio"].copy(), max_new_tokens=256, generate_kwargs={"task": "transcribe"})
```

**Sortie :**

```
{'text': ' Entonces te deleitarás en Jehová y yo te haré subir sobre las alturas de la tierra y te daré a comer la heredad de Jacob tu padre porque la boca de Jehová lo ha hablado.'}
```

Super, cela ressemble énormément à notre texte de référence (sans doute mieux car il a une ponctuation et une casse !). Vous remarquerez que nous avons transféré `"task"` en tant que _generate kwarg_. Définir la `"task"` à `"transcribe"` oblige Whisper à effectuer la tâche de reconnaissance de la parole, où l'audio est transcrit dans la même langue que le discours a été prononcé. Whisper est également capable d'effectuer la tâche étroitement liée de traduction de la parole, où l'audio en espagnol peut être traduit en texte en anglais. Pour y parvenir, nous définissons la `"task"` sur `"translate"` :

```python
pipe(sample["audio"], max_new_tokens=256, generate_kwargs={"task": "translate"})
```

**Sortie :**

```
{'text': ' So you will choose in Jehovah and I will raise you on the heights of the earth and I will give you the honor of Jacob to your father because the voice of Jehovah has spoken to you.'}
```

Maintenant que nous savons que nous pouvons basculer entre la reconnaissance automatique de la parole et la traduction de la parole, nous pouvons choisir notre tâche en fonction de nos besoins. Soit nous reconnaissons l'audio dans la langue X vers le texte dans la même langue X (par exemple, l'audio espagnol vers le texte espagnol), soit nous traduisons de l'audio dans n'importe quelle langue X vers du texte en anglais (par exemple, l'audio espagnol vers le texte anglais).
Pour en savoir plus sur la façon dont l'argument `"task"` est utilisé pour contrôler les propriétés du texte généré, reportez-vous à la [carte de modèle](https://huggingface.co/openai/whisper-base#usage) pour le modèle Whisper base.

## Longue transcription et horodatage

Jusqu'à présent, nous nous sommes concentrés sur la transcription de courts échantillons audio de moins de 30 secondes. Nous avons mentionné que l'un des attraits de Whisper était sa capacité à travailler sur de longs échantillons audio. Nous allons nous attaquer à cette tâche ici !
Créons un long fichier audio en concaténant des échantillons successifs à partir du jeu de données MLS. Étant donné que MLS est organisé en divisant de longs enregistrements de livres audio en segments plus courts, la concaténation d'échantillons est un moyen de reconstruire des passages de livres audio plus longs. Par conséquent, l'audio résultant doit être cohérent sur l'ensemble de l'échantillon. Nous allons définir notre durée audio cible sur 5 minutes et arrêter de concaténer des échantillons une fois que nous aurons atteint cette valeur :

```python
import numpy as np

target_length_in_m = 5

# convertir les minutes en secondes (* 60) en nombre d'échantillons (* taux d'échantillonnage)
sampling_rate = pipe.feature_extractor.sampling_rate
target_length_in_samples = target_length_in_m * 60 * sampling_rate

# itérer sur notre jeu de données en streaming, en concaténant les échantillons jusqu'à ce que nous atteignions notre cible
long_audio = []
for sample in dataset:
    long_audio.extend(sample["audio"]["array"])
    if len(long_audio) > target_length_in_samples:
        break

long_audio = np.asarray(long_audio)

# Résultat
seconds = len(long_audio) / 16000
minutes, seconds = divmod(seconds, 60)
print(f"Length of audio sample is {minutes} minutes {seconds:.2f} seconds")
```

**Sortie :**

```
Length of audio sample is 5.0 minutes 17.22 seconds
```

5 minutes et 17 secondes d'audio à transcrire. Le transfert de ce long échantillon audio directement vers le modèle pose deux problèmes :
1. Whisper est intrinsèquement conçu pour fonctionner avec des échantillons de 30 secondes. Tout ce qui est inférieur à 30s est rembourré à 30s avec du silence, et tout ce qui dépasse 30s est tronqué à 30s en coupant l'audio excédentaire. Donc si nous passons notre audio directement, nous n'obtiendrons la transcription que pour les 30 premières secondes
2. La mémoire dans un *transformer* évolue quadratiquement avec la longueur de séquence a : doubler la longueur d'entrée quadruple le besoin en mémoire, de sorte que le passage de fichiers audio très longs entraînera inévitablement une erreur de mémoire insuffisante (OOM : out-of-memory)
La transcription de longs audio fonctionne dans 🤗 *Transformers* en segmentant l'audio d'entrée en segments plus petits et plus faciles à gérer.
Chaque segment a un petit chevauchement avec le précédent. Cela nous permet de recoudre avec précision les segments aux bornes, car nous pouvons trouver le chevauchement entre les segments et fusionner les transcriptions en conséquence :

     

L'avantage de segmenter les échantillons est que nous n'avons pas besoin du résultat du bloc \\( i \\) pour transcrire le morceau suivant \\( i + 1 \\). La couture est effectuée après que nous ayons transcrit tous les morceaux aux bornes des morceaux. Donc peu importe l'ordre dans lequel nous transcrivons les morceaux. L'algorithme est entièrement **sans états**, donc nous pouvons même faire du découpage sur \\( i + 1 \\) en même temps que du découpage sur \\( i \\) ! Cela nous permet de former des _batch_ de morceaux et de les exécuter dans le modèle en parallèle, offrant une grande accélération de calcul par rapport à leur transcription séquentielle. Pour en savoir plus sur la segmentation d’audio dans 🤗 *Transformers*, vous pouvez vous référer à cet [article de blog] (https://huggingface.co/blog/asr-chunking) (en anglais).
Pour activer les longues transcriptions, nous devons ajouter un argument supplémentaire lorsque nous appelons le pipeline. Cet argument, `chunk_length_s`, contrôle la longueur des segments divisés en secondes. Pour Whisper, des morceaux de 30 secondes sont optimaux, car cela correspond à la longueur d'entrée attendue par Whisper.
Pour activer le traitement par batch, nous devons passer l'argument `batch_size` au pipeline. En mettant tout cela ensemble, nous pouvons transcrire le long échantillon audio comme suit:

```python
pipe(
    long_audio,
    max_new_tokens=256,
    generate_kwargs={"task": "transcribe"},
    chunk_length_s=30,
    batch_size=8,
)
```

**Sortie :**

```
{'text': ' Entonces te deleitarás en Jehová, y yo te haré subir sobre las alturas de la tierra, y te daré a comer la
heredad de Jacob tu padre, porque la boca de Jehová lo ha hablado. nosotros curados. Todos nosotros nos descarriamos
como bejas, cada cual se apartó por su camino, mas Jehová cargó en él el pecado de todos nosotros...
``` 

Nous n’affichons pas toute la sortie ici car elle est assez longue (312 mots au total). Sur un GPU V100 de 16 Go, vous pouvez vous attendre à ce que la ligne ci-dessus prenne environ 3,45 secondes à s’éxécuter, ce qui est assez bon pour un échantillon audio de 317 secondes. Sur un CPU, attendez-vous à plus de 30 secondes.
Whisper est également capable de prédire les _horodatages_ au niveau du segment pour les données audio. Ces horodatages indiquent l'heure de début et de fin d'un court passage audio et sont particulièrement utiles pour aligner une transcription avec l'audio d'entrée. Supposons que nous voulions fournir des sous-titres pour une vidéo. Nous avons besoin de ces horodatages pour savoir quelle partie de la transcription correspond à un certain segment de vidéo, afin d'afficher la transcription correcte pour cette heure.
L'activation de la prédiction d'horodatage est simple, il suffit de définir l'argument `return_timestamps=True`. Les horodatages sont compatibles avec les méthodes de segmentation et de traitement par batchs que nous avons utilisées précédemment. Nous pouvons donc simplement ajouter l'argument timestamp à notre code précédent :

```python
pipe(
    long_audio,
    max_new_tokens=256,
    generate_kwargs={"task": "transcribe"},
    chunk_length_s=30,
    batch_size=8,
    return_timestamps=True,
)["chunks"]
``` 

**Sortie :**

```
[{'timestamp': (0.0, 26.4),
  'text': ' Entonces te deleitarás en Jehová, y yo te haré subir sobre las alturas de la tierra, y te daré a comer la heredad de Jacob tu padre, porque la boca de Jehová lo ha hablado. nosotros curados. Todos nosotros nos descarriamos como bejas, cada cual se apartó por su camino,'},
 {'timestamp': (26.4, 32.48),
  'text': ' mas Jehová cargó en él el pecado de todos nosotros. No es que partas tu pan con el'},
 {'timestamp': (32.48, 38.4),
  'text': ' hambriento y a los hombres herrantes metas en casa, que cuando vieres al desnudo lo cubras y no'},
 ...
``` 

Et le tour est joué ! Nous avons notre texte prédit ainsi que les horodatages correspondants.

## Résumé

Whisper est un modèle pré-entraîné solide pour la reconnaissance automatique de la parole et la traduction. Par rapport à Wav2Vec2, il a une plus grande précision de transcription, avec des sorties qui contiennent la ponctuation et la casse. Il peut être utilisé pour transcrire la parole en anglais ainsi que dans 96 autres langues, à la fois sur des segments audio courts et des segments plus longs par le biais de  la segmentation. Ces attributs en font un modèle viable pour de nombreuses tâches de reconnaissance automatique de la parole et de traduction sans avoir besoin d'être *finetuné*. La méthode `pipeline()` fournit un moyen facile d'inférer en une ligne de code avec un contrôle sur les prédictions générées.
Bien que le modèle Whisper fonctionne extrêmement bien sur de nombreuses langues à ressources élevées, il a une précision de transcription et de traduction plus faible sur les langues à faibles ressources, c'est-à-dire celles pour lesquelles les données d'apprentissage sont moins facilement disponibles. Les performances varient également selon les accents et dialectes de certaines langues, y compris une précision moindre pour les locuteurs de différents sexes, races, âges ou autres critères démographiques (_cf._ le papier de [Whisper](https://arxiv.org/pdf/2212.04356.pdf)).
Pour améliorer les performances sur les langues, les accents ou les dialectes à faibles ressources, nous pouvons prendre le modèle Whisper pré-entraîné et l'entraîner sur un petit corpus de données sélectionnées de manière appropriée, dans un processus appelé _*finetuning*_. Nous montrerons qu'avec seulement dix heures de données supplémentaires, nous pouvons améliorer les performances du modèle Whisper de plus de 100% sur une langue à faibles ressources. Dans la section suivante, nous aborderons le processus de sélection d'un jeu de données à *finetuner*.

### Choisir un jeu de données
https://huggingface.co/learn/audio-course/fr/chapter5/choosing_dataset.md

# Choisir un jeu de données

Comme pour tout problème d'apprentissage automatique, la qualité de notre modèle dépend des données sur lesquelles nous l'entraînons. Les jeux de données de reconnaissance vocale varient considérablement dans la façon dont ils sont gérés et dans les domaines qu'ils couvrent. Pour choisir le bon jeu de données, nous devons faire correspondre nos critères aux caractéristiques offertes par un jeu de données.

Avant de choisir un jeu de données, nous devons d'abord comprendre les principales caractéristiques qui le définissent.

## Caractéristiques des jeux de données vocaux

### 1. Nombre d'heures

En termes simples, le nombre d'heures d'entraînement indique la taille du jeu de données. Il est analogue au nombre d'exemples d'entraînement dans un jeu de données de NLP. Toutefois, les jeux de données plus importants ne sont pas nécessairement meilleurs. Si nous voulons un modèle qui généralise bien, nous avons besoin d'un jeu de données **varié** avec beaucoup de locuteurs, de domaines et de styles d'expression différents.

### 2. Domaine

Le domaine est l'endroit d'où proviennent les données, qu'il s'agisse de livres audio, de podcasts, de YouTube ou de réunions professionnelles.
Chaque domaine a une distribution de données différente. Par exemple, les livres audio sont enregistrés dans des conditions de studio, en haute qualité (sans bruit de fond) et le texte est tiré de la littérature. En revanche, pour YouTube, l'audio contient probablement plus de bruits de fond et un style de discours plus informel.

Nous devons faire correspondre notre domaine aux conditions que nous prévoyons au moment de l'inférence. Par exemple, si nous entraînons notre modèle sur des livres audio, nous ne pouvons pas nous attendre à ce qu'il soit performant dans des environnements bruyants.

### 3. Style d'élocution

Le style d'élocution peut être classé dans l'une des deux catégories suivantes :

* narré : lu à partir d'un script
* spontané : discours non scénarisé, conversationnel.

Les données audio et textuelles reflètent le style d'élocution. Étant donné que le texte narré est écrit, il a tendance à être prononcé de manière articulée et sans erreur :

```
“Consider the task of training a model on a speech recognition dataset”
```

Dans le cas d'un discours spontané, on peut s'attendre à un style plus familier, avec des répétitions, des hésitations et des faux départs :

```
“Let’s uhh let's take a look at how you'd go about training a model on uhm a sp- speech recognition dataset”
```

### 4. Style de transcription

Le style de transcription indique si le texte cible comporte de la ponctuation, de la casse ou les deux. Si nous voulons qu'un système génère un texte entièrement formaté pouvant être utilisé pour la transcription d'une publication ou d'une réunion, nous avons besoin de données d'entraînement comportant de la ponctuation et des majuscules. Si nous avons simplement besoin des mots prononcés dans une structure non formatée, ni la ponctuation ni la casse ne sont nécessaires.
Dans ce cas, nous pouvons soit choisir un jeu de données sans ponctuation ni casse, soit choisir un jeu de données avec ponctuation et casse, puis les supprimer du texte cible par le biais d'un prétraitement.

## Résumé de jeux de données sur le *Hub*

Voici un résumé de jeux de données de reconnaissance vocale en anglais les plus populaires sur le *Hub* :

| Jeu de données                                                                          | Heures d'entraînement | Domaine                      | Style d'élocution        | Casse | Ponctuation | Licence         | Usage recommandé                 |
|-----------------------------------------------------------------------------------------|-------------|-----------------------------|-----------------------|--------|-------------|-----------------|----------------------------------|
| [LibriSpeech](https://huggingface.co/datasets/librispeech_asr)                          | 960         | Audiobook                   | Narrated              | ❌      | ❌           | CC-BY-4.0       | Academic benchmarks              |
| [Common Voice 11](https://huggingface.co/datasets/mozilla-foundation/common_voice_11_0) | 3000        | Wikipedia                   | Narrated              | ✅      | ✅           | CC0-1.0         | Non-native speakers              |
| [VoxPopuli](https://huggingface.co/datasets/facebook/voxpopuli)                         | 540         | European Parliament         | Oratory               | ❌      | ✅           | CC0             | Non-native speakers              |
| [TED-LIUM](https://huggingface.co/datasets/LIUM/tedlium)                                | 450         | TED talks                   | Oratory               | ❌      | ❌           | CC-BY-NC-ND 3.0 | Technical topics                 |
| [GigaSpeech](https://huggingface.co/datasets/speechcolab/gigaspeech)                    | 10000       | Audiobook, podcast, YouTube | Narrated, spontaneous | ❌      | ✅           | apache-2.0      | Robustness over multiple domains |
| [SPGISpeech](https://huggingface.co/datasets/kensho/spgispeech)                         | 5000        | Financial meetings          | Oratory, spontaneous  | ✅      | ✅           | User Agreement  | Fully formatted transcriptions   |
| [Earnings-22](https://huggingface.co/datasets/revdotcom/earnings22)                     | 119         | Financial meetings          | Oratory, spontaneous  | ✅      | ✅           | CC-BY-SA-4.0    | Diversity of accents             |
| [AMI](https://huggingface.co/datasets/edinburghcstr/ami)                                | 100         | Meetings                    | Spontaneous           | ✅      | ✅           | CC-BY-4.0       | Noisy speech conditions          |

Ce tableau sert de référence pour sélectionner un jeu de données en fonction de vos critères. Vous trouverez ci-dessous un tableau équivalent pour la reconnaissance vocale multilingue. Notez que nous omettons la colonne des heures d'entraînement, qui varie en fonction de la langue pour chaque jeu de données, et que nous la remplaçons par le nombre de langues par jeu de données :

| Jeu de données                                                                                | Langues | Domaine                                | Style d'élocution | Casse | Ponctuation | Licence   | Usage recommandé        |
|-----------------------------------------------------------------------------------------------|-----------|---------------------------------------|----------------|--------|-------------|-----------|-------------------------|
| [Multilingual LibriSpeech](https://huggingface.co/datasets/facebook/multilingual_librispeech) | 6         | Audiobooks                            | Narrated       | ❌      | ❌           | CC-BY-4.0 | Academic benchmarks     |
| [Common Voice 13](https://huggingface.co/datasets/mozilla-foundation/common_voice_13_0)       | 108       | Wikipedia text & crowd-sourced speech | Narrated       | ✅      | ✅           | CC0-1.0   | Diverse speaker set     |
| [VoxPopuli](https://huggingface.co/datasets/facebook/voxpopuli)                               | 15        | European Parliament recordings        | Spontaneous    | ❌      | ✅           | CC0       | European languages      |
| [FLEURS](https://huggingface.co/datasets/google/fleurs)                                       | 101       | European Parliament recordings        | Spontaneous    | ❌      | ❌           | CC-BY-4.0 | Multilingual evaluation |

Pour une analyse détaillée des jeux de données audio couverts dans les deux tableaux, consultez l'article de blog [*A Complete Guide to Audio Datasets*](https://huggingface.co/blog/audio-datasets#a-tour-of-audio-datasets-on-the-hub) (en anglais).
Bien qu'il existe plus de 180 jeux de données de reconnaissance vocale sur le *Hub*, il est possible qu'aucun jeu de données ne corresponde à vos besoins. Dans ce cas, il est également possible d'utiliser vos propres données audio avec 🤗 *Datasets*. Pour créer un jeu de données audio personnalisé, reportez-vous au guide [Créer un jeu de données audio](https://huggingface.co/docs/datasets/audio_dataset). Lorsque vous créez un jeu de données audio personnalisé, pensez à partager le jeu de données final sur le *Hub* afin que d'autres membres de la communauté puissent bénéficier de vos efforts et apprécieront votre travail comme vous appréciez le leur.

Très bien ! Maintenant que nous avons passé en revue tous les critères de sélection d'un jeu de données d'ASR, choisissons-en un pour les besoins de ce tutoriel.
Nous savons que Whisper fait déjà un très bon travail de transcription de données dans des langues à hautes ressources (telles que l'anglais et l'espagnol), nous allons donc nous concentrer sur la transcription multilingue à faibles ressources. Nous voulons conserver la capacité de Whisper à prédire la ponctuation et la casse, donc il semble, d'après le deuxième tableau, que Common Voice 13 est un excellent jeu de données candidat !

## Common Voice 13

Common Voice 13 est un jeu de données *crown-sourcés* dans lequel des locuteurs enregistrent des textes tirés de Wikipédia dans différentes langues. Il fait partie de la série Common Voice, une collection de jeux de données publiés par la Fondation Mozilla. À l'heure où nous écrivons ces lignes, Common Voice 13 est la dernière édition du jeu de données, avec le plus grand nombre de langues et d'heures par langue de toutes les versions à ce jour.

Nous pouvons obtenir la liste complète des langues pour le jeu de données Common Voice 13 en consultant la page du jeu de données sur le *Hub* : [mozilla-foundation/common_voice_13_0](https://huggingface.co/datasets/mozilla-foundation/common_voice_13_0).
La première fois que vous consulterez cette page, il vous sera demandé d'accepter les conditions d'utilisation. Ensuite, vous aurez un accès complet au jeu de données.

Une fois que nous nous sommes authentifiés pour utiliser le jeu de données, son aperçu s'affiche montrant les 100 premiers échantillons du jeu de données pour chaque langue, prêts à être écoutés en temps réel. Pour cette unité, nous sélectionnerons le [_Dhivehi_](https://en.wikipedia.org/wiki/Maldivian_language) (ou _Maldivien_), une langue indo-aryenne parlée dans le pays insulaire d'Asie du Sud, les Maldives. Bien que nous choisissions le dhivehi pour ce tutoriel, les étapes couvertes ici s'appliquent à n'importe laquelle des 108 langues de l'ensemble de données Common Voice 13, et plus généralement à n'importe lequel des 180+ jeux de données audio du *Hub*. Il n'y a donc pas de restriction sur la langue ou le dialecte.

Nous pouvons sélectionner le sous-ensemble Dhivehi de Common Voice 13 en réglant le sous-ensemble sur `dv` à l'aide du menu déroulant (`dv` étant le code d'identification de la langue pour le Dhivehi) :

    

Si nous appuyons sur le bouton de lecture du premier échantillon, nous pouvons écouter le son et voir le texte correspondant. Parcourez les échantillons des ensembles d'entraînement et de test pour vous faire une idée plus précise des données que nous traitons.
L'intonation et le style indiquent que les enregistrements sont issus d'un discours narré. Vous remarquerez également la grande diversité des locuteurs et de la qualité des enregistrements, un trait commun aux données provenant de données *crown-sourcées*.

L'aperçu des données est un excellent moyen d'expérimenter les données audio avant de s'engager à les utiliser. Vous pouvez choisir n'importe quel jeu de données sur le Hub, faire défiler les échantillons et écouter l'audio pour les différents sous-ensembles et divisions, afin d'évaluer s'il s'agit du bon jeu de données pour vos besoins. Une fois que vous avez sélectionné un jeu de données, il est facile de charger les données afin de pouvoir commencer à les utiliser.

Personnellement, je ne parle pas le dhivehi et je m'attends à ce que la grande majorité des lecteurs ne le parlent pas non plus ! Pour savoir si notre modèle *finetuné* est bon, nous aurons besoin d'un moyen rigoureux de l'_évaluer_ sur des données inédites et de mesurer sa précision de transcription.
C'est exactement ce que nous allons faire dans la section suivante !

### Évaluation et métriques pour la reconnaissance automatique de la parole
https://huggingface.co/learn/audio-course/fr/chapter5/evaluation.md

# Évaluation et métriques pour la reconnaissance automatique de la parole

Si vous connaissez la [distance de Levenshtein](https://fr.wikipedia.org/wiki/Distance_de_Levenshtein) en NLP, les métriques d'évaluation des systèmes de reconnaissance vocale vous seront familières ! Ne vous inquiétez pas si ce n'est pas le cas, nous allons passer en revue les explications afin de nous assurer que vous maîtrisez les différentes métriques et que vous comprenez ce qu'elles signifient.

Lors de l'évaluation des systèmes de reconnaissance vocale, nous comparons les prédictions du système aux transcriptions du texte cible, en annotant toutes les erreurs présentes. Nous classons ces erreurs dans l'une des trois catégories suivantes :
1. Substitutions (Sub) : lorsque nous transcrivons le **mauvais mot** dans notre prédiction (par exemple "sit" au lieu de "sat").
2. Insertions (Ins) : lorsque nous ajoutons un **mot supplémentaire** dans notre prédiction.
3. Suppressions (Sup)  : lorsque nous **supprimons un mot** dans notre prédiction.

Ces catégories d'erreurs sont les mêmes pour toutes les mesures de reconnaissance vocale. Ce qui diffère, c'est le niveau auquel nous calculons ces erreurs : nous pouvons les calculer soit au niveau du _mot_, soit au niveau du _caractère_.

Nous utiliserons un exemple courant pour chacune des définitions des mesures. Nous avons ici une séquence de texte de _vérité de base_ ou de _référence_ :

```python
reference = "the cat sat on the mat"
```

Et une séquence prédite par le système de reconnaissance vocale que nous essayons d'évaluer :

```python
prediction = "the cat sit on the"
```

Nous pouvons constater que la prédiction est assez proche, mais que certains mots ne sont pas tout à fait corrects. Nous allons évaluer cette prédiction par rapport à la référence pour les trois mesures de reconnaissance vocale les plus populaires et voir quels types de chiffres nous obtenons pour chacune d'entre elles.

## *Word Error Rate* (Taux d'erreur au niveau du mot)

Le *word error rate (WER)* est la mesure de facto pour la reconnaissance vocale. Elle calcule les substitutions, les insertions et les suppressions au niveau du *mot*. Cela signifie que les erreurs sont annotées mot par mot. Prenons notre exemple :

| Réference :  | the | cat | sat     | on  | the | mat |
|-------------|-----|-----|---------|-----|-----|-----|
| Prediction : | the | cat | **sit** | on  | the |     |  |
| Étiquette :  | ✅   | ✅   | Sub       | ✅   | ✅   | Sup  |

Ici, nous avons
* 1 substitution ("sit" au lieu de "sat")
* 0 insertion
* 1 suppression ("mat" est manquant)

Cela donne 2 erreurs au total. Pour obtenir notre taux d'erreur, nous divisons le nombre d'erreurs par le nombre total de mots de notre référence (N), qui est de 6 pour cet exemple :

$$
\begin{aligned}
WER &= \frac{Sub + Ins + Sup}{N} \\
&= \frac{1 + 0 + 1}{6} \\
&= 0.333
\end{aligned}
$$

Ok, nous avons donc un WER de 0,333, soit 33,3 %. Remarquez que le mot "sit" ne comporte qu'un seul caractère erroné, mais que le mot entier est marqué comme incorrect. Il s'agit là d'une caractéristique essentielle du WER : les fautes d'orthographe sont lourdement pénalisées, même si elles sont mineures.

Le WER est défini de telle sorte que *plus il est bas, mieux c'est* : un WER bas signifie qu'il y a moins d'erreurs dans notre prédiction, de sorte qu'un système de reconnaissance vocale parfait aurait un WER de zéro (pas d'erreurs).

Voyons comment nous pouvons calculer le WER en utilisant 🤗 *Evaluate*. Nous aurons besoin de deux packages pour calculer notre métrique WER : 🤗 *Evaluate* pour l'interface API, et JIWER pour effectuer le gros du travail de calcul :

```
pip install --upgrade evaluate jiwer
```

Nous pouvons maintenant charger la métrique WER et calculer le résultat pour notre exemple :

```python
from evaluate import load

wer_metric = load("wer")

wer = wer_metric.compute(references=[reference], predictions=[prediction])

print(wer)
```

**Sortie :**

```
0.3333333333333333
```

0,33, soit 33,3 %, comme prévu ! Nous savons maintenant ce qui se passe sous le capot avec ce calcul du WER.

Maintenant, voici quelque chose qui est assez déroutant... D'après vous, quelle est la limite supérieure du WER ? On pourrait s'attendre à ce qu'elle soit de 1 ou de 100 %, n'est-ce pas ? Le WER étant le rapport entre le nombre d'erreurs et le nombre de mots (N), il n'y a pas de limite supérieure au WER !
Prenons un exemple dans lequel nous prédisons 10 mots et la cible n'en a que 2. Si toutes nos prédictions étaient fausses (10 erreurs), nous aurions un REE de 10 / 2 = 5, soit 500 % ! Il convient de garder cela à l'esprit si vous entraînez un système ASR et que vous obtenez un WER supérieur à 100 %. Toutefois, si vous obtenez ce résultat, il est probable que quelque chose n'a pas fonctionné... 😅

## *Word Accuracy* (Précision au niveau du mot)

Nous pouvons inverser le WER pour obtenir une mesure où *plus c'est haut, mieux c'est*. Plutôt que de mesurer le taux d'erreurs au niveau du mot, nous pouvons mesurer la *précision au niveau du mot* (WAcc) de notre système :

$$
\begin{equation}
WAcc = 1 - WER \nonumber
\end{equation}
$$

Le WAcc est mesuré au niveau du mot, il s'agit simplement du WER reformulé en tant que mesure de précision plutôt qu'en tant que mesure d'erreur. Le WAcc est très rarement cité dans la littérature : nous pensons aux prédictions de notre système en termes d'erreurs de mots, et nous préférons donc les mesures de taux d'erreur qui sont plus associées à ces annotations de type d'erreur.

## *Character Error Rate* (Taux d'erreur au niveau des caractères)

Il semble un peu injuste que nous ayons marqué l'ensemble du mot "sit" comme erroné alors qu'en fait une seule lettre était incorrecte.
Le *Character Error Rate (CER)* évalue les systèmes au *niveau des caractères*. Cela signifie que nous divisons nos mots en caractères individuels et que nous annotons les erreurs caractère par caractère :

| Réference :  | t   | h   | e   |     | c   | a   | t   |     | s   | a     | t   |     | o   | n   |     | t   | h   | e   |     | m   | a   | t   |
|-------------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| Prediction : | t   | h   | e   |     | c   | a   | t   |     | s   | **i** | t   |     | o   | n   |     | t   | h   | e   |     |     |     |     |
| Étiquette :      | ✅   | ✅   | ✅   |     | ✅   | ✅   | ✅   |     | ✅   | Sub     | ✅   |     | ✅   | ✅   |     | ✅   | ✅   | ✅   |     | D   | D   | D   |

Nous voyons maintenant que pour le mot "sit", le "s" et le "t" sont marqués comme corrects. Seul le "i" est étiqueté comme une erreur de substitution. Nous récompensons donc notre système pour la prédiction partiellement correcte 🤝

Dans notre exemple, nous avons 1 substitution de caractère, 0 insertion et 3 suppressions. Au total, nous avons 14 caractères. Notre CER est donc :

$$
\begin{aligned}
CER &= \frac{S + I + D}{N} \\
&= \frac{1 + 0 + 3}{14} \\
&= 0.286
\end{aligned}
$$

Nous obtenons un CER de 0,286, soit 28,6 %. Remarquez que ce chiffre est inférieur à notre WER. Nous avons beaucoup moins pénalisé l'erreur d'orthographe.

## Quelle mesure dois-je utiliser ?

En général, le WER est beaucoup plus utilisé que le CER pour évaluer les systèmes vocaux. En effet, le WER exige des systèmes une meilleure compréhension du contexte des prédictions. Dans notre exemple, "sit" n'est pas au bon temps. Un système qui comprend la relation entre le verbe et le temps de la phrase aurait prédit le temps correct du verbe "sat". Nous voulons encourager ce niveau de compréhension de la part de nos systèmes vocaux. Ainsi, bien que le WER soit moins indulgent que le CER, il est également plus propice aux types de systèmes intelligibles que nous souhaitons développer. C'est pourquoi nous utilisons généralement le WER et nous vous encourageons à faire de même ! Toutefois, dans certaines circonstances, il n'est pas possible de l'utiliser.
En effet, certaines langues, comme le mandarin et le japonais, n'ont pas de notion de "mots", et le WER n'a donc pas de sens. Dans ce cas, nous revenons à l'utilisation du CER.

Dans notre exemple, nous n'avons utilisé qu'une seule phrase pour calculer le WER. Lors de l'évaluation d'un système réel, nous utilisons généralement un ensemble de test complet composé de plusieurs milliers de phrases. Lorsque l'évaluation porte sur plusieurs phrases, nous agrégeons Sub, Inv, Sup et N pour toutes les phrases, puis nous calculons le WER à l'aide de la formule définie ci-dessus. Cela permet d'obtenir une meilleure estimation du WER pour des données inédites.

## Normalisation

Si nous entraînons un modèle d'ASR sur des données contenant de la ponctuation et de la casse, il apprendra à prédire la casse et la ponctuation dans ses transcriptions. C'est une bonne chose lorsque nous voulons utiliser notre modèle pour des applications réelles, telles que la transcription de réunions ou de dictées, car les transcriptions prédites seront entièrement formatées avec la casse et la ponctuation, un style appelé *orthographique*.

Cependant, nous avons également la possibilité de *normaliser* le jeu de données afin d'en supprimer la casse et la ponctuation. La normalisation du jeu de données facilite la tâche de reconnaissance vocale : le modèle n'a plus besoin de faire la distinction entre les majuscules et les minuscules, ni de prédire la ponctuation à partir des seules données audio (par exemple, quel est le son d'un point-virgule ?).
De ce fait, les taux d'erreur sur les mots sont naturellement plus faibles (ce qui signifie que les résultats sont meilleurs). L'article de Whisper démontre
l'effet radical que la normalisation des transcriptions peut avoir sur les résultats du WER (*cf.* Section 4.4 du [papier] (https://cdn.openai.com/papers/whisper.pdf)).
Bien que nous obtenions des WER plus bas, le modèle n'est pas nécessairement meilleur pour la production. L'absence de casse et de ponctuation rend le texte prédit par le modèle nettement plus difficile à lire. Prenons l'exemple de la [section précédente](asr_models), où nous avons utilisé Wav2Vec2 et Whisper sur le même échantillon audio du jeu de données LibriSpeech. Le modèle Wav2Vec2 ne prédit ni la ponctuation ni la casse, alors que Whisper prédit les deux. En comparant les transcriptions côte à côte, nous constatons que la transcription de Whisper est beaucoup plus facile à lire :

```
Wav2Vec2:  HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH CHRISTMAUS AND ROSE BEEF LOOMING BEFORE US SIMALYIS DRAWN FROM EATING AND ITS RESULTS OCCUR MOST READILY TO THE MIND
Whisper:   He tells us that at this festive season of the year, with Christmas and roast beef looming before us, similarly is drawn from eating and its results occur most readily to the mind.
```

La transcription Whisper est orthographique et donc prête à l'emploi. Au contraire, nous devrions utiliser un post-traitement supplémentaire pour restaurer la ponctuation et la casse dans nos prédictions Wav2Vec2 si nous voulions les utiliser pour des applications en aval.

Il existe un juste milieu entre normaliser et ne pas normaliser : nous pouvons entraîner nos systèmes sur des transcriptions orthographiques, puis normaliser les prédictions et les cibles avant de calculer le WER. De cette manière, nous entraînons nos systèmes à prédire des textes entièrement formatés, mais nous bénéficions également des améliorations du WER que nous obtenons en normalisant les transcriptions.

Whisper a été publié avec un normaliseur qui gère efficacement la normalisation de la casse, de la ponctuation et du formatage des nombres, entre autres. Appliquons le aux transcriptions de Whisper pour montrer comment nous pouvons les normaliser :

```python
from transformers.models.whisper.english_normalizer import BasicTextNormalizer

normalizer = BasicTextNormalizer()

prediction = " He tells us that at this festive season of the year, with Christmas and roast beef looming before us, similarly is drawn from eating and its results occur most readily to the mind."
normalized_prediction = normalizer(prediction)

normalized_prediction
```

**Sortie :**

```
' he tells us that at this festive season of the year with christmas and roast beef looming before us similarly is drawn from eating and its results occur most readily to the mind '
```

Nous pouvons constater que le texte a été entièrement mis en minuscules et que toute la ponctuation a été supprimée. Définissons maintenant la transcription de référence et calculons le WER normalisé entre la référence et la cible :

```python
reference = "HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH CHRISTMAS AND ROAST BEEF LOOMING BEFORE US SIMILES DRAWN FROM EATING AND ITS RESULTS OCCUR MOST READILY TO THE MIND"
normalized_referece = normalizer(reference)

wer = wer_metric.compute(
    references=[normalized_referece], predictions=[normalized_prediction]
)
wer
```

**Sortie :**

```
0.0625
```

6,25 % ; c'est à peu près ce à quoi nous nous attendions pour le modèle de base de Whisper sur l'ensemble de validation de LibriSpeech. Comme nous le voyons ici, nous avons prédit une transcription orthographique, mais nous avons bénéficié de l'augmentation du WER obtenue en normalisant la référence et la prédiction avant de calculer le WER.

Le choix de la méthode de normalisation des transcriptions dépend en fin de compte de vos besoins. Nous recommandons d'entraîner sur du texte orthographique et d'évaluer sur du texte normalisé afin d'obtenir le meilleur des deux mondes.

## Assembler le tout

Nous avons couvert trois sujets jusqu'à présent dans cette unité : les modèles pré-entraînés, la sélection des jeux de données et l'évaluation. 
Nous allons nous préparer pour la prochaine section sur le *finetuning* en évaluant le modèle Whisper pré-entraîné sur l'ensemble de test Common Voice 13 Dhivehi. Nous utiliserons le WER pour établir une _base_ pour la prochaine section où notre objectif sera d'essayer de le battre 🥊

Tout d'abord, nous allons charger le modèle Whisper pré-entraîné en utilisant la classe `pipeline()`. Ce processus vous est maintenant familier !
La seule nouveauté est de charger le modèle en demi-précision (float16) s'il est exécuté sur un GPU. Cela permet d'accélérer l'inférence sans que le WER n'en souffre.

```python
from transformers import pipeline
import torch

if torch.cuda.is_available():
    device = "cuda:0"
    torch_dtype = torch.float16
else:
    device = "cpu"
    torch_dtype = torch.float32

pipe = pipeline(
    "automatic-speech-recognition",
    model="openai/whisper-small",
    torch_dtype=torch_dtype,
    device=device,
)
```

Ensuite, nous allons charger l'échantillon test Dhivehi de Common Voice 13. Nous avons vu dans la section précédente que Common Voice 13 est *sécurisé*, ce qui signifie que nous avons dû accepter les conditions d'utilisation du jeu de données avant d'y avoir accès. Nous pouvons maintenant relier notre compte Hugging Face à notre *notebook*, afin d'avoir accès au jeu de données à partir de la machine que nous utilisons actuellement.

Lier le *notebook* au *Hub* est très simple, il suffit d'entrer votre *token* d'authentification au *Hub* lorsque l'on vous y invite.
Votre *token* d'authentification est trouvable [ici](https://huggingface.co/settings/tokens).

```python
from huggingface_hub import notebook_login

notebook_login()
```

Une fois que nous avons lié le *notebook* à notre compte Hugging Face, nous pouvons procéder au téléchargement du jeu de données Common Voice. Cela prendra quelques minutes de les télécharger et de les prétraiter automatiquement sur votre *notebook* :

```python
from datasets import load_dataset

common_voice_test = load_dataset(
    "mozilla-foundation/common_voice_13_0", "dv", split="test"
)
```

    Si vous rencontrez un problème d'authentification lors du chargement du jeu de données, assurez-vous que vous avez accepté les conditions d'utilisation du jeu de données sur le *Hub* via le lien suivant : https://huggingface.co/datasets/mozilla-foundation/common_voice_13_0.

L'évaluation sur un jeu de données entier peut être faite de la même manière que sur un seul exemple. Tout ce que nous avons à faire est de **boucler** sur les audios d'entrée, plutôt que d'inférer un seul échantillon. Pour ce faire, nous transformons d'abord notre jeu de données en un `KeyDataset`. Cela sélectionne la colonne particulière du jeu de données que nous voulons transmettre au modèle (dans notre cas, c'est la colonne `"audio"`), en ignorant le reste (comme les transcriptions cibles, que nous ne voulons pas utiliser pour l'inférence). Nous itérons ensuite sur ce jeu de données transformé, en ajoutant les sorties du modèle à une liste pour sauvegarder les prédictions. La cellule de code suivante prendra environ cinq minutes si elle est exécutée sur un GPU en demi-précision, avec un maximum de 12 Go de mémoire :

```python
from tqdm import tqdm
from transformers.pipelines.pt_utils import KeyDataset

all_predictions = []

# lancer l'inférence en streaming
for prediction in tqdm(
    pipe(
        KeyDataset(common_voice_test, "audio"),
        max_new_tokens=128,
        generate_kwargs={"task": "transcribe"},
        batch_size=32,
    ),
    total=len(common_voice_test),
):
    all_predictions.append(prediction["text"])
```

Si vous rencontrez une erreur de mémoire CUDA lors de l'exécution de la cellule ci-dessus, réduisez progressivement la taille du batch par un facteur de 2 jusqu'à ce que vous trouviez une taille de batch qui convienne à votre appareil.

Enfin, nous pouvons calculer le WER. Calculons d'abord le WER orthographique, c'est-à-dire le WER sans post-traitement :

```python
from evaluate import load

wer_metric = load("wer")

wer_ortho = 100 * wer_metric.compute(
    references=common_voice_test["sentence"], predictions=all_predictions
)
wer_ortho
```

**Sortie :**

```
167.29577268612022
```

D'accord... 167% signifie essentiellement que notre modèle produit n'imprte quoi 😜 Ne vous inquiétez pas, notre objectif est d'améliorer ce résultat en *fientunant* le modèle sur l'ensemble d'entraînement Dhivehi !

Ensuite, nous évaluons le WER normalisé, c'est-à-dire le WER avec post-traitement de normalisation. Nous devons filtrer nos échantillons qui seraient vides après normalisation, car sinon le nombre total de mots dans notre référence (N) serait nul, ce qui donnerait une erreur de division par zéro dans notre calcul :

```python
from transformers.models.whisper.english_normalizer import BasicTextNormalizer

normalizer = BasicTextNormalizer()

# calculer le WER normalisé
all_predictions_norm = [normalizer(pred) for pred in all_predictions]
all_references_norm = [normalizer(label) for label in common_voice_test["sentence"]]

# étape de filtrage pour n'évaluer que les échantillons qui correspondent à des références non nulles
all_predictions_norm = [
    all_predictions_norm[i]
    for i in range(len(all_predictions_norm))
    if len(all_references_norm[i]) > 0
]
all_references_norm = [
    all_references_norm[i]
    for i in range(len(all_references_norm))
    if len(all_references_norm[i]) > 0
]

wer = 100 * wer_metric.compute(
    references=all_references_norm, predictions=all_predictions_norm
)

wer
```

**Sortie :**

```
125.69809089960707
```

Une fois de plus, nous constatons la réduction drastique du WER obtenue en normalisant nos références et nos prédictions : le modèle de base obtient un WER de 168 % pour le test orthographique, alors que le WER normalisé est de 126 %.

Voilà qui est clair ! Ce sont les chiffres que nous voulons essayer de battre lors du *finetuning* du modèle de reconnaissance de la parole en Dhivehi. Poursuivez votre lecture pour vous familiariser avec un exemple de *finetuning* 🚀

### Se préparer à suivre le cours
https://huggingface.co/learn/audio-course/fr/chapter0/get_ready.md

# Se préparer à suivre le cours

Nous espérons que vous êtes impatient de commencer le cours, et nous avons conçu cette page pour nous assurer que vous avez tout ce dont vous avez besoin pour vous lancer !

## Étape 1. Avoir un compte Hugging Face

Si vous n'en avez pas encore, créez [un compte Hugging Face](https://huggingface.co/join) (c'est gratuit). Vous en aurez besoin pour effectuer des tâches pratiques, pour recevoir votre certificat d'achèvement, pour explorer des modèles pré-entraînés, pour accéder à des jeux de données et plus encore.

## Étape 2. Révisez les principes fondamentaux (si vous en avez besoin).

Nous supposons que vous connaissez les bases de l'apprentissage profond et que vous êtes familiarisés avec les *transformers*. Si vous avez besoin de rafraîchir vos connaissances sur ces modèles, consultez notre [cours sur le NLP](https://huggingface.co/course/fr/chapter1/1).

## Étape 3. Vérifiez votre configuration

Pour parcourir les supports de cours, vous aurez besoin des éléments suivants :
- Un ordinateur avec une connexion Internet
- [Google Colab](https://colab.research.google.com) pour les exercices pratiques. La version gratuite suffit.

Si vous n'avez jamais utilisé Google Colab, consultez ce *notebook* d'introduction officiel (https://colab.research.google.com/notebooks/intro.ipynb).

## Étape 4. Rejoignez la communauté

Inscrivez-vous sur notre serveur [Discord](http://hf.co/join/discord), l'endroit où vous pouvez échanger des idées avec vos camarades de classe et nous contacter (l'équipe d'Hugging Face).
Pour en savoir plus sur notre Discord et comment en tirer le meilleur parti, consultez la [page suivante](community).

### Bienvenue dans le cours d'audio d'Hugging Face !
https://huggingface.co/learn/audio-course/fr/chapter0/introduction.md

# Bienvenue dans le cours d'audio d'Hugging Face !

Cher apprenant, bienvenue dans ce cours sur l'utilisation des *transformers* pour l'audio, À maintes reprises, les *transformers* se sont révélés être l'une des architectures d'apprentissage profond les plus puissantes et les plus polyvalentes, capables d'obtenir des résultats de pointe dans un large éventail de tâches, y compris le traitement du langage naturel, la vision par ordinateur et, plus récemment, le traitement audio.

Dans ce cours, nous allons explorer comment ces modèles peuvent être appliqués à une série de tâches et de données audio. Que vous soyez intéressé par la reconnaissance vocale, la classification audio ou la synthèse vocale, les *transformers* et ce cours vous le permettront.

Pour vous donner un avant-goût de ce que ces modèles peuvent faire, prononcez quelques mots dans la démo ci-dessous et regardez le modèle les transcrire en temps réel !
 

Tout au long du cours, vous comprendrez les spécificités du travail avec des données audio, vous découvrirez différentes architectures de *transformers*, et *finetunerez* vos propres modèles audio en tirant parti de puissants modèles pré-entraînés.

Ce cours est conçu pour les personnes ayant des connaissances en apprentissage profond et une connaissance générale des *transformers*.
Aucune expertise en traitement de données audio n'est requise. Si vous avez besoin de rafraîchir vos connaissances sur les *transformers*, consultez notre [cours de NLP](https://huggingface.co/course/fr/chapter1/1) qui aborde en détail les principes de base de cette architecture.

## Rencontrer l'équipe du cours

**Sanchit Gandhi, ingénieur de recherche en apprentissage automatique chez Hugging Face**

Bonjour, je m'appelle Sanchit et je suis ingénieur de recherche en apprentissage automatique pour l'audio dans l'équipe *open-source* de Hugging Face 🤗.
Je me concentre principalement sur la reconnaissance automatique de la parole et la traduction, avec l'objectif actuel de rendre les modèles de parole plus rapides, plus légers et plus faciles à utiliser.

**Matthijs Hollemans, ingénieur en apprentissage automatique chez Hugging Face**.

Je m'appelle Matthijs et je suis ingénieur en apprentissage automatique en audio dans l'équipe *open source* de Hugging Face. Je suis également l'auteur d'un livre sur l'écriture de sons de synthétiseurs, et je crée des *plugins* audio pendant mon temps libre.

**Maria Khalusova, Documentation et cours chez Hugging Face**.

Je m'appelle Maria et je crée du contenu éducatif et de la documentation pour rendre *Transformers* et d'autres outils *open-source* encore plus accessibles. Je décompose des concepts techniques complexes et j'aide les gens à démarrer avec des technologies de pointe.

**Vaibhav Srivastav, ingénieur *advocate* et développeur en apprentissage automatique chez Hugging Face**.

Je m'appelle Vaibhav (VB) et je suis ingénieur *advocate* en audio au sein de l'équipe *open source* de Hugging Face. Je fais des recherches sur la synthèse vocale sur els lagnues à faibles ressources et j'aide à mettre l'état de l'art de la recherche sur la parole à la portée du plus grand nombre.

## Structure du cours

Le cours est structuré en plusieurs unités qui couvrent différents sujets en profondeur :

* Unité 1 : apprendre les spécificités du travail avec des données audio, y compris les techniques de traitement audio et la préparation des données.
* Unité 2 : connaître les applications audio et apprendre comment utiliser les pipelines de 🤗 *Transformers* pour différentes tâches, telles que la classification audio et la reconnaissance vocale.
* Unité 3 : explorer les architectures de *transformers* audio, apprendre comment ils diffèrent, et quelles sont les tâches pour lesquelles ils sont les mieux adaptés.
* Unité 4 : Apprenez à construire votre propre classifieur de genre musical.
* Unité 5 : approfondissement de la reconnaissance vocale
* Unité 6 : apprendre à générer de la parole à partir d'un texte.
* Unité 7 : apprendre à construire des applications audio réelles (traducteur parole-à-parole, assistant vocal et transcription de réunions).

Chaque unité comprend un volet théorique qui vous permettra d'acquérir une compréhension approfondie des concepts et des techniques sous-jacents. Tout au long du cours, des quiz vous permettent de tester vos connaissances et de renforcer votre apprentissage.
Certains chapitres comprennent également des exercices pratiques qui vous permettront d'appliquer ce que vous avez appris.

À la fin du cours, vous aurez acquis de solides bases dans l'utilisation des *transformers* pour les données audio et serez bien équipé pour appliquer ces techniques à un large éventail de tâches.

## Parcours d'apprentissage

Il n'y a pas de bonne ou de mauvaise façon de suivre ce cours. Tout le matériel contenu dans ce cours est 100% gratuit, public et *open-source*.
Vous pouvez le suivre à votre propre rythme, mais nous vous recommandons de suivre les unités dans l'ordre.

Bon cours !

### Rejoignez la communauté !
https://huggingface.co/learn/audio-course/fr/chapter0/community.md

# Rejoignez la communauté !

Nous vous invitons à [rejoindre notre communauté sur Discord](http://hf.co/join/discord). Vous aurez la possibilité d'échanger avec des apprenants, de partager des idées et d'obtenir un retour d'information précieux sur vos exercices pratiques. Vous pouvez poser des questions, partager des ressources et collaborer avec d'autres.

Notre équipe est également active sur Discord et se tient à votre disposition pour vous apporter son soutien et ses conseils en cas de besoin. Rejoindre notre communauté est un excellent moyen de rester motivé, engagé et connecté, et nous avons hâte de vous y voir !

## Qu'est-ce que Discord ?

Discord est une plateforme de chat gratuite. Si vous avez utilisé Slack, vous la trouverez assez similaire. Le serveur Discord d'Hugging Face abrite une communauté florissante de 18 000 experts, apprenants et passionnés d'IA dont vous pouvez faire partie.

## Naviguer sur Discord

Une fois inscrit à notre serveur Discord, vous devrez choisir les sujets qui vous intéressent en cliquant sur `#role-assignment` à gauche. Vous pouvez choisir autant de catégories différentes que vous le souhaitez. Pour rejoindre d'autres apprenants de ce cours, assurez-vous de cliquer sur "ML for Audio and Speech".
Explorez les canaux et présentez-vous dans le canal `#introduce-yourself`.

## Canaux du cours

Il existe de nombreux canaux axés sur différents sujets sur notre serveur Discord. Vous y trouverez des gens qui discutent d'articles, organisent des événements, partagent leurs projets et leurs idées, font du *brainstorming*, et bien plus encore.

En tant qu'apprenant du cours audio, vous trouverez peut-être les canaux suivants particulièrement pertinents :
* `#audio-announcements` : mises à jour sur le cours, nouvelles de Hugging Face en rapport avec tout ce qui concerne l'audio, annonces d'événements, et plus encore.
* `#audio-study-group` : un lieu pour échanger des idées, poser des questions sur le cours et entamer des discussions.
* `#audio-discuss` : un endroit général pour discuter de tout ce qui concerne l'audio.

En plus de rejoindre le canal `#audio-study-group`, n'hésitez pas à créer votre propre groupe d'étude, apprendre ensemble est toujours plus facile !

### Sessions en direct et ateliers
https://huggingface.co/learn/audio-course/fr/events/introduction.md

# Sessions en direct et ateliers

## Sessions en direct

Evènement de lancement du cours en direct avec [Paige Bailey](https://dynamicwebpaige.github.io/info/) (DeepMind), [Seokhwan Kim](https://seokhwankim.github.io/) (Amazon Alexa AI) et [Brian McFee](https://brianmcfee.net/) (Librosa) :

Enregistrement du direct "Demandez-moi n'importe quoi" avec l'équipe de Hugging Face du cours :

## Ateliers

### Hugging Face Machine Learning for Audio Study Group

Fin 2021 / début 2022, un groupe d'études sur les modèles audio était actif sur le Discord de Hugging Face.
Il consistait principalement en des présentations d'articles scientifiques, d'outils et de discussions sur le sujet de l'application de l'apprentissage automatique dans le domaine de l'audio.
Vous pouvez retrouver les enregistrements des présentations sur la [chaîne YouTube de Hugging Face](https://www.youtube.com/watch?v=cAviRhkqdnc&list=PLo2EIpI_JMQtOQK_B4G97yn1QWZ4Xi4Tu).
Les supports et *notebooks* utilisés dans les présentations sont disponibles sur le [GitHub de VB](https://github.com/Vaibhavs10/ml-with-audio).

### Whisper Fine-Tuning Event

En décembre 2022, un évènement pour *finetuner* le modèle Whisper dans plusieurs langues a été organisé.
Vous pouvez retrouver les informations le concernant sur la page [suivante](https://github.com/huggingface/community-events/tree/main/whisper-fine-tuning-event) (en anglais).

### Classification audio avec un pipeline
https://huggingface.co/learn/audio-course/fr/chapter2/audio_classification_pipeline.md

# Classification audio avec un pipeline

La classification audio consiste à attribuer une ou plusieurs étiquettes à un enregistrement audio en fonction de son contenu. 
Les étiquettes peuvent correspondre à différentes catégories sonores, telles que la musique, la parole ou le bruit, ou à des catégories plus spécifiques telles que le chant d’oiseaux ou les sons de moteur de voiture.
Avant de plonger dans les détails du fonctionnement des *transformers* audio les plus populaires, et avant de finetuner un modèle personnalisé, voyons comment vous pouvez utiliser un modèle pré-entraîné standard pour la classification audio avec seulement quelques lignes de code avec 🤗 *Transformers*.
Utilisons le même jeu de données [MINDS-14](https://huggingface.co/datasets/PolyAI/minds14) que vous avez exploré dans l'unité précédente. 
Si vous vous souvenez, MINDS-14 contient des enregistrements de personnes posant des questions à un système bancaire électronique dans plusieurs langues et dialectes, et a le `intent_class` pour chaque enregistrement. Nous pouvons classer les enregistrements par intention de l'appel.

Comme précédemment, commençons par charger le sous-ensemble `en-AU` pour essayer le pipeline, et suréchantillonnons-le à un taux d'échantillonnage de 16 kHz, ce qui est ce que la plupart des modèles vocaux exigent.

```py
from datasets import load_dataset
from datasets import Audio

minds = load_dataset("PolyAI/minds14", name="en-AU", split="train")
minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
```

Pour classer un enregistrement audio dans un ensemble de classes, nous pouvons utiliser le pipeline `audio-classification` de 🤗 *Transformers*.
Dans notre cas, nous avons besoin d'un modèle qui a été finetuné pour la classification des intentions, et en particulier sur le jeu de données MINDS-14. Heureusement pour nous, le *Hub* a un modèle qui fait exactement cela ! Chargeons-le en utilisant la fonction `pipeline()` :

```py
from transformers import pipeline

classifier = pipeline(
    "audio-classification",
    model="anton-l/xtreme_s_xlsr_300m_minds14",
)
```

Ce pipeline attend les données audio sous forme de tableau NumPy. Tout le prétraitement des données audio brutes sera commodément géré pour nous par le pipeline. Choisissons un exemple pour l'essayer :

```py
example = minds[0]
```

Si vous vous souvenez de la structure du jeu de données, les données audio brutes sont stockées dans un tableau NumPy sous `["audio"]["array"]`, passons-les directement au `classifier` :

```py
classifier(example["audio"]["array"])
```

**Sortie :**

```out
[
    {"score": 0.9631525278091431, "label": "pay_bill"},
    {"score": 0.02819698303937912, "label": "freeze"},
    {"score": 0.0032787492964416742, "label": "card_issues"},
    {"score": 0.0019414445850998163, "label": "abroad"},
    {"score": 0.0008378693601116538, "label": "high_value_payment"},
]
```

Le modèle est très confiant que l'appelant avait l'intention d'apprendre à payer sa facture. Voyons quelle est l'étiquette réelle pour cet exemple:

```py
id2label = minds.features["intent_class"].int2str
id2label(example["intent_class"])
```

**Sortie :**

```out
"pay_bill"
```

L'étiquette prédite est correcte ! Ici, nous avons eu la chance de trouver un modèle capable de classer les étiquettes exactes dont nous avons besoin.
Souvent, lorsqu'il s'agit d'une tâche de classification, l'ensemble de classes d'un modèle pré-entraîné n'est pas exactement le même que les classes que vous devez distinguer par le modèle. 
Dans ce cas, vous pouvez finetuner un modèle pré-entraîné pour le « calibrer » en fonction de votre ensemble exact d'étiquettes de classe. Nous apprendrons comment le faire dans les prochaines unités.

### Reconnaissance automatique de la parole avec pipeline
https://huggingface.co/learn/audio-course/fr/chapter2/asr_pipeline.md

# Reconnaissance automatique de la parole avec pipeline

La reconnaissance automatique de la parole (ASR pour *Automatic Speech Recognition*) est une tâche qui implique la transcription de l'enregistrement vocal en texte.
Cette tâche a de nombreuses applications pratiques, de la création de sous-titres codés pour les vidéos à l'activation des commandes vocales pour les assistants virtuels comme Siri et Alexa.

Dans cette section, nous utiliserons le pipeline `automatic-speech-recognition` pour transcrire un enregistrement audio d'une personne posant une question sur le paiement d'une facture en utilisant le même jeu de données MINDS-14 qu'auparavant.

Pour commencer, chargez le jeu de données et suréchantillonnez-le à 16 kHz comme décrit dans [Classification audio avec un pipeline](audio_classification_pipeline), si vous ne l'avez pas encore fait.

Pour transcrire un enregistrement audio, nous pouvons utiliser le pipeline de `automatic-speech-recognition` de 🤗 *Transformers*. Instancions le pipeline :

```py
from transformers import pipeline

asr = pipeline("automatic-speech-recognition")
```

Ensuite, nous allons prendre un exemple du jeu de données et transmettre ses données brutes au pipeline :

```py
example = minds[0]
asr(example["audio"]["array"])
```

**Sortie :**

```out
{"text": "I WOULD LIKE TO PAY MY ELECTRICITY BILL USING MY COD CAN YOU PLEASE ASSIST"}
# "Je voudrais payer ma facture d'électricité avec ma morue, pouvez-vous m'aider"
```

Comparons cette sortie à ce qu'est la transcription réelle pour cet exemple :

```py
example["english_transcription"]
``` 
**Sortie :**
```out
"I would like to pay my electricity bill using my card can you please assist"
# "Je voudrais payer ma facture d'électricité avec ma carte, pouvez-vous m'aider"
``` 

Le modèle semble avoir fait un assez bon travail pour transcrire l'audio ! Il n'a eu qu'un mot erroné (*card*) par rapport à la transcription originale, ce qui est plutôt bon étant donné que le locuteur a un accent australien, où la lettre « r » est souvent silencieuse. Cela dit, je ne recommanderais pas d'essayer de payer votre prochaine facture d'électricité avec un poisson !

Par défaut, ce pipeline utilise un modèle entraîné pour la reconnaissance automatique de la parole pour la langue anglaise, ce qui est très bien dans cet exemple. Si vous souhaitez essayer de transcrire d'autres sous-ensembles de MINDS-14 dans une langue différente, vous pouvez trouver un modèle ASR pré-entraîné sur le [🤗 *Hub*](https://huggingface.co/models?pipeline_tag=automatic-speech-recognition&language=fr&sort=downloads).
Vous pouvez d'abord filtrer la liste des modèles par tâche, puis par langue. Une fois que vous avez trouvé le modèle que vous aimez, passez son nom comme argument `model` au pipeline.

Essayons cela pour l’échantillon allemand de MINDS-14. Chargez le sous-ensemble `de-DE` :

```py
from datasets import load_dataset
from datasets import Audio

minds = load_dataset("PolyAI/minds14", name="de-DE", split="train")
minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
```

Obtenez un exemple et voyez ce que la transcription est censée être:

```py
example = minds[0]
example["transcription"]
```

**Sortie :**

```out
"ich möchte gerne Geld auf mein Konto einzahlen"
```

Trouvez un modèle ASR pré-entraîné pour la langue allemande sur le 🤗 *Hub*, instanciez un pipeline et transcrivez l'exemple :

```py
from transformers import pipeline

asr = pipeline("automatic-speech-recognition", model="maxidl/wav2vec2-large-xlsr-german")
asr(example["audio"]["array"])
```

**Sortie :**

```out
{"text": "ich möchte gerne geld auf mein konto einzallen"}
```

Identique !

Lorsque vous travaillez à résoudre votre propre tâche, commencer par un pipeline simple comme ceux que nous avons montrés dans cette unité est un outil précieux qui offre plusieurs avantages :
- Il peut exister un modèle pré-entraîné qui résout déjà très bien votre tâche, vous faisant gagner beaucoup de temps
- `pipeline()` s'occupe de tout le pré/post-traitement pour vous, vous n'avez donc pas à vous soucier d'obtenir les données dans le bon format pour un modèle
- Si le résultat n'est pas idéal, cela vous donne quand même une base de référence rapide pour les ajustements futurs
- une fois que vous avez affiné un modèle sur vos données personnalisées et que vous l'avez partagé sur le *Hub*, toute la communauté pourra l'utiliser rapidement et sans effort via la méthode 'pipeline()' rendant l'IA plus accessible.

### Exercice pratique
https://huggingface.co/learn/audio-course/fr/chapter2/hands_on.md

# Exercice pratique

Cet exercice n'est pas noté et a pour but de vous aider à vous familiariser avec les outils et les bibliothèques que vous utiliserez pendant le reste du cours. Si vous avez déjà l'habitude d'utiliser Google Colab, 🤗 *Datasets*, librosa et 🤗 *Transformers*, vous pouvez choisir de passer cet exercice.

1. Créez un *notebook* [Google Colab](https://colab.research.google.com).
2. Utilisez 🤗 *Datasets* pour charger le split d'entraînement du jeu de données [`facebook/voxpopuli`](https://huggingface.co/datasets/facebook/voxpopuli) dans la langue de votre choix en mode streaming.
3. Récupérez le troisième exemple de la partie `train` du jeu de données et explorez-le. Compte tenu des caractéristiques de cet exemple, pour quels types de tâches audio pouvez-vous utiliser ce jeu de données ?
4. Tracez la forme d'onde et le spectrogramme de cet exemple.
5. Allez sur le [🤗 *Hub*](https://huggingface.co/models), explorez les modèles pré-entraînés et trouvez-en un qui peut être utilisé pour la reconnaissance automatique de la parole dans la langue que vous avez choisie plus tôt. Instanciez un pipeline correspondant avec le modèle que vous avez trouvé, et transcrivez l'exemple.
6. Comparez la transcription que vous obtenez du pipeline à la transcription fournie dans l'exemple.

Si cet exercice vous pose problème, n'hésitez pas à jeter un coup d'œil à un [exemple de solution](https://colab.research.google.com/drive/1NGyo5wFpRj8TMfZOIuPaJHqyyXCITftc?usp=sharing). 
Vous avez découvert quelque chose d'intéressant ? Vous avez trouvé un modèle intéressant ? Vous avez un beau spectrogramme ? N'hésitez pas à partager votre travail et vos découvertes sur Twitter ! 

Dans les prochains chapitres, vous en apprendrez plus sur les différentes architectures de transformers audio et vous entraînerez votre propre modèle !

### Unité 2 : Une introduction en douceur aux applications audio
https://huggingface.co/learn/audio-course/fr/chapter2/introduction.md

# Unité 2 : Une introduction en douceur aux applications audio

Bienvenue dans la deuxième unité du cours audio Hugging Face ! Précédemment, nous avons exploré les principes fondamentaux des données audio et appris à travailler avec des jeux de données audio en utilisant les bibliothèques 🤗 *Datasets* et 🤗 *Transformers*.
Nous avons abordé divers concepts tels que la fréquence d'échantillonnage, l'amplitude, la profondeur de bits, la forme d'onde et les spectrogrammes, et nous avons vu comment prétraiter les données pour les préparer à un modèle pré-entraîné.

À ce stade, vous êtes peut-être impatient de découvrir les tâches audio que 🤗 *Transformers* peut gérer, et vous avez toutes les connaissances de base nécessaires pour vous y plonger ! Jetons un coup d'œil à quelques exemples de tâches audio époustouflantes :

**Classification audio** : classez facilement les clips audio dans différentes catégories. Vous pouvez déterminer si un enregistrement est celui d'un chien qui aboie ou d'un chat qui miaule, ou à quel genre musical appartient une chanson.
**Reconnaissance automatique de la parole** : transformez les clips audio en texte en les transcrivant automatiquement. Vous pouvez obtenir une représentation textuelle d'un enregistrement de quelqu'un qui parle, comme "Comment allez-vous aujourd'hui ?". Plutôt utile pour la prise de notes !
**Diagnostic du locuteur** : Vous vous êtes déjà demandé qui parlait dans un enregistrement ? Avec 🤗 *Transformers*, vous pouvez identifier le locuteur qui parle à un moment donné dans un clip audio. Imaginez que vous puissiez faire la différence entre "Alice" et "Bob" dans un enregistrement de leur conversation.
**Text to speech** : créer une version narrée d'un texte qui peut être utilisée pour produire un livre audio, aider à l'accessibilité ou donner une voix à un PNJ dans un jeu. Avec 🤗 *Transformers*, vous pouvez facilement le faire !

Dans cette unité, vous apprendrez à utiliser des modèles pré-entraînés pour certaines de ces tâches en utilisant la fonction `pipeline()` de 🤗 *Transformers*.
Plus précisément, nous verrons comment les modèles pré-entraînés peuvent être utilisés pour la classification audio et la reconnaissance automatique de la parole.
C'est parti !

### Finetuning du SpeechT5
https://huggingface.co/learn/audio-course/fr/chapter6/fine-tuning.md

# Finetuning du SpeechT5

Maintenant que vous êtes familiarisé avec la tâche de synthèse vocale et le fonctionnement interne du SpeechT5 qui a été entraîné sur des données en langue anglaise, voyons comment nous pouvons le *finetuner* à une autre langue. 

## Préparation
Assurez-vous de disposer d'un GPU si vous souhaitez reproduire cet exemple. Dans un *notebook*, vous pouvez vérifier avec la commande suivante : 

```bash
nvidia-smi
```

Dans notre exemple, nous utiliserons environ 40 heures de données d'entraînement. Si vous souhaitez suivre en utilisant la version gratuite de Google Colab, vous devrez réduire la quantité de données d'entraînement à environ 10-15 heures, ainsi que réduire le nombre d'étapes d'entraînement.

Vous aurez également besoin de quelques dépendances supplémentaires : 

```bash
pip install transformers datasets soundfile speechbrain accelerate
```

Enfin, n'oubliez pas de vous connecter à votre compte Hugging Face pour pouvoir télécharger et partager votre modèle avec la communauté :

```py
from huggingface_hub import notebook_login

notebook_login()
```

## Le jeu de données

Pour cet exemple, nous prendrons le sous-ensemble en néerlandais (`nl`) du jeu de données [VoxPopuli](https://huggingface.co/datasets/qmeeus/voxpopuli).
[VoxPopuli](https://huggingface.co/datasets/qmeeus/voxpopuli) est un corpus de parole multilingue à grande échelle composé de données provenant d'enregistrements d'événements du Parlement européen de 2009 à 2020.
Il contient des données de transcription audio étiquetées pour 15 langues européennes. Nous utiliserons le sous-ensemble néerlandais, mais vous pouvez choisir un autre sous-ensemble. 
 
Il s'agit d'un jeu de données de reconnaissance automatique de la parole, donc comme mentionné précédemment, ce n'est pas l'option la plus appropriée pour entraîner des modèles TTS. Cependant, il sera suffisant pour cet exercice. 

Chargeons les données :

```python
from datasets import load_dataset, Audio

dataset = load_dataset("qmeeus/voxpopuli", "nl", split="train")
len(dataset)
```

**Sortie :**
```out
20968
```

20968 exemples devraient suffire pour un *finetuning*. SpeechT5 s'attend à ce que les données audio aient une fréquence d'échantillonnage de 16 kHz, assurez-vous donc que les exemples du jeu de données répondent à cette exigence :

```python
dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
```

## Prétraitement des données 

Commençons par définir le *checkpoint* du modèle à utiliser et par charger le processeur approprié qui contient à la fois le *tokenizer* et l'extracteur de caractéristiques dont nous aurons besoin pour préparer les données en vue de l'entraînement : 

```py
from transformers import SpeechT5Processor

checkpoint = "microsoft/speecht5_tts"
processor = SpeechT5Processor.from_pretrained(checkpoint)
```

### Nettoyage du texte pour la tokenisation de SpeechT5

Tout d'abord, pour préparer le texte, nous aurons besoin de la partie *tokenizer* du processeur, alors allons-y :

```py
tokenizer = processor.tokenizer
```

Prenons un exemple : 

```python
dataset[0]
```

**Sortie :**
```out
{'audio_id': '20100210-0900-PLENARY-3-nl_20100210-09:06:43_4',
 'language': 9,
 'audio': {'path': '/root/.cache/huggingface/datasets/downloads/extracted/02ec6a19d5b97c03e1379250378454dbf3fa2972943504a91c7da5045aa26a89/train_part_0/20100210-0900-PLENARY-3-nl_20100210-09:06:43_4.wav',
  'array': array([ 4.27246094e-04,  1.31225586e-03,  1.03759766e-03, ...,
         -9.15527344e-05,  7.62939453e-04, -2.44140625e-04]),
  'sampling_rate': 16000},
 'text': 'dat kan naar mijn gevoel alleen met een brede meerderheid die wij samen zoeken.',
 'gender': 'female',
 'speaker_id': '1122',
 'is_gold_transcript': True,
 'accent': 'None'}
```

Les exemples du jeu de données contiennent une caractéristique `text` que nous utiliserons comme entrée de texte. Il est important de savoir que le *tokenizer* de SpeechT5 n'a pas de *tokens* pour les nombres, donc si votre texte contient des nombres, vous devrez peut-être les écrire sous forme textuelle.

Comme SpeechT5 a été entraîné sur la langue anglaise, il se peut qu'il ne reconnaisse pas certains caractères dans le jeu de données néerlandais. 
S'ils sont laissés tels quels, ces caractères seront convertis en tokens ``. Cependant, en néerlandais, certains caractères comme `à` sont utilisés pour souligner les syllabes. Afin de préserver le sens du texte, nous pouvons remplacer ce caractère par un `a` normal.

Pour identifier les *tokens* non supportés, extrayez tous les caractères uniques du jeu de données en utilisant le `SpeechT5Tokenizer` qui fonctionne avec les caractères comme des *tokens*. 
Pour ce faire, nous allons écrire la fonction `extract_all_chars` qui concatène les transcriptions de tous les exemples en une chaîne et la convertit en un ensemble de caractères. 
Assurez-vous de mettre `batched=True` et `batch_size=-1` dans `dataset.map()` afin que toutes les transcriptions soient disponibles en même temps pour la fonction de *mapping*.

```py
def extract_all_chars(batch):
    all_text = " ".join(batch["text"])
    vocab = list(set(all_text))
    return {"vocab": [vocab], "all_text": [all_text]}

vocabs = dataset.map(
    extract_all_chars,
    batched=True,
    batch_size=-1,
    keep_in_memory=True,
    remove_columns=dataset.column_names,
)

dataset_vocab = set(vocabs["vocab"][0])
tokenizer_vocab = {k for k, _ in tokenizer.get_vocab().items()}
```

Vous disposez à présent de deux ensembles de caractères : l'un avec le vocabulaire du jeu de données et l'autre avec le vocabulaire du *tokenizer*. 
Pour identifier les caractères non pris en charge dans le jeu de données, vous pouvez prendre la différence entre ces deux ensembles. L'ensemble résultant contiendra les caractères qui se trouvent dans le jeu de données mais pas dans le *tokenizer*.

```py
dataset_vocab - tokenizer_vocab
```

**Sortie :**
```out
{' ', 'à', 'ç', 'è', 'ë', 'í', 'ï', 'ö', 'ü'}
```

Pour gérer les caractères non supportés identifiés dans l'étape précédente, nous pouvons définir une fonction qui fait correspondre ces caractères à des *tokens* valides. Notez que les espaces sont déjà remplacés par `▁` dans le *tokenizer* et n'ont pas besoin d'être gérés séparément.

```py
replacements = [
    ("à", "a"),
    ("ç", "c"),
    ("è", "e"),
    ("ë", "e"),
    ("í", "i"),
    ("ï", "i"),
    ("ö", "o"),
    ("ü", "u"),
]

def cleanup_text(inputs):
    for src, dst in replacements:
        inputs["normalized_text"] = inputs["normalized_text"].replace(src, dst)
    return inputs

dataset = dataset.map(cleanup_text)
```

Maintenant que nous avons traité les caractères spéciaux dans le texte, il est temps de se concentrer sur les données audio.

### Les locuteurs

Le jeu de données VoxPopuli comprend la parole de plusieurs locuteurs, mais combien de locuteurs sont représentés dans le jeu de données ? Pour le savoir, nous pouvons compter le nombre de locuteurs uniques et le nombre d'exemples que chaque locuteur apporte au jeu de données. 
Avec un total de 20 968 exemples dans le jeu de données, cette information nous permettra de mieux comprendre la distribution des locuteurs et des exemples dans les données.

```py
from collections import defaultdict

speaker_counts = defaultdict(int)

for speaker_id in dataset["speaker_id"]:
    speaker_counts[speaker_id] += 1
```

En traçant un histogramme, vous pouvez vous faire une idée de la quantité de données pour chaque locuteur.

```py
import matplotlib.pyplot as plt

plt.figure()
plt.hist(speaker_counts.values(), bins=20)
plt.ylabel("Speakers")
plt.xlabel("Examples")
plt.show()
```

    

L'histogramme révèle qu'environ un tiers des locuteurs du jeu de données ont moins de 100 exemples, tandis qu'une dizaine de locuteurs ont plus de 500 exemples. Pour améliorer l'efficacité de l'entraînement et équilibrer le jeu de données, nous pouvons limiter les données aux locuteurs ayant entre 100 et 400 exemples. 

```py
def select_speaker(speaker_id):
    return 100 

Remarque : si vous trouvez ce spectrogramme déroutant, c'est peut-être parce que vous êtes familier avec la convention qui consiste à placer les basses fréquences en bas et les hautes fréquences en haut d'un graphique. 
Cependant, lorsque l'on trace des spectrogrammes sous forme d'image à l'aide de la bibliothèque matplotlib, l'axe des ordonnées est inversé et les spectrogrammes apparaissent à l'envers.

Nous devons maintenant appliquer la fonction de traitement à l'ensemble du jeu de données. Cela prendra entre 5 et 10 minutes.

```py
dataset = dataset.map(prepare_dataset, remove_columns=dataset.column_names)
```

Vous verrez un avertissement indiquant que certains exemples du jeu de données sont plus longs que la longueur d'entrée maximale que le modèle peut traiter (600 *tokens*). 
Supprimez ces exemples du jeu de données. Ici, nous allons encore plus loin et, pour tenir compte de la taille des batchs, nous supprimons tout ce qui dépasse 200 *tokens*.

```py
def is_not_too_long(input_ids):
    input_length = len(input_ids)
    return input_length  Dict[str, torch.Tensor]:
        input_ids = [{"input_ids": feature["input_ids"]} for feature in features]
        label_features = [{"input_values": feature["labels"]} for feature in features]
        speaker_features = [feature["speaker_embeddings"] for feature in features]

        # assembler les données d'entrée et les cibles dans un batch
        batch = processor.pad(
            input_ids=input_ids, labels=label_features, return_tensors="pt"
        )

        # remplacer le rembourrage par -100 pour ignorer correctement les pertes
        batch["labels"] = batch["labels"].masked_fill(
            batch.decoder_attention_mask.unsqueeze(-1).ne(1), -100
        )

        # non utilisé pendant le finetuning
        del batch["decoder_attention_mask"]

        # arrondir les longueurs cibles au multiple du facteur de réduction
        if model.config.reduction_factor > 1:
            target_lengths = torch.tensor(
                [len(feature["input_values"]) for feature in label_features]
            )
            target_lengths = target_lengths.new(
                [
                    length - length % model.config.reduction_factor
                    for length in target_lengths
                ]
            )
            max_length = max(target_lengths)
            batch["labels"] = batch["labels"][:, :max_length]

        # ajoutez également les enchâssements de locuteur
        batch["speaker_embeddings"] = torch.tensor(speaker_features)

        return batch
```

Dans SpeechT5, l'entrée de la partie décodeur du modèle est réduite d'un facteur 2. En d'autres termes, il élimine un pas de temps sur deux de la séquence cible. Le décodeur prédit alors une séquence deux fois plus longue. Étant donné que la longueur de la séquence cible d'origine peut être impaire, l'assembleur de données veille à arrondir la longueur maximale du batch à un multiple de 2.

```py 
data_collator = TTSDataCollatorWithPadding(processor=processor)
```

## Entraîner le modèle

Chargez le modèle pré-entraîné à partir du même *checkpoint* que celui utilisé pour le chargement du processeur : 

```py
from transformers import SpeechT5ForTextToSpeech

model = SpeechT5ForTextToSpeech.from_pretrained(checkpoint)
```

L'option `use_cache=True` est incompatible avec le *checkingpointing* du gradient. Désactivez-la pour l'entraînement, et réactivez le cache pour la génération afin d'accélérer le temps d'inférence :

```py 
from functools import partial

# désactiver le cache pendant l'entraînement car il est incompatible avec le checkpointing du gradient
model.config.use_cache = False

# définir la langue et la tâche pour la génération et réactiver le cache
model.generate = partial(model.generate, use_cache=True)
``` 

Définir les arguments d'entraînement. Ici, nous ne calculons aucune métrique d'évaluation pendant le processus d'entraînement, nous parlerons d'évaluation plus tard dans ce chapitre. Au lieu de cela, nous ne nous intéresserons qu'à la perte :

```python
from transformers import Seq2SeqTrainingArguments

training_args = Seq2SeqTrainingArguments(
    output_dir="speecht5_finetuned_voxpopuli_nl",  # changer pour un nom de dépôt de votre choix
    per_device_train_batch_size=4,
    gradient_accumulation_steps=8,
    learning_rate=1e-5,
    warmup_steps=500,
    max_steps=4000,
    gradient_checkpointing=True,
    fp16=True,
    evaluation_strategy="steps",
    per_device_eval_batch_size=2,
    save_steps=1000,
    eval_steps=1000,
    logging_steps=25,
    report_to=["tensorboard"],
    load_best_model_at_end=True,
    greater_is_better=False,
    label_names=["labels"],
    push_to_hub=True,
)
```

Instancie l'objet `Trainer` et lui passe le modèle, le jeu de données et l'assembleur de données.

```py
from transformers import Seq2SeqTrainer

trainer = Seq2SeqTrainer(
    args=training_args,
    model=model,
    train_dataset=dataset["train"],
    eval_dataset=dataset["test"],
    data_collator=data_collator,
    tokenizer=processor,
)
```

Et voilà, nous sommes prêts à commencer l'entraînement ! Il prendra plusieurs heures. En fonction de votre GPU, il est possible que vous rencontriez une erreur CUDA "out-of-memory" lorsque vous commencez l'entraînement. Dans ce cas, vous pouvez réduire la taille de `per_device_train_batch_size` par incréments d'un facteur 2 et augmenter `gradient_accumulation_steps` par 2 pour compenser.

```py
trainer.train()
```

Pousser le modèle final sur le *Hub* :

```py
trainer.push_to_hub()
```

## Inférence

Une fois que vous avez *finetuné* un modèle, vous pouvez l'utiliser pour l'inférence ! Chargez le modèle à partir du *Hub* (assurez-vous d'utiliser votre nom de compte dans l'extrait de code suivant) : 

```py
model = SpeechT5ForTextToSpeech.from_pretrained(
    "YOUR_ACCOUNT/speecht5_finetuned_voxpopuli_nl"
)
```

Choisissez un exemple, ici nous en prendrons un du jeu de données de test. Obtenez un enchâssement du locuteur. 

```py 
example = dataset["test"][304]
speaker_embeddings = torch.tensor(example["speaker_embeddings"]).unsqueeze(0)
```

Définir un texte d'entrée et le *tokeniser*.

```py 
text = "hallo allemaal, ik praat nederlands. groetjes aan iedereen!"
```

Prétraiter le texte d'entrée : 

```py
inputs = processor(text=text, return_tensors="pt")
```

Installez un vocodeur et générez de la parole : 

```py
from transformers import SpeechT5HifiGan

vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")
speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder)
```

On écoute le résultat ?

```py
from IPython.display import Audio

Audio(speech.numpy(), rate=16000)
```

Il peut être difficile d'obtenir des résultats satisfaisants avec ce modèle dans une nouvelle langue. La qualité de l'enchâssement du locuteur peut être un facteur important. Comme SpeechT5 a été entraîné avec des X-vectors anglais, il donne de meilleurs résultats lorsqu'il utilise des enchâssements de locuteurs anglais. Si la synthèse vocale semble médiocre, essayez d'utiliser un autre enchâssement de locuteur.

L'augmentation de la durée d'entraînement est également susceptible d'améliorer la qualité des résultats. Malgré cela, le discours est clairement néerlandais et non anglais, et il capture les caractéristiques vocales du locuteur (comparez avec l'audio original dans l'exemple).
Une autre chose à expérimenter est la configuration du modèle. Par exemple, essayez d'utiliser `config.reduction_factor = 1` pour voir si cela améliore les résultats.

Dans la section suivante, nous verrons comment nous évaluons les modèles de synthèse vocale.

### Exercice pratique
https://huggingface.co/learn/audio-course/fr/chapter6/hands_on.md

# Exercice pratique

Dans cette unité, nous avons exploré la tâche audio de synthèse vocale, parlé des jeux de données existants, des modèles pré-entraînés et des nuances du *finetuning* de SpeechT5 pour une nouvelle langue. 

Comme vous l'avez vu, le *finetuning* des modèles pour la tâche de synthèse vocale peut s'avérer difficile dans des scénarios à faibles ressources. Parallèlement, l'évaluation des modèles de synthèse vocale n'est pas facile non plus. 

Pour ces raisons, cet exercice pratique se concentrera sur la mise en pratique des compétences plutôt que sur l'obtention d'une certaine valeur de métrique. 

Votre objectif pour cette tâche est de *finetuner* SpeechT5 sur un jeu de données de votre choix. Vous pouvez choisir une autre langue dans le même jeu de données `voxpopuli`, ou tout autre jeu de données listé dans cette unité.

Faites attention à la taille des données d'entraînement ! Pour s'entraîner sur un GPU gratuit de Google Colab, nous recommandons de limiter les données d'entraînement à environ 10-15 heures. 

Une fois que vous avez terminé le processus de *finetuné*, partagez votre modèle en le téléchargeant sur le *Hub*. Assurez-vous de marquer votre modèle comme un modèle `text-to-speech` soit avec les kwargs appropriés, soit dans l'interface utilisateur du *Hub*.

Rappelez-vous, le but principal de cet exercice est de vous fournir une grande pratique, vous permettant d'affiner vos compétences et d'acquérir une compréhension plus profonde des tâches audio de synthèse vocale.

### Jeux de données de synthèse vocale
https://huggingface.co/learn/audio-course/fr/chapter6/tts_datasets.md

# Jeux de données de synthèse vocale

La tâche de synthèse vocale comporte une série de défis.
Tout d'abord, tout comme dans la reconnaissance automatique de la parole discutée précédemment, l'alignement entre le texte et la parole peut être délicat.  
Cependant, contrairement à l’ASR,  le TTS est un problème d’association **un-à-plusieurs**, c'est-à-dire que le même texte peut être synthétisé de différentes manières. Pensez à la diversité des voix et des styles de parole dans le discours que vous entendez quotidiennement : chaque personne a une façon différente de prononcer la même phrase, mais elles sont toutes valides et correctes. Même des sorties différentes (spectrogrammes ou formes d'ondes audio) peuvent correspondre à la même réalité de terrain. Le modèle doit apprendre à générer la durée et le timing corrects pour chaque phonème, mot ou phrase, ce qui peut être difficile, en particulier pour les phrases longues et complexes.

Ensuite, il y a le problème de la dépendance : la langue a un aspect temporel, et comprendre le sens d'une phrase nécessite souvent de tenir compte du contexte des mots environnants. Il est crucial de s'assurer que le modèle de TTS capture et conserve les informations contextuelles sur de longues séquences pour générer un discours cohérent et naturel.

Enfin, l'apprentissage des modèles de TTS nécessite généralement des paires de texte et des enregistrements vocaux correspondants. En plus de cela, pour s'assurer que le modèle peut générer un discours qui sonne naturel pour différents locuteurs et styles de parole, les données doivent contenir des échantillons de discours divers et représentatifs de plusieurs locuteurs. La collecte de ces données est coûteuse, prend du temps et, pour certaines langues, n'est pas réalisable. Vous vous demandez peut-être, pourquoi ne pas simplement prendre un jeu de données conçu pour l'ASR et l'utiliser pour entraîner un modèle TTS ? Malheureusement, ces jeux de données ne sont pas la meilleure option. Les caractéristiques qui le rendent bénéfique pour l'ASR, telles qu'un bruit de fond excessif, sont généralement indésirables dans le TTS. C'est génial de pouvoir transcrire la parole à partir d'un enregistrement bruyant d’une rue par exemple, mais pas tellement si votre assistant vocal vous répond avec des voitures qui klaxonnent et des bruits de travaux en arrière-plan. Néanmoins, certains jeux de données ASR peuvent parfois être utiles pour *finetuner*, car trouver des jeux de données de TTS de haute qualité, multilingues et multi-locuteurs peut être assez difficile.
Explorons quelques ensembles de données adaptés au TTS que vous pouvez trouver sur le  *Hub*.

## LJSpeech

[LJSpeech](https://huggingface.co/datasets/lj_speech) est un jeu de données composé de 13 100 échantillons audio de langue anglaise jumelés à leurs transcriptions correspondantes. Le jeu de données contient l'enregistrement d'un seul locuteur lisant des phrases de 7 livres en anglais. LJSpeech est souvent utilisé comme référence pour évaluer les modèles de TTS en raison de sa haute qualité audio et de son contenu linguistique diversifié.

## Multilingual LibriSpeech
[Multilingual LibriSpeech] (https://huggingface.co/datasets/facebook/multilingual_librispeech) est une extension multilingue du jeu de données LibriSpeech, qui est à la base une collection à grande échelle de livres audio lus en anglais. LibriSpeech multilingue inclus des langues supplémentaires, telles que l'allemand, le néerlandais, l'espagnol, le français, l'italien, le portugais et le polonais. 
Il propose des enregistrements audio ainsi que des transcriptions alignées pour chaque langue. Le jeu de données fournit une ressource précieuse pour développer des systèmes et techniques TTS de synthèse vocale multilingue.

## VCTK (*Voice Cloning Toolkit*)

[VCTK](https://huggingface.co/datasets/vctk) est un jeu de données spécialement conçu pour la recherche et le développement de synthèse vocale.
Il contient des enregistrements audio de 110 anglophones avec divers accents. Chaque orateur lit environ 400 phrases, qui ont été choisies dans un journal, et un paragraphe d'élicitation utilisé pour les archives de l'accent de la parole.
C’est une ressource précieuse pour l’entraînement de modèles de TTS avec des voix et des accents variés, permettant une synthèse vocale plus naturelle et diversifiée.

## Libri-TTS/ LibriTTS-R
[Libri-TTS/ LibriTTS-R](https://huggingface.co/datasets/cdminix/libritts-r-aligned) est un corpus multi-locuteurs d'environ 585 heures de lecture de l'anglais, préparé par Heiga Zen avec l'aide des membres de l'équipe Google Speech et Google Brain. Le corpus LibriTTS est conçu pour la recherche. Il est dérivé des matériaux originaux (fichiers audio mp3 de LibriVox et fichiers texte du projet Gutenberg) du corpus LibriSpeech. Les principales différences par rapport au corpus LibriSpeech sont énumérées ci-dessous : 
* Les fichiers audio sont à une fréquence d'échantillonnage de 24 kHz. 
* Le discours est divisé lors des pauses de phrase. 
* Les textes originaux et normalisés sont inclus. 
* Des informations contextuelles (par exemple, des phrases voisines) peuvent être extraites. 
* Les énoncés avec un bruit de fond important sont exclus.

La conception d'un bon jeu de données pour le TTS n'est pas une tâche facile car un tel jeu de données devrait posséder plusieurs caractéristiques clés :

* Enregistrements de haute qualité et diversifiés qui couvrent un large éventail de modèles de parole, d'accents, de langues et d'émotions. Les enregistrements doivent être clairs, exempts de bruit de fond et présenter des caractéristiques naturelles de la parole.
* Chaque enregistrement audio doit être accompagné de sa transcription textuelle correspondante.
* Le jeu de données doit contenir un large éventail de contenu linguistique, y compris différents types de phrases, de phrases et de mots. Il devrait couvrir divers sujets, genres et domaines pour assurer la capacité du modèle à gérer différents contextes linguistiques.

La bonne nouvelle est qu'il est peu probable que vous ayez à entraîner un modèle de TTS à partir de zéro. Dans la section suivante, nous examinerons les modèles pré-entraînés disponibles sur le *Hub*.

### Unité 6 : Du texte à la parole
https://huggingface.co/learn/audio-course/fr/chapter6/introduction.md

# Unité 6 : Du texte à la parole

Dans l'unité précédente, vous avez appris à utiliser les *transformers* pour convertir la parole en texte. Maintenant, inversons le scénario et voyons comment vous pouvez transformer un texte d'entrée donné en une sortie audio qui ressemble à de la parole.

La tâche que nous allons étudier dans cette unité s'appelle "*Text-to-speech*" (TTS) ou synthèse vocale. Les modèles capables de gérer cette tâche ont un large éventail d'applications potentielles : 

* Applications d'assistance : des outils permettant aux malvoyants d'accéder au contenu numérique par le biais du son.
* Narrations de livres audio : rendre la littérature plus accessible aux personnes qui préfèrent écouter ou qui ont des difficultés à lire.
* Assistants virtuels : les modèles TTS sont un élément fondamental des assistants virtuels tels que Siri, Google Assistant ou Amazon Alexa. Une fois qu'ils ont utilisé un modèle de classification pour repérer le mot déclencheur et un modèle ASR pour traiter la demande, ils peuvent utiliser un modèle de TTS pour répondre à votre demande.
* Divertissement, jeux et apprentissage des langues : donnez une voix à vos personnages, racontez des événements d’un jeu ou aidez les apprenants en leur donnant des exemples de prononciation et d'intonation correctes des mots et des phrases.

Il ne s'agit là que de quelques exemples, et je suis sûr que vous pouvez en imaginer beaucoup d'autres ! Il est important de souligner que les modèles de TTS peuvent être utilisés à des fins malveillantes.
Par exemple, avec suffisamment d'échantillons de voix, il serait possible potentiellement de créer de faux enregistrements audio convaincants, conduisant à l'utilisation non autorisée de la voix d'une personne à des fins frauduleuses ou de manipulation. 
Si vous envisagez de collecter des données pour *finetuner* vos propres systèmes, examinez attentivement la question de la protection de la vie privée et du consentement.
Les données vocales doivent être obtenues avec le consentement explicite des personnes, en veillant à ce qu'elles comprennent l'objectif, la portée et les risques potentiels associés à l'utilisation de leur voix dans un système de synthèse vocale. Utilisez la synthèse vocale de manière responsable.

## Ce que vous allez apprendre et construire

Dans cette unité, nous parlerons de : 

* [Jeux de données pour entraîner un modèle de synthèse vocale](tts_datasets)
* [Modèles pré-entraînés de synthèse vocale](pre-trained_models)
* [*Finetuning* du modèle SpeechT5 sur une nouvelle langue](fine-tuning)
* [Evaluation des modèles TTS](evaluation)

### Lectures et ressources complémentaires
https://huggingface.co/learn/audio-course/fr/chapter6/supplemental_reading.md

# Lectures et ressources complémentaires

Cette unité a introduit la tâche de synthèse vocale et a couvert beaucoup de terrain. 
Vous voulez en savoir plus ? Vous trouverez ici des ressources qui vous aideront à approfondir votre compréhension des sujets et à améliorer votre expérience d'apprentissage.

* [HiFi-GAN : Generative Adversarial Networks for Efficient and High Fidelity Speech Synthesis](https://arxiv.org/pdf/2010.05646.pdf) : article présentant HiFi-GAN pour la synthèse vocale. 
* [X-Vectors : Robust DNN Embeddings For Speaker Recognition](https://www.danielpovey.com/files/2018_icassp_xvectors.pdf) : article présentant la méthode X-Vector pour l'intégration des locuteurs.
* [FastSpeech 2 : Fast and High-Quality End-to-End Text to Speech](https://arxiv.org/pdf/2006.04558.pdf) : un article présentant FastSpeech 2, un autre modèle de synthèse vocale populaire qui utilise une méthode de TTS non autorégressive.
* [A Vector Quantized Approach for Text to Speech Synthesis on Real-World Spontaneous Speech](https://arxiv.org/pdf/2302.04215v1.pdf) : un article présentant MQTTS, un système TTS autorégressif qui remplace les mel-spectrogrammes par une représentation discrète quantifiée.

### Modèles pré-entraînés pour la synthèse vocale
https://huggingface.co/learn/audio-course/fr/chapter6/pre-trained_models.md

# Modèles pré-entraînés pour la synthèse vocale

Par rapport aux tâches de reconnaissance automatique de la parole et de classification audio, il y a beaucoup moins de *checkpoints* de modèles pré-entraînés disponibles. Vous trouverez près de 300 sur le *Hub*. Parmi ces modèles pré-entraînés, nous nous concentrerons sur deux architectures qui sont facilement disponibles dans la bibliothèque 🤗 *Transformers* : SpeechT5 et Massive Multilingual Speech (MMS). Dans cette section, nous allons explorer comment utiliser ces modèles.

## SpeechT5 

[SpeechT5] (https://arxiv.org/abs/2110.07205) est un modèle publié par Junyi Ao et al. de Microsoft qui est capable de gérer une série de tâches vocales. Bien que dans cette unité, nous nous concentrions sur l'aspect texte-parole, ce modèle peut être adapté à des tâches de parole-texte (reconnaissance automatique de la parole ou identification du locuteur), ainsi qu'à des tâches de parole-parole (par exemple, amélioration de la parole ou conversion entre différentes voix). Ceci est dû à la façon dont le modèle est conçu et pré-entraîné. 

Au cœur de SpeechT5 se trouve un *transformer* encodeur-décodeur classique. Ce réseau modélise une transformation de séquence à séquence en utilisant des représentations cachées. Ce *transformer* est le même pour toutes les tâches prises en charge par SpeechT5.

Il est complété par six pré ou post-réseaux modaux spécifiques (parole/texte). La parole ou le texte en entrée (en fonction de la tâche) est prétraité par un pré-réseau correspondant afin d'obtenir les représentations cachées que le *transformer* peut utiliser. La sortie obtenue est ensuite transmise à un post-réseau qui l'utilisera pour générer la sortie dans la modalité cible.

Voici à quoi ressemble l'architecture (image tirée de l'article original) : 

    

SpeechT5 est d'abord pré-entraîné à l'aide de données vocales et textuelles non étiquetées en grande quantité afin d'acquérir une représentation unifiée des différentes modalités. Pendant la phase de pré-entraînement, tous les pré-réseaux et post-réseaux sont utilisés simultanément.

Après le pré-entraînement, le réseau encodeur-décodeur *finetuné* pour chaque tâche individuelle. À cette étape, seuls les pré- et post-réseaux pertinents pour la tâche spécifique sont utilisés. Par exemple, pour utiliser SpeechT5 pour la synthèse vocale, vous aurez besoin du pré-réseau encodeur de texte pour les entrées de texte et des pré-réseaux et post-réseaux du décodeur de parole pour les sorties de parole. 

Cette approche permet d'obtenir plusieurs modèles *finetunés* pour différentes tâches vocales qui bénéficient tous du pré-entraînement initial sur des données non étiquetées.  

Même si les modèles *finetunés* commencent par utiliser le même ensemble de poids provenant du modèle pré-entraîné partagé, les versions finales sont toutes très différentes au bout du compte. Vous ne pouvez pas prendre un modèle ASR *finetuné* et échanger les pré- et post-réseaux pour obtenir un modèle de TTS fonctionnel, par exemple. SpeechT5 est flexible, mais pas à ce point ;)

Voyons quels sont les pré- et post-réseaux que SpeechT5 utilise pour la tâche de TTS :

* Pré-réseau encodeur de texte : Une couche d'enchâssement de texte qui fait correspondre les *tokens* de texte aux représentations cachées que l'encodeur attend. Ceci est similaire à ce qui se passe dans un modèle NLP tel que BERT.
* Pré-réseau de décodage de la parole : Il prend en entrée un spectrogramme log-mel et utilise une séquence de couches linéaires pour compresser le spectrogramme en représentations cachées. 
* Post-réseau décodeur de la parole : Il prédit un résidu à ajouter au spectrogramme de sortie et est utilisé pour affiner les résultats.

Une fois combinée, voici à quoi ressemble l'architecture SpeechT5 pour la synthèse vocale :

    

Comme vous pouvez le constater, la sortie est un spectrogramme log mel et non une forme d'onde. Si vous vous souvenez, nous avons brièvement abordé ce sujet dans l'[unité 3](../chapitre3/introduction#spectrogram-output). Il est courant que les modèles qui génèrent de l'audio produisent un spectrogramme log mel, qui doit être converti en forme d'onde à l'aide d'un réseau neuronal supplémentaire appelé vocodeur.

Voyons comment procéder.

Tout d'abord, chargeons le SpeechT5 *finetuné* sur du TTS depuis le *Hub*, ainsi que l'objet processeur utilisé pour la tokenisation et l'extraction de caractéristiques :

```python
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech

processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")
```

Ensuite, le texte d'entrée est *tokenisé*.

```python
inputs = processor(text="Don't count the days, make the days count.", return_tensors="pt")
```

Le SpeechT5 TTS n'est pas limité à la création de discours pour un seul locuteur. Il utilise en effet ce que l'on appelle des " enchâssements de locuteurs, qui capturent les caractéristiques de la voix d'un locuteur particulier.

L'enchâssement des locuteurs est une méthode permettant de représenter l'identité d'un locuteur de manière compacte, sous la forme d'un vecteur de taille fixe, quelle que soit la longueur de l'énoncé. Ces enchâssements capturent des informations essentielles sur la voix d'un locuteur, son accent, son intonation et d'autres caractéristiques uniques qui distinguent un locuteur d'un autre. De tels enregistrements peuvent être utilisés pour la vérification du locuteur, la diarisation du locuteur, l'identification du locuteur, etc. 
Les techniques les plus courantes pour générer des enchâssements de locuteurs sont les suivantes :

* Les I-Vecteurs (vecteurs d'identité) : ils sont basés sur un modèle de mélange gaussien (GMM). Ils représentent les locuteurs sous la forme de vecteurs de faible dimension et de longueur fixe, dérivés des statistiques d'un GMM spécifique au locuteur, et sont obtenus de manière non supervisée. 
* Les vecteurs X : ils sont dérivés à l'aide de réseaux neuronaux profonds (DNN) et capturent des informations sur le locuteur au niveau de l'image en incorporant le contexte temporel. 

[X-Vectors](https://www.danielpovey.com/files/2018_icassp_xvectors.pdf) est une méthode de pointe qui montre des performances supérieures sur des jeux de données d'évaluation par rapport aux I-Vectors. Le réseau neuronal profond est utilisé pour obtenir les X-Vecteurs : il est entraîné à discriminer les locuteurs, et fait correspondre des énoncés de longueur variable à des enchâssements de dimension fixe. Vous pouvez également charger un enchâssement de locuteur X-Vector qui a été calculé à l'avance et qui encapsule les caractéristiques d'élocution d'un locuteur particulier.

Chargeons un tel enchâssement de locuteur à partir d'un jeu de données sur le *Hub*. Les enchâssements ont été obtenus à partir du [jeu de données CMU ARCTIC](http://www.festvox.org/cmu_arctic/) en utilisant [ce script](https://huggingface.co/mechanicalsea/speecht5-vc/blob/main/manifest/utils/prep_cmu_arctic_spkemb.py), mais n'importe quel enchâssement X-Vector devrait fonctionner.

```python
from datasets import load_dataset

embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")

import torch

speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0)
```

L'enchâssement du locuteur est un tenseur de forme (1, 512). Cette représentation particulière du locuteur décrit une voix féminine.

À ce stade, nous disposons déjà de suffisamment d'entrées pour générer un log mel spectrogramme en sortie :

```python
spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings)
```

Il en résulte un tenseur de forme (140, 80) contenant un log mel spectrogramme. La première dimension est la longueur de la séquence, et elle peut varier d'une exécution à l'autre car le pré-réseau décodeur de parole applique toujours un *dropout* à la séquence d'entrée. Cela ajoute un peu de variabilité aléatoire à la parole générée.

Cependant, si nous cherchons à générer une forme d'onde de la parole, nous devons spécifier un vocodeur à utiliser pour la conversion du spectrogramme en forme d'onde.
En théorie, vous pouvez utiliser n'importe quel vocodeur qui fonctionne sur des mel spectrogrammes 80-bin. De manière pratique, 🤗 *Transformers* propose un vocodeur basé sur HiFi-GAN. Ses poids ont été aimablement fournis par les auteurs originaux de SpeechT5.

[HiFi-GAN](https://arxiv.org/pdf/2010.05646v2.pdf) est un réseau antagoniste génératif (GAN) de pointe conçu pour de la synthèse vocale haute-fidélité. Il est capable de générer des formes d'ondes audio réalistes et de haute qualité à partir de spectrogrammes.

À un niveau élevé, HiFi-GAN se compose d'un générateur et de deux discriminateurs. Le générateur est un réseau neuronal entièrement convolutionnel qui prend un mel spectrogramme en entrée et apprend à produire des formes d'ondes audio brutes. Les discriminateurs ont pour rôle de faire la distinction entre l'audio réel et l'audio généré. Les deux discriminateurs se concentrent sur des aspects différents de l'audio.

HiFi-GAN est entraîné sur un grand jeu de données d'enregistrements audio de haute qualité. Il utilise un entraînement dit antagoniste, dans lequel les réseaux du générateur et du discriminateur sont en compétition l'un contre l'autre. Au départ, le générateur produit un son de faible qualité et le discriminateur peut facilement le différencier du son réel. Au fur et à mesure que l'entraînement progresse, le générateur améliore sa sortie, dans le but de tromper le discriminateur. Le discriminateur, à son tour, devient plus précis dans la distinction entre le son réel et le son généré. Cette boucle de rétroaction antagoniste permet aux deux réseaux de s'améliorer au fil du temps. En fin de compte, HiFi-GAN apprend à générer un son de haute fidélité qui ressemble étroitement aux caractéristiques des données entraînées.

Le chargement du vocodeur est aussi simple que n'importe quel autre modèle de 🤗 *Transformers*.

```python
from transformers import SpeechT5HifiGan

vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")
```

Il ne vous reste plus qu'à le passer en argument lors de la génération de la parole, et les sorties seront automatiquement converties en forme d'onde de la parole.

```python
speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder)
```

Écoutons le résultat. La fréquence d'échantillonnage utilisée par SpeechT5 est toujours de 16 kHz.

```python
from IPython.display import Audio

Audio(speech, rate=16000)
```

Super ! 

N'hésitez pas à jouer avec la démo de SpeechT5 TSS, à explorer d'autres voix, à expérimenter avec les entrées. Notez que ce *checkpoint* pré-entraîné ne prend en charge que la langue anglaise :

## Massive Multilingual Speech (MMS)

Que faire si vous recherchez un modèle pré-entraîné dans une langue autre que l'anglais ? Massive Multilingual Speech (MMS) est un autre modèle qui couvre un large éventail de tâches vocales, mais qui prend en charge un grand nombre de langues. Par exemple, il peut synthétiser la parole dans plus de 1 100 langues.

MMS pour la synthèse vocale est basé sur [VITS Kim et al., 2021] (https://arxiv.org/pdf/2106.06103.pdf), qui est l'une des approches TTS les plus modernes.

VITS est un réseau de génération de parole qui convertit le texte en formes d'ondes vocales brutes. Il fonctionne comme un auto-encodeur variationnel conditionnel, estimant les caractéristiques audio à partir du texte d'entrée. Tout d'abord, les caractéristiques acoustiques, représentées sous forme de spectrogrammes, sont générées. La forme d'onde est ensuite décodée à l'aide de couches convolutives transposées adaptées de HiFi-GAN. 
Pendant l'inférence, les encodages du texte sont suréchantillonnés et transformés en formes d'onde à l'aide du module de flux et du décodeur HiFi-GAN.
Cela signifie que vous n'avez pas besoin d'ajouter un vocodeur pour l'inférence, il est déjà "intégré".  

Essayons le modèle et voyons comment nous pouvons synthétiser de la parole dans une langue autre que l'anglais, par exemple l'allemand.
Tout d'abord, nous allons charger le *checkpoint* du modèle et le *tokenizer* pour la bonne langue : 

```python
from transformers import VitsModel, VitsTokenizer

model = VitsModel.from_pretrained("facebook/mms-tts-deu")
tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-deu")
```

Vous pouvez remarquer que pour charger le MMS, vous devez utiliser `VitsModel` et `VitsTokenizer`. C'est parce que le MMS pour la synthèse vocale est basé sur le modèle VITS comme mentionné précédemment. 

Prenons un exemple de texte en allemand, comme ces deux premières lignes d'une chanson pour enfants : 

```python
text_example = (
    "Ich bin Schnappi das kleine Krokodil, komm aus Ägypten das liegt direkt am Nil."
)
```

Pour générer une forme d'onde, il faut prétraiter le texte à l'aide du *tokenizer* et le transmettre au modèle : 

```python
import torch

inputs = tokenizer(text_example, return_tensors="pt")
input_ids = inputs["input_ids"]

with torch.no_grad():
    outputs = model(input_ids)

speech = outputs.audio[0]
```

Écoutons :

```python
from IPython.display import Audio

Audio(speech, rate=16000)
```

Superbe ! Si vous souhaitez essayer MMS avec une autre langue, trouvez d'autres *checkpoints* `vits` appropriés sur le [*Hub*] (https://huggingface.co/models?filter=vits).

Voyons maintenant comment vous pouvez vous-même *finetuner* un modèle TTS !

### Évaluation des modèles de synthèse vocale
https://huggingface.co/learn/audio-course/fr/chapter6/evaluation.md

# Évaluation des modèles de synthèse vocale

Pendant la période d'entraînement, les modèles de synthèse vocale optimisent la perte d'erreur quadratique moyenne (ou l'erreur absolue moyenne) entre les valeurs prédites du spectrogramme et celles générées. La MSE et la MAE encouragent toutes deux le modèle à minimiser la différence entre les spectrogrammes prédits et les spectrogrammes cibles.
Toutefois, étant donné que la synthèse vocale est un problème d'association un-à-plusieurs, c'est-à-dire que le spectrogramme de sortie pour un texte donné peut être représenté de nombreuses manières différentes, l'évaluation des modèles de synthèse vocale qui en résultent est beaucoup plus difficile. 

Contrairement à de nombreuses autres tâches informatiques qui peuvent être mesurées objectivement à l'aide de paramètres quantitatifs, tels que l'exactitude ou la précision, l'évaluation des modèles de synthèse vocale repose en grande partie sur une analyse humaine subjective.

L'une des méthodes d'évaluation les plus couramment employées pour les systèmes de reconnaissance vocale consiste à réaliser des évaluations qualitatives à l'aide de scores d'opinion moyens (MOS pour *mean opinion scores*). Le MOS est un système de notation subjectif qui permet aux évaluateurs humains de noter la qualité perçue de la parole synthétisée sur une échelle de 1 à 5. Ces scores sont généralement recueillis lors de tests d'écoute, au cours desquels des participants humains écoutent et évaluent des échantillons de parole synthétisée.

L'une des principales raisons pour lesquelles il est difficile de développer des mesures objectives pour l'évaluation de la synthèse vocale est la nature subjective de la perception de la parole. Les auditeurs humains ont des préférences et des sensibilités diverses pour différents aspects de la parole, notamment la prononciation, l'intonation, le naturel et la clarté. Saisir ces nuances perceptives avec une seule valeur numérique est une tâche ardue. En même temps, la subjectivité de l'évaluation humaine rend difficile la comparaison et l'étalonnage de différents systèmes de traitement de la parole.

En outre, ce type d'évaluation peut négliger certains aspects importants de la synthèse vocale, tels que le naturel, l'expressivité et l'impact émotionnel. Ces qualités sont difficiles à quantifier objectivement mais sont très importantes dans les applications où la parole synthétisée doit transmettre des qualités humaines et susciter des réactions émotionnelles appropriées.

En résumé, l'évaluation des modèles de synthèse vocale est une tâche complexe en raison de l'absence d'une mesure véritablement objective. La méthode d'évaluation la plus courante, le MOS, repose sur une analyse humaine subjective. Bien qu'il fournisse des informations précieuses sur la qualité de la parole synthétisée, il introduit également de la variabilité et de la subjectivité.

### Traduction parole-à-parole
https://huggingface.co/learn/audio-course/fr/chapter7/speech-to-speech.md

# Traduction parole-à-parole 

La traduction parole-à-parole (STST ou S2ST pour *Speech-to-speech translation*) est une tâche de traitement du langage parlé relativement nouvelle. Elle consiste à traduire le discours d'une langue en un discours dans une langue **différente** :

    

La STST peut être considérée comme une extension de la tâche traditionnelle de traduction automatique : au lieu de traduire du **texte** d'une langue à une autre, nous traduisons de la **parole** d'une langue à une autre. La STST trouve des applications dans le domaine de la communication multilingue, en permettant à des locuteurs de langues différentes de communiquer entre eux par l'intermédiaire de la parole.

Supposons que vous souhaitiez communiquer avec une autre personne au-delà de la barrière de la langue. Plutôt que d'écrire l'information que vous souhaitez transmettre et de la traduire ensuite en texte dans la langue cible, vous pouvez la parler directement et demander à un système STST de convertir votre discours dans la langue cible. Le destinataire peut alors répondre en s'adressant au système STST, et vous pouvez écouter sa réponse. Cette méthode de communication est plus naturelle que la traduction automatique basée sur le texte.

Dans ce chapitre, nous allons explorer une approche *cascadée* de la STST, en rassemblant les connaissances que vous avez acquises dans les unités 5 et 6 du cours. Nous utiliserons un système de *traduction vocale* pour transcrire le discours source en texte dans la langue cible, puis un système de *text-to-speech* pour générer du discours dans la langue cible à partir du texte traduit :

    

Nous aurions également pu utiliser une approche en trois étapes, en commençant par utiliser un système de reconnaissance automatique de la parole (ASR) pour transcrire la parole source en texte dans la même langue, puis la traduction automatique pour traduire le texte transcrit dans la langue cible, et enfin la synthèse vocale pour générer de la parole dans la langue cible. Cependant, l'ajout d'autres composants au pipeline se prête à la propagation d'erreurs, où les erreurs introduites dans un système sont aggravées lorsqu'elles passent par les systèmes restants, et augmente également le temps de latence, puisque l'inférence doit être effectuée pour davantage de modèles.

Bien que cette approche en deux étapes de la STST soit assez simple, elle permet d'obtenir des systèmes très efficaces. Le système en deux étapes à trois étapes ASR + traduction automatique + TTS a été utilisé précédemment pour de nombreux produits STST commerciaux, y compris [*Google Translate*](https://ai.googleblog.com/2019/05/introducing-translatotron-end-to-end.html).
Il s'agit également d'une méthode très efficace en termes de données et de calcul, puisque les systèmes de reconnaissance vocale et de synthèse vocale existants peuvent être couplés pour produire un nouveau modèle de STST sans aucun entraînement supplémentaire.

Dans la suite de cette unité, nous nous concentrerons sur la création d'un système de STST qui traduit la parole de n'importe quelle langue X en anglais. Les méthodes abordées peuvent être étendues aux systèmes de STST qui traduisent de n'importe quelle langue X vers n'importe quelle langue Y, mais nous laissons cette extension au lecteur et fournissons des pointeurs le cas échéant. Nous divisons ensuite la tâche de STST en ses deux composantes constitutives : traduction vocale et synthèse vocale. Nous terminerons en les assemblant pour construire une démo Gradio afin de présenter notre système.

## Traduction vocale

Nous utilisons le modèle Whisper puisqu'il est capable de traduire plus de 96 langues vers l'anglais. Plus précisément, nous chargerons le *checkpoint* [Whisper Base](https://huggingface.co/openai/whisper-base), qui contient 74 millions de paramètres. Ce n'est en aucun cas le modèle Whisper le plus performant (le [plus grand *checkpoint* Whisper](https://huggingface.co/openai/whisper-large-v2) étant plus de 20 fois plus grand) mais comme nous concaténons deux systèmes autorégressifs, nous voulons nous assurer que chaque modèle peut générer relativement rapidement afin d'obtenir une vitesse d'inférence raisonnable :

```python
import torch
from transformers import pipeline

device = "cuda:0" if torch.cuda.is_available() else "cpu"
pipe = pipeline(
    "automatic-speech-recognition", model="openai/whisper-base", device=device
)
```

C'est très bien ! Pour tester notre système de STST, nous allons charger un échantillon audio dans une autre langue que l'anglais. Chargeons le premier exemple de la partie italienne (`it`) du jeu de données [VoxPopuli](https://huggingface.co/datasets/qmeeus/voxpopuli) :

```python
from datasets import load_dataset

dataset = load_dataset("qmeeus/voxpopuli", "it", split="validation", streaming=True)
sample = next(iter(dataset))
```

Pour écouter cet échantillon, nous pouvons soit le jouer en utilisant le *viewer* sur le *Hub* : [qmeeus/voxpopuli/viewer](https://huggingface.co/datasets/qmeeus/voxpopuli/viewer/it/validation?row=0)

Ou le lire à l'aide de la fonction audio d'ipynb :

```python
from IPython.display import Audio

Audio(sample["audio"]["array"], rate=sample["audio"]["sampling_rate"])
```

Maintenant, définissons une fonction qui prend cette entrée audio et retourne le texte traduit. Vous vous rappelez que nous devons passer l'argument `"task": "translate"` pour s'assurer que Whisper effectue de la traduction vocale et non de la reconnaissance vocale :

```python
def translate(audio):
    outputs = pipe(audio, max_new_tokens=256, generate_kwargs={"task": "translate"})
    return outputs["text"]
```

Whisper peut aussi être "trompé" pour traduire de la parole dans n'importe quelle langue X vers n'importe quelle langue Y. Il suffit de mettre la tâche à `"transcribe"` et `"language"` à votre langue cible en argument. Par exemple pour l'espagnol, on mettrait : `generate_kwargs={"task" : "transcribe", "language" : "es"&rcub;`

Bien, vérifions rapidement que nous obtenons un résultat raisonnable à partir du modèle :

```python
translate(sample["audio"].copy())
```

```
' psychological and social. I think that it is a very important step in the construction of a juridical space of freedom, circulation and protection of rights.'
```

Ok, et si nous comparons cela au texte source :

```python
sample["text"]
```

```
'Penso che questo sia un passo in avanti importante nella costruzione di uno spazio giuridico di libertà di circolazione e di protezione dei diritti per le persone in Europa.'
```

Nous constatons que la traduction est plus ou moins conforme (vous pouvez la vérifier en utilisant Google Translate ou DeepL), à l'exception de quelques mots supplémentaires au début de la transcription, lorsque le locuteur terminait sa phrase précédente.

Nous avons ainsi terminé la première moitié de notre pipeline de STST en deux étapes, en mettant en pratique les compétences acquises dans l'unité 5 lorsque nous avons appris à utiliser le modèle Whisper pour la reconnaissance vocale et la traduction. Si vous souhaitez vous rafraîchir la mémoire sur l'une des étapes que nous avons couvertes, lisez la section [Modèles pré-entraînés pour la reconnaissance automatique de la parole](../chapiter5/asr_models) de l'unité 5.

## Synthèse vocale

La deuxième partie de notre système de STST en deux étapes consiste à passer d'un texte anglais à la parole en anglais. Pour cela, nous utiliserons le modèle pré-entraîné [SpeechT5 TTS](https://huggingface.co/microsoft/speecht5_tts). 🤗 *Transformers* n'a actuellement pas de `pipeline` TTS, donc nous devrons utiliser le modèle directement nous-mêmes. Ce n'est pas grave, vous êtes tous experts dans l'utilisation du modèle pour l'inférence après l'unité 6 !

Tout d'abord, chargeons le processeur SpeechT5, le modèle et le vocodeur à partir du *checkpoint* pré-entraîné :

```python
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech, SpeechT5HifiGan

processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")

model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")
vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")
```

    Nous utilisons ici le *checkpoint* SpeechT5 entraîné spécifiquement pour le TTS anglais. Si vous souhaitez traduire dans une autre langue que l'anglais, remplacez le *checkpoint* par un modèle SpeechT5 TTS *finetuné* dans la langue de votre choix, ou utilisez un *checkpoint* MMS TTS pré-entraîné dans la langue cible.

Comme pour le Whisper, nous placerons le SpeechT5 et le vocodeur sur notre GPU, si nous en avons un :

```python
model.to(device)
vocoder.to(device)
```

Bien, chargeons les enregistrements du locuteur :

```python
embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")
speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0)
```

Nous pouvons maintenant écrire une fonction qui prend en entrée un prompt de texte et génère le discours correspondant. Nous allons d'abord prétraiter l'entrée textuelle à l'aide du processeur SpeechT5, en tokenisant le texte pour obtenir nos identifiants d'entrée. Nous transmettons ensuite les identifiants d'entrée et les enchâssements de locuteurs au modèle SpeechT5, en plaçant chacun d'entre eux sur le GPU s'il est disponible. Enfin, nous renverrons le discours généré au CPU pour qu'il puisse être lu dans notre *notebook* :

```python
def synthesise(text):
    inputs = processor(text=text, return_tensors="pt")
    speech = model.generate_speech(
        inputs["input_ids"].to(device), speaker_embeddings.to(device), vocoder=vocoder
    )
    return speech.cpu()
```

Vérifions qu'il fonctionne avec une entrée de texte fictive :

```python
speech = synthesise("Hey there! This is a test!")

Audio(speech, rate=16000)
```

Ça a l'air bien ! Passons maintenant à la partie la plus excitante : assembler le tout.

## Creating a STST demo

Avant de créer une démo [Gradio](https://gradio.app) pour présenter notre système de STST, effectuons d'abord une vérification rapide pour nous assurer que nous pouvons concaténer les deux modèles, en introduisant un échantillon audio et en obtenant un échantillon audio. Pour ce faire, nous concaténerons les deux fonctions définies dans les deux sous-sections précédentes, de sorte que nous entrons l'audio source et récupérons le texte traduit, puis nous synthétisons le texte traduit pour obtenir la parole traduite. Enfin, nous allons convertir la synthèse vocale en un *array* `int16`, qui est le format de fichier audio de sortie attendu par Gradio. Pour ce faire, nous devons d'abord normaliser l'*array* audio par la plage dynamique de la cible de type (`int16`), puis convertir le type par défaut de NumPy (`float64`) vers la cible de type (`int16`) :

```python
import numpy as np

target_dtype = np.int16
max_range = np.iinfo(target_dtype).max

def speech_to_speech_translation(audio):
    translated_text = translate(audio)
    synthesised_speech = synthesise(translated_text)
    synthesised_speech = (synthesised_speech.numpy() * max_range).astype(np.int16)
    return 16000, synthesised_speech
```

Vérifions que cette fonction concaténée donne le résultat attendu :

```python
sampling_rate, synthesised_speech = speech_to_speech_translation(sample["audio"])

Audio(synthesised_speech, rate=sampling_rate)
```

Parfait ! Nous allons à présent intégrer tout cela dans une belle démo Gradio afin d'enregistrer notre source vocale à l'aide d'un microphone ou d'un fichier et de lire la prédiction du système :

```python
import gradio as gr

demo = gr.Blocks()

mic_translate = gr.Interface(
    fn=speech_to_speech_translation,
    inputs=gr.Audio(source="microphone", type="filepath"),
    outputs=gr.Audio(label="Generated Speech", type="numpy"),
)

file_translate = gr.Interface(
    fn=speech_to_speech_translation,
    inputs=gr.Audio(source="upload", type="filepath"),
    outputs=gr.Audio(label="Generated Speech", type="numpy"),
)

with demo:
    gr.TabbedInterface([mic_translate, file_translate], ["Microphone", "Audio File"])

demo.launch(debug=True)
```

Cela lancera une démo Gradio similaire à celle qui fonctionne sur le *Space* suivant :

Vous pouvez [dupliquer](https://huggingface.co/spaces/course-demos/speech-to-speech-translation?duplicate=true) cette démo et l'adapter pour utiliser un *checkpoint* Whisper différent, un *checkpoint* TTS différent, ou travailler sur une autre langue que l'anglais et suivre les conseils fournis pour traduire dans la langue de votre choix !

## Pour aller plus loin

Bien que le système en deux étapes soit un moyen efficace de construire un système de STST, il souffre des problèmes de propagation d'erreurs et de latence additive décrits ci-dessus. Des travaux récents ont exploré une approche *directe* de la STST, qui ne prédit pas de texte intermédiaire et qui, au lieu de cela, établit une correspondance directe entre la parole source et la parole cible. Ces systèmes sont également capables de conserver les caractéristiques de la parole du locuteur source dans la parole cible (telles que la prosodie, la hauteur et l'intonation). Si vous souhaitez en savoir plus sur ces systèmes, consultez les ressources répertoriées dans la section [lectures complémentaires](supplemental_reading).

### Exercice pratique
https://huggingface.co/learn/audio-course/fr/chapter7/hands-on.md

# Exercice pratique

Dans cette unité, nous avons consolidé le matériel couvert dans les six unités précédentes du cours pour créer trois applications audio. Comme vous l'avez constaté, il est tout à fait possible de créer des outils audio plus complexes en utilisant les compétences fondamentales que vous avez acquises dans ce cours.

L'exercice pratique prend l'une des applications couvertes dans cette unité, et l'étend avec quelques modifications multilingues 🌍 Votre objectif est de prendre la [démo Gradio de traduction vocale en deux étapes](https://huggingface.co/spaces/course-demos/speech-to-speech-translation) de la première section de cette unité, et de la mettre à jour pour la traduire dans n'importe quelle langue **non-anglaise**. En d'autres termes, la démo doit prendre un discours dans une langue X, et le traduire en un discours dans une langue Y, où la langue cible Y n'est pas l'anglais. Vous devriez commencer par [dupliquer](https://huggingface.co/spaces/course-demos/speech-to-speech-translation?duplicate=true) le modèle sous votre espace Hugging Face. Il n'est pas néce

Des conseils pour mettre à jour la fonction de traduction vocale afin d'effectuer une traduction vocale multilingue sont fournis dans la section sur la [traduction parole-parole](speech-to-speech). En suivant ces instructions, vous devriez être en mesure de mettre à jour la démo pour traduire de la parole dans la langue X vers du texte dans la langue Y, ce qui représente la moitié de la tâche !

Pour synthétiser du texte dans la langue Y vers la parole dans la langue Y, où Y est une langue multilingue, vous devrez utiliser un *checkpoint* TTS multilingue. Pour cela, vous pouvez utiliser soit celui de SpeechT5 TTS que vous avez *finetuné* dans l'exercice pratique précédent, soit un un *checkpoint* TTS multilingue pré-entraîné. Il y a alors deux options pour ce dernier cas : soit le *checkpoint* [sanchit-gandhi/speecht5_tts_vox_nl](https://huggingface.co/sanchit-gandhi/speecht5_tts_vox_nl), qui est un SpeechT5 *finetuné* sur la partie néerlandaise de [VoxPopuli](https://huggingface.co/datasets/facebook/voxpopuli), soit un *checkpoint* MMS TTS (voir la section [modèles pretrainés pour TTS](../chapter6/pre-trained_models)).

D'après notre expérience avec le néerlandais, l'utilisation d'un *checkpoint* MMS TTS permet d'obtenir de meilleures performances qu'un *checkpoint* SpeechT5 *finetuné* mais il se peut que votre *checkpoint* TTS *fientuné* soit préférable dans votre langue.

Votre démo doit prendre en entrée un fichier audio, et retourner en sortie un autre fichier audio, correspondant à la signature de la fonction [`speech_to_speech_translation`](https://huggingface.co/spaces/course-demos/speech-to-speech-translation/blob/3946ba6705a6632a63de8672ac52a482ab74b3fc/app.py#L35). Par conséquent, nous vous recommandons de laisser la fonction principale `speech_to_speech_translation` telle quelle, et de ne mettre à jour les fonctions [`translate`](https://huggingface.co/spaces/course-demos/speech-to-speech-translation/blob/a03175878f522df7445290d5508bfb5c5178f787/app.py#L24) et [`synthesise`](https://huggingface.co/spaces/course-demos/speech-to-speech-translation/blob/a03175878f522df7445290d5508bfb5c5178f787/app.py#L29) que si nécessaire.

Une fois que vous avez construit votre démo sur le *Hub*, vous pouvez la soumettre pour évaluation. Rendez-vous dans le *Space* [audio-course-u7-assessment](https://huggingface.co/spaces/huggingface-course/audio-course-u7-assessment) et indiquez l'identifiant de dépôt de votre démo. Ce *Space* vérifiera que votre démo a été construite correctement en envoyant un échantillon de fichier audio à votre démo et en vérifiant que le fichier audio renvoyé n'est pas en anglais. Si votre démo fonctionne correctement, vous obtiendrez une coche verte à côté de votre nom sur le [*Space* de progression](https://huggingface.co/spaces/MariaK/Check-my-progress-Audio-Course) ✅

### Transcrire une réunion
https://huggingface.co/learn/audio-course/fr/chapter7/transcribe-meeting.md

# Transcrire une réunion

Dans cette dernière section, nous utiliserons le modèle Whisper pour générer la transcription d'une conversation ou d'une réunion entre deux ou plusieurs locuteurs. Nous l'associerons ensuite à un modèle de *séparation des locuteurs* pour prédire "qui a parlé quand". En faisant correspondre les horodatages des transcriptions Whisper avec les horodatages du modèle de séparation des locuteurs, nous pouvons prédire une transcription de réunion de bout en bout avec des heures de début et de fin entièrement formatées pour chaque locuteur. Il s'agit d'une version basique des services de transcription de réunions que vous avez pu voir en ligne sur [Otter.ai](https://otter.ai) et co :

     
 

## Séparation des locuteurs

La séparation des locuteur (tâche de *diarization* en anglais) consiste à prendre une entrée audio non étiquetée et à prédire "qui a parlé quand".
Ce faisant, nous pouvons prédire les horodatages de début / fin pour chaque tour de parole, correspondant au moment où chaque locuteur commence à parler et au moment où il termine.

🤗 *Transformers* n'a actuellement pas de modèle de *diarization* inclus, mais il y a des *checkpoints* sur le *Hub* qui peuvent être utilisés avec une relative facilité. Dans cet exemple, nous utiliserons le modèle pré-entraîné de [pyannote.audio](https://github.com/pyannote/pyannote-audio). Commençons par l'installation du paquet avec pip :

```bash
pip install --upgrade pyannote.audio
```

Bien, les poids de ce modèle sont hébergés sur le *Hub*. Pour y accéder, nous devons d'abord accepter les conditions d'utilisation du modèle de *diarization* : [pyannote/speaker-diarization](https://huggingface.co/pyannote/speaker-diarization). Et ensuite les conditions d'utilisation du modèle de segmentation : [pyannote/segmentation](https://huggingface.co/pyannote/segmentation).

Une fois terminé, nous pouvons charger le pipeline de séparation des locuteurs localement sur notre appareil :

```python
from pyannote.audio import Pipeline

diarization_pipeline = Pipeline.from_pretrained(
    "pyannote/speaker-diarization@2.1", use_auth_token=True
)
```

Essayons-le sur un échantillon de fichier audio ! Pour cela, nous allons charger un échantillon du jeu de données [LibriSpeech ASR](https://huggingface.co/datasets/librispeech_asr) qui consiste en deux locuteurs différents qui ont été concaténés ensemble pour donner un seul fichier audio :

```python
from datasets import load_dataset

concatenated_librispeech = load_dataset(
    "sanchit-gandhi/concatenated_librispeech", split="train", streaming=True
)
sample = next(iter(concatenated_librispeech))
```

Nous pouvons écouter l'audio pour voir à quoi cela ressemble :

```python
from IPython.display import Audio

Audio(sample["audio"]["array"], rate=sample["audio"]["sampling_rate"])
```

Nous pouvons clairement entendre deux locuteurs différents, avec une transition d'environ 15 secondes. Passons ce fichier audio au modèle de séparation pour obtenir les heures de début et de fin du locuteur. Notez que pyannote.audio s'attend à ce que l'entrée audio soit un tenseur PyTorch de la forme `(channels, seq_len)`, nous devons donc effectuer cette conversion avant d'exécuter le modèle :

```python
import torch

input_tensor = torch.from_numpy(sample["audio"]["array"][None, :]).float()
outputs = diarization_pipeline(
    {"waveform": input_tensor, "sample_rate": sample["audio"]["sampling_rate"]}
)

outputs.for_json()["content"]
```

```text
[{'segment': {'start': 0.4978125, 'end': 14.520937500000002},
  'track': 'B',
  'label': 'SPEAKER_01'},
 {'segment': {'start': 15.364687500000002, 'end': 21.3721875},
  'track': 'A',
  'label': 'SPEAKER_00'}]
```

Cela semble plutôt bien ! Nous pouvons voir que le premier locuteur est prédit comme parlant jusqu'à la marque de 14,5 secondes, et le second locuteur à partir de 15,4s. Il ne nous reste plus qu'à obtenir notre transcription !

## Transcription de la parole

Pour la troisième fois dans cette unité, nous allons utiliser le modèle Whisper pour notre système de transcription de la parole. Plus précisément, nous chargerons le *checkpoint* [Whisper Base](https://huggingface.co/openai/whisper-base), car il est suffisamment petit pour donner une bonne vitesse d'inférence avec une précision de transcription raisonnable. Comme auparavant, vous pouvez utiliser n'importe quel *checkpoint *de reconnaissance vocale disponible sur le [*Hub*](https://huggingface.co/models?pipeline_tag=automatic-speech-recognition&library=transformers&sort=trending), y compris Wav2Vec2, MMS ASR ou d'autres tailles de Whisper :

```python
from transformers import pipeline

asr_pipeline = pipeline(
    "automatic-speech-recognition",
    model="openai/whisper-base",
)
```

Obtenons la transcription de notre échantillon audio, en retournant également les horodatages au niveau du segment afin que nous connaissions les heures de début et de fin de chaque segment. Vous vous souviendrez de l'unité 5 que nous devons passer l'argument `return_timestamps=True` pour activer la tâche de prédiction de l'horodatage de Whisper :

```python
asr_pipeline(
    sample["audio"].copy(),
    generate_kwargs={"max_new_tokens": 256},
    return_timestamps=True,
)
```

```text
{
    "text": " The second and importance is as follows. Sovereignty may be defined to be the right of making laws. In France, the king really exercises a portion of the sovereign power, since the laws have no weight. He was in a favored state of mind, owing to the blight his wife's action threatened to cast upon his entire future.",
    "chunks": [
        {"timestamp": (0.0, 3.56), "text": " The second and importance is as follows."},
        {
            "timestamp": (3.56, 7.84),
            "text": " Sovereignty may be defined to be the right of making laws.",
        },
        {
            "timestamp": (7.84, 13.88),
            "text": " In France, the king really exercises a portion of the sovereign power, since the laws have",
        },
        {"timestamp": (13.88, 15.48), "text": " no weight."},
        {
            "timestamp": (15.48, 19.44),
            "text": " He was in a favored state of mind, owing to the blight his wife's action threatened to",
        },
        {"timestamp": (19.44, 21.28), "text": " cast upon his entire future."},
    ],
}
```

Ok, nous constatons que chaque segment de la transcription a une heure de début et une heure de fin, avec un changement de locuteur au bout de 15,48 secondes. Nous pouvons maintenant associer cette transcription aux horodatages des locuteurs que nous avons obtenus à partir de notre modèle de *diarization* pour obtenir notre transcription finale.

## Speechbox

Pour obtenir la transcription finale, nous allons aligner les timestamps du modèle de diarisation avec ceux du modèle Whisper.
Le modèle de séparation prédit que le premier locuteur se termine à 14,5 secondes et que le second locuteur commence à 15,4 secondes, alors que Whisper prédit les limites des segments à 13,88, 15,48 et 19,44 secondes respectivement. Comme les timestamps de Whisper ne correspondent pas parfaitement à ceux du modèle de séparation, nous devons trouver lesquelles de ces limites sont les plus proches de 14,5 et 15,4 secondes, et segmenter la transcription par locuteur en conséquence. Plus précisément, nous trouverons l'alignement le plus proche entre les horodatages de la séparation et de la transcription en minimisant la distance absolue entre les deux.

Heureusement pour nous, nous pouvons utiliser 🤗 *Speechbox* pour effectuer cet alignement. Tout d'abord, installons `speechbox` depuis *main* :

```bash
pip install git+https://github.com/huggingface/speechbox
```

Nous pouvons maintenant instancier notre pipeline combiné de *diarization* et de transcription, en passant nos deux modèles à la classe [`ASRDiarizationPipeline`](https://github.com/huggingface/speechbox/tree/main#asr-with-speaker-diarization) :

```python
from speechbox import ASRDiarizationPipeline

pipeline = ASRDiarizationPipeline(
    asr_pipeline=asr_pipeline, diarization_pipeline=diarization_pipeline
)
```

    Vous pouvez également instancier le `ASRDiarizationPipeline` directement à partir d'un modèle pré-entraîné en spécifiant l'identifiant d'un modèle ASR sur le *Hub* : `pipeline = ASRDiarizationPipeline.from_pretrained("openai/whisper-base")`

Passons le fichier audio au pipeline et voyons ce que nous obtenons :

```python
pipeline(sample["audio"].copy())
```

```text
[{'speaker': 'SPEAKER_01',
  'text': ' The second and importance is as follows. Sovereignty may be defined to be the right of making laws. In France, the king really exercises a portion of the sovereign power, since the laws have no weight.',
  'timestamp': (0.0, 15.48)},
 {'speaker': 'SPEAKER_00',
  'text': " He was in a favored state of mind, owing to the blight his wife's action threatened to cast upon his entire future.",
  'timestamp': (15.48, 21.28)}]
```

Excellent ! Le premier locuteur est segmenté comme parlant de 0 à 15,48 secondes, et le second locuteur de 15,48 à 21,28 secondes, avec les transcriptions correspondantes pour chacun.

Nous pouvons formater les horodatages de manière un peu plus agréable en définissant deux fonctions d'aide. La première convertit un *tuple* d'horodatages en une chaîne de caractères, arrondie à un nombre défini de décimales. La seconde combine l'identifiant du locuteur, l'horodatage et les informations textuelles sur une seule ligne, et sépare chaque locuteur sur sa propre ligne pour faciliter la lecture :

```python
def tuple_to_string(start_end_tuple, ndigits=1):
    return str((round(start_end_tuple[0], ndigits), round(start_end_tuple[1], ndigits)))

def format_as_transcription(raw_segments):
    return "\n\n".join(
        [
            chunk["speaker"] + " " + tuple_to_string(chunk["timestamp"]) + chunk["text"]
            for chunk in raw_segments
        ]
    )
```

Exécutons à nouveau le pipeline, en formatant cette fois la transcription selon la fonction que nous venons de définir :

```python
outputs = pipeline(sample["audio"].copy())

format_as_transcription(outputs)
```

```text
SPEAKER_01 (0.0, 15.5) The second and importance is as follows. Sovereignty may be defined to be the right of making laws.
In France, the king really exercises a portion of the sovereign power, since the laws have no weight.

SPEAKER_00 (15.5, 21.3) He was in a favored state of mind, owing to the blight his wife's action threatened to cast upon
his entire future.
```

Et voilà ! Nous avons ainsi séparé et transcrit notre audio et renvoyé des transcriptions segmentées par locuteur.
Bien que l'algorithme de distance minimale pour aligner les horodatages diarisés et les horodatages transcrits soit simple, il fonctionne bien dans la pratique. Si vous souhaitez explorer des méthodes plus avancées pour combiner les horodatages, le code source de `ASRDiarizationPipeline` est un bon point de départ : [speechbox/diarize.py](https://github.com/huggingface/speechbox/blob/96d2d1a180252d92263f862a1cd25a48860f1aed/src/speechbox/diarize.py#L12).

### Unité 7. Rassemblement de tous les éléments
https://huggingface.co/learn/audio-course/fr/chapter7/introduction.md

# Unité 7. Rassemblement de tous les éléments

Bravo d'être arrivé à l'unité 7 ! Vous êtes à quelques pas de terminer le cours et d'acquérir les dernières compétences dont vous avez besoin pour naviguer dans le domaine de l'apprentissage machine audio. 
En termes de compréhension, vous savez déjà tout ce qu'il y a à savoir.
Ensemble, nous avons couvert de manière exhaustive les principaux sujets qui constituent le domaine audio et la théorie qui les accompagne (données, classification, reconnaissance de la parole et synthèse vocale). 
L'objectif de cette unité est de fournir un cadre pour **assembler tout cela** : maintenant que vous savez comment chacune de ces tâches fonctionne indépendamment, nous allons explorer comment vous pouvez les combiner pour construire des applications du monde réel.

## Ce que vous allez apprendre et construire

Dans cette unité, nous aborderons les trois sujets suivants :

* [Traduction parole-à-parole](speech-to-speech) : traduire l'audio d'une langue en audio dans une autre langue.
* [Créer un assistant vocal](voice-assistant) : créer votre propre assistant vocal qui fonctionne de la même manière qu'Alexa ou Siri.
* [Transcription de réunions](transcribe-meeting) : transcrire une réunion et indiquez sur la transcription qui a parlé et à quel moment.

### Créer un assistant vocal
https://huggingface.co/learn/audio-course/fr/chapter7/voice-assistant.md

# Créer un assistant vocal

Dans cette section, nous allons rassembler trois modèles déjà vus pour construire un assistant vocal de bout en bout baptisé **Marvin** 🤖. Comme Alexa d'Amazon ou Siri d'Apple, Marvin est un assistant vocal répondant à un mot déclencheur particulier, écoutant ensuite une requête vocale et répond enfin par une réponse vocale.

Nous pouvons décomposer le pipeline de l'assistant vocal en quatre étapes, chacune d'entre elles nécessitant un modèle autonome :

     
 

### 1. Détection du mot déclencheur

Les assistants vocaux écoutent en permanence les entrées audio provenant du microphone de votre appareil, mais ils ne se mettent en action que lorsqu'un mot déclencheur (ou mot de réveil) particulier est prononcé.

La tâche de détection des mots déclencheurs est gérée par un petit modèle de classification audio sur l'appareil, qui est beaucoup plus petit et plus léger que le modèle de reconnaissance vocale, ne comportant souvent que quelques millions de paramètres, contre plusieurs centaines de millions pour la reconnaissance vocale. Il peut donc être exécuté en continu sur l'appareil sans en épuiser la batterie. Ce n'est que lorsque le mot de réveil est détecté que le modèle de reconnaissance vocale, plus grand, est lancé, avant d'être à nouveau arrêté.

### 2. Transcription de la parole

L'étape suivante du processus consiste à transcrire la requête vocale en texte. Dans la pratique, le transfert des fichiers audio de votre appareil local vers le *cloud* est lent en raison de la nature volumineuse des fichiers audio. Il est donc plus efficace de les transcrire directement à l'aide d'un modèle d'ASR sur l'appareil plutôt qu'à l'aide d'un modèle dans le *cloud*. Le modèle sur l'appareil peut être plus petit et donc moins précis qu'un modèle hébergé dans le *cloud*, mais la vitesse d'inférence plus rapide en vaut la peine puisque nous pouvons exécuter la reconnaissance vocale quasiment en temps réel, notre énoncé audio étant transcrit au fur et à mesure que nous le prononçons.

Nous sommes maintenant très familiers avec le processus de reconnaissance vocale, donc cela devrait être un jeu d'enfant !

### 3. Requêter le modèle de langage

Maintenant que nous savons ce que l'utilisateur a demandé, nous devons générer une réponse ! Les meilleurs modèles candidats pour cette tâche sont les *grands modèles de langage (LLM)*, car ils sont effectivement capables de comprendre la sémantique de la requête textuelle et de générer une réponse appropriée.

Puisque notre requête textuelle est petite (juste quelques *tokens*), et les modèles de langage volumineux (plusieurs milliards de paramètres), la façon la plus efficace d'exécuter l'inférence est d'envoyer notre requête textuelle de notre appareil à un LLM fonctionnant dans le *cloud*, de générer une réponse textuelle, et de renvoyer la réponse à l'appareil.

### 4. Synthétiser la réponse

Enfin, nous utiliserons un modèle de synthèse vocale pour synthétiser la réponse textuelle sous forme de parole. Cette opération s'effectue sur l'appareil, mais il est tout à fait possible d'exécuter un modèle de synthèse vocale dans le *cloud*, en générant la sortie audio et en la transférant vers l'appareil.

Encore une fois, nous avons fait cela plusieurs fois maintenant, donc le processus sera très familier !

## Détection des mots déclencheur

La première étape du pipeline de l'assistant vocal consiste à détecter si le mot déclencheur a été prononcé, et nous devons donc trouver un modèle pré-entraîné approprié pour cette tâche ! Vous vous souviendrez de la section sur les [modèles pré-entraînés pour la classification audio](../chapiter4/classification_models) que [Speech Commands](https://huggingface.co/datasets/speech_commands) est un jeu de données de mots prononcés conçu pour évaluer les modèles de classification audio sur plus de 15 mots de commande simples comme `up`, `down`, `yes` et `no`, ainsi qu'un label `silence` pour classer l'absence de parole. Prenez une minute pour écouter les échantillons sur le visualisateur de jeux de données du *Hub* et vous familiariser à nouveau avec le jeu de données : [visualisateur](https://huggingface.co/datasets/speech_commands/viewer/v0.01/train).

Nous pouvons utiliser un modèle de classification audio pré-entraîné sur le jeu de données Speech Commands et choisir l'un de ces mots de commande simples comme mot déclencheur. Parmi plus de 15 mots de commande possibles, si le modèle prédit avec la plus grande probabilité le mot que nous avons choisi, nous pouvons être quasiment certains que ce mot de déclencheur a été prononcé.

Rendez-vous sur le *Hub* et cliquez sur l'onglet *Models* : https://huggingface.co/models. Cela va faire apparaître tous les modèles sur le *Hub* :

     
 

Vous remarquerez sur le côté gauche que nous avons une sélection d'onglets que nous pouvons sélectionner pour filtrer les modèles par tâche, bibliothèque, jeu de données, etc. Faites défiler vers le bas et sélectionnez la tâche *Audio Classification* dans la liste des tâches audio :

     
 

Nous sommes maintenant en présence d'un sous-ensemble de plus de 500 modèles de classification audio sur le *Hub*. Pour affiner cette sélection, nous pouvons filtrer les modèles par jeu de données. Cliquez sur l'onglet *Datasets* et dans la barre de recherche, tapez *speech_commands*. Vous pouvez cliquer sur ce bouton pour filtrer tous les modèles de classification audio vers ceux qui ont été *finetuné* sur le jeu de données Speech Commands :

     
 

Bien , nous constatons que nous disposons de six modèles pré-entraînés pour ce jeu de données et cette tâche spécifiques (bien que de nouveaux modèles puissent être ajoutés si vous lisez à une date ultérieure !) Vous reconnaîtrez le premier de ces modèles comme le [*Spectrogram Transformer*](https://huggingface.co/MIT/ast-finetuned-speech-commands-v2) que nous avons utilisé dans l'exemple de l'unité 4. Nous utiliserons à nouveau ce *checkpoint* pour notre tâche de détection de mots déclencheur.

Chargeons le *checkpoint* à l'aide de la classe `pipeline` :

```python
from transformers import pipeline
import torch

device = "cuda:0" if torch.cuda.is_available() else "cpu"

classifier = pipeline(
    "audio-classification", model="MIT/ast-finetuned-speech-commands-v2", device=device
)
```

Nous pouvons vérifier sur quelles étiquettes le modèle a été entraîné en vérifiant l'attribut `id2label` dans la configuration du modèle :

```python
classifier.model.config.id2label
```

Nous voyons que le modèle a été entraîné sur 35 étiquettes de classe, y compris quelques mots déclencheurs simples que nous avons décrits ci-dessus, ainsi que quelques objets particuliers comme `bed`, `house` et `cat`. Nous voyons qu'il y a un nom dans ces étiquettes de classe : id 27 correspond à l'étiquette **`marvin`** :

```python
classifier.model.config.id2label[27]
```

```
'marvin'
```

Parfait ! Nous pouvons utiliser ce nom comme mot délchencheur de notre assistant vocal, de la même manière qu'on utilise "Alexa" pour l'Alexa d'Amazon, ou "Hey Siri" pour le Siri d'Apple. Parmi toutes les étiquettes possibles, si le modèle prédit "marvin" avec la probabilité de classe la plus élevée, nous pouvons être sûrs que le mot de réveil que nous avons choisi a été prononcé. 

Nous devons maintenant définir une fonction qui écoute en permanence le microphone de notre appareil et qui transmet continuellement l'audio au modèle de classification pour inférence. Pour ce faire, nous allons utiliser une fonction d'aide pratique fournie avec 🤗 *Transformers* appelée [`ffmpeg_microphone_live`](https://github.com/huggingface/transformers/blob/fb78769b9c053876ed7ae152ee995b0439a4462a/src/transformers/pipelines/audio_utils.py#L98).

Cette fonction transmet de petits morceaux d'audio d'une longueur spécifiée `chunk_length_s` au classifieur. Pour s'assurer que nous obtenons des frontières lisses entre les morceaux d'audio, nous lançons une fenêtre coulissante à travers notre audio avec un pas de `chunk_length_s / 6`. 
Pour que nous n'ayons pas à attendre que tout le premier morceau soit enregistré avant de commencer l'inférence, nous définissons également une longueur d'entrée audio temporaire minimale `stream_chunk_s` qui est transmise au modèle avant que le temps `chunk_length_s` ne soit atteint.

La fonction `ffmpeg_microphone_live` renvoie un objet *generator*, produisant une séquence de morceaux audio qui peuvent chacun être transmis au modèle de classification pour faire une prédiction. Nous pouvons passer ce générateur directement au `pipeline`, qui à son tour retourne une séquence de prédictions de sortie, une pour chaque morceau d'entrée audio. Nous pouvons inspecter les probabilités des classes pour chaque morceau d'audio, et arrêter notre boucle de détection de mot de réveil lorsque nous détectons que le mot de réveil a été prononcé.

Nous utiliserons un critère très simple pour déterminer si notre mot de réveil a été prononcé : si l'étiquette de classe ayant la probabilité la plus élevée est celle de notre mot, et que cette probabilité dépasse un seuil `prob_threshold`, nous déclarons que le mot déclencheur a été prononcé. L'utilisation d'un seuil de probabilité pour contrôler notre classifieur garantit que le mot déclencheur  n'est pas prédit par erreur si l'entrée audio est un bruit, ce qui est typiquement le cas lorsque le modèle est très incertain et que toutes les probabilités d'étiquettes de classe sont faibles. Vous voudrez peut-être ajuster ce seuil de probabilité ou explorer des moyens plus sophistiqués par le biais d'une métrique basée sur l'[*entropie*](https://fr.wikipedia.org/wiki/Entropie_de_Shannon).

```python
from transformers.pipelines.audio_utils import ffmpeg_microphone_live

def launch_fn(
    wake_word="marvin",
    prob_threshold=0.5,
    chunk_length_s=2.0,
    stream_chunk_s=0.25,
    debug=False,
):
    if wake_word not in classifier.model.config.label2id.keys():
        raise ValueError(
            f"Wake word {wake_word} not in set of valid class labels, pick a wake word in the set {classifier.model.config.label2id.keys()}."
        )

    sampling_rate = classifier.feature_extractor.sampling_rate

    mic = ffmpeg_microphone_live(
        sampling_rate=sampling_rate,
        chunk_length_s=chunk_length_s,
        stream_chunk_s=stream_chunk_s,
    )

    print("Listening for wake word...")
    for prediction in classifier(mic):
        prediction = prediction[0]
        if debug:
            print(prediction)
        if prediction["label"] == wake_word:
            if prediction["score"] > prob_threshold:
                return True
```

Essayons cette fonction pour voir comment elle fonctionne ! Nous allons mettre `debug=True` pour afficher la prédiction pour chaque morceau d'audio. Laissons le modèle fonctionner pendant quelques secondes pour voir le type de prédictions qu'il fait lorsqu'il n'y a pas de parole, puis prononçons clairement le mot de réveil *marvin* et regardons sa prédiction monter en flèche à près de 1 :

```python
launch_fn(debug=True)
```

```text
Listening for wake word...
{'score': 0.055326107889413834, 'label': 'one'}
{'score': 0.05999856814742088, 'label': 'off'}
{'score': 0.1282748430967331, 'label': 'five'}
{'score': 0.07310110330581665, 'label': 'follow'}
{'score': 0.06634809821844101, 'label': 'follow'}
{'score': 0.05992642417550087, 'label': 'tree'}
{'score': 0.05992642417550087, 'label': 'tree'}
{'score': 0.999913215637207, 'label': 'marvin'}
```

Génial ! Comme nous nous y attendions, le modèle génère des prédictions erronées pendant les premières secondes. Il n'y a pas d'entrée vocale, donc le modèle fait des prédictions presque aléatoires, mais avec une très faible probabilité. Dès que nous prononçons le mot de réveil, le modèle prédit *marvin* avec une probabilité proche de 1 et termine la boucle, signalant que le mot de réveil a été détecté et que le système ASR doit être activé !

## Transcription de la parole

Une fois de plus, nous utiliserons le modèle Whisper pour notre système de transcription de la parole. Plus précisément, nous chargerons le *checkpoint* [*Whisper Base English*](https://huggingface.co/openai/whisper-base.en), car il est suffisamment petit pour donner une bonne vitesse d'inférence avec une précision de transcription raisonnable. Nous utiliserons une astuce pour obtenir une transcription presque en temps réel en étant astucieux sur la façon dont nous transmettons nos entrées audio au modèle. Comme auparavant, vous pouvez utiliser n'importe quel modèle de reconnaissance vocale sur le [*Hub*](https://huggingface.co/models?pipeline_tag=automatic-speech-recognition&library=transformers&sort=trending), y compris Wav2Vec2, MMS ASR ou d'autres tailles de Whisper :

```python
transcriber = pipeline(
    "automatic-speech-recognition", model="openai/whisper-base.en", device=device
)
```

    Si vous utilisez un GPU, vous pouvez augmenter la taille du modèle à utiliser, ce qui permettra d'obtenir une meilleure précision de transcription tout en respectant le seuil de latence requis. Il suffit de remplacer l'identifiant du modèle par : "openai/whisper-small.en".

Nous pouvons maintenant définir une fonction pour enregistrer l'entrée de notre microphone et transcrire le texte correspondant. Avec la fonction d'aide `ffmpeg_microphone_live`, nous pouvons contrôler le degré de "temps réel" de notre modèle de reconnaissance vocale. L'utilisation d'un `stream_chunk_s` plus petit se prête à une reconnaissance vocale davantage en temps réel, puisque nous divisons notre audio d'entrée en plus petits morceaux et que nous les transcrivons à la volée. Cependant, cela se fait au détriment de la précision, puisqu'il y a moins de contexte pour le modèle à déduire. 

Lors de la transcription de la parole, nous devons également avoir une idée du moment où l'utilisateur **s'arrête** de parler, afin de pouvoir mettre fin à l'enregistrement. Pour des raisons de simplicité, nous mettrons fin à l'enregistrement après le premier `chunk_length_s` (qui est fixé à 5 secondes par défaut), mais vous pouvez essayer d'utiliser un modèle de [détection de l'activité vocale (VAD pour *voice activity detection*)](https://huggingface.co/models?pipeline_tag=voice-activity-detection&sort=trending) pour prédire quand l'utilisateur s'est arrêté de parler.

```python
import sys

def transcribe(chunk_length_s=5.0, stream_chunk_s=1.0):
    sampling_rate = transcriber.feature_extractor.sampling_rate

    mic = ffmpeg_microphone_live(
        sampling_rate=sampling_rate,
        chunk_length_s=chunk_length_s,
        stream_chunk_s=stream_chunk_s,
    )

    print("Start speaking...")
    for item in transcriber(mic, generate_kwargs={"max_new_tokens": 128}):
        sys.stdout.write("\033[K")
        print(item["text"], end="\r")
        if not item["partial"][0]:
            break

    return item["text"]
```

Essayons et voyons comment nous nous débrouillerons ! Une fois que le microphone est activé, commencez à parler et regardez votre transcription apparaître en semi-temps réel :

```python
transcribe()
```

```text
Start speaking...
 Hey, this is a test with the whisper model.
```

Bien, vous pouvez ajuster la longueur maximale de l'audio `chunk_length_s` en fonction de la rapidité ou de la lenteur avec laquelle vous parlez (augmentez-la si vous avez l'impression de ne pas avoir assez de temps pour parler, diminuez-la si vous êtes resté dans l'expectative à la fin), et le `stream_chunk_s` pour le facteur temps réel. Il suffit de passer ces arguments à la fonction `transcribe`.

## Requêter le modèle de langue

Maintenant que notre requête vocale a été transcrite, nous voulons générer une réponse significative. Pour ce faire, nous utiliserons un LLM hébergé sur le *cloud*. Plus précisément, nous choisissons un LLM sur le *Hub* et utilisons l'[API Inference](https://huggingface.co/inference-api) pour interroger facilement le modèle.

Trouvons notre LLM sur le *Hub* en utilisant l'[🤗 *Open LLM Leaderboard*](https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard), un *Space* qui classe les LLM par performance sur quatre tâches de génération. Nous effectuerons une recherche par "instruct" pour filtrer les modèles qui ont été *finetuné* car devraient mieux fonctionner pour notre tâche de requêtage :

     
 

Nous utiliserons le *checkpoint* [tiiuae/falcon-7b-instruct](https://huggingface.co/tiiuae/falcon-7b-instruct) par [TII](https://www.tii.ae/), un *transformer* décodeur de paramètres 7B *finetuné* sur un mélange de jeux de données de chat et d'instructions. Vous pouvez utiliser n'importe quel LLM du *Hub* ayant l'"*Hosted inference API*" activé. Il suffit de regarder le widget sur le côté droit de la carte du modèle :

     
 

L'API Inference nous permet d'envoyer une requête HTTP depuis notre machine locale vers le LLM hébergé sur le *Hub*, et renvoie la réponse sous la forme d'un fichier `json`. Tout ce que nous devons fournir est notre *token* d'authentification au *Hub* et l'identifiant du modèle du LLM que nous souhaitons interroger :

```python
from huggingface_hub import HfFolder
import requests

def query(text, model_id="tiiuae/falcon-7b-instruct"):
    api_url = f"https://api-inference.huggingface.co/models/{model_id}"
    headers = {"Authorization": f"Bearer {HfFolder().get_token()}"}
    payload = {"inputs": text}

    print(f"Querying...: {text}")
    response = requests.post(api_url, headers=headers, json=payload)
    return response.json()[0]["generated_text"][len(text) + 1 :]
```

Essayons-le avec une entrée de test !

```python
query("What does Hugging Face do?")
```

```
'Hugging Face is a company that provides natural language processing and machine learning tools for developers. They'
```

Vous remarquerez à quel point l'inférence est rapide en utilisant l'API Inference. Nous n'avons qu'à envoyer un petit nombre de *tokens* de texte de notre machine locale au modèle hébergé, le coût de communication est donc très faible. Le LLM est hébergé sur des GPU, de sorte que l'inférence s'exécute très rapidement. Enfin, la réponse générée est transférée du modèle à notre machine locale, toujours avec un faible coût de communication.

## Synthétiser la parole

Et maintenant, nous sommes prêts à obtenir la sortie vocale finale ! Une fois de plus, nous utiliserons le modèle [SpeechT5 TTS](https://huggingface.co/microsoft/speecht5_tts) de Microsoft mais vous pouvez utiliser n'importe quel modèle TTS de votre choix. Chargeons le processeur et le modèle :

```python
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech, SpeechT5HifiGan

processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")

model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts").to(device)
vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan").to(device)
```

Et aussi l'enchâssement des locuteurs :

```python
from datasets import load_dataset

embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")
speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0)
```

Nous allons réutiliser la fonction `synthesise` que nous avons définie dans le chapitre [précédent](speech-to-speech) :

```python
def synthesise(text):
    inputs = processor(text=text, return_tensors="pt")
    speech = model.generate_speech(
        inputs["input_ids"].to(device), speaker_embeddings.to(device), vocoder=vocoder
    )
    return speech.cpu()
```

Vérifions rapidement que cela fonctionne comme prévu :

```python
from IPython.display import Audio

audio = synthesise(
    "Hugging Face is a company that provides natural language processing and machine learning tools for developers."
)

Audio(audio, rate=16000)
```

Joli travail 👍

## Marvin 🤖

Maintenant que nous avons défini une fonction pour chacune des quatre étapes du pipeline de l'assistant vocal, il ne reste plus qu'à les assembler pour obtenir notre assistant vocal de bout en bout. Nous allons simplement concaténer les quatre étapes, en commençant par la détection du mot de réveil (`launch_fn`), la transcription de la parole, le requêtage du LLM, et enfin la synthèse de la parole.

```python
launch_fn()
transcription = transcribe()
response = query(transcription)
audio = synthesise(response)

Audio(audio, rate=16000, autoplay=True)
```

Essayez-le avec quelques demandes ! Voici quelques exemples pour vous aider à démarrer :
* *Quel est le pays le plus chaud du monde ?
* *Comment fonctionnent les *transformers* ?
* *Connais-tu l'espagnol ?

Et avec cela, nous avons notre assistant vocal complet, réalisé à l'aide des outils audio que vous avez appris tout au long de ce cours, avec une pincée de magie LLM à la fin. Il y a plusieurs extensions que nous pourrions faire pour améliorer l'assistant vocal. Tout d'abord, le modèle de classification audio classifie 35 étiquettes différentes. Nous pourrions utiliser un modèle de classification binaire plus petit et plus léger qui prédit uniquement si le mot de réveil a été prononcé ou non. Deuxièmement, nous préchargeons tous les modèles à l'avance et les laissons tourner sur notre appareil. Si nous voulions économiser de l'énergie, nous ne chargerions chaque modèle qu'au moment où il est nécessaire, et nous le déchargerions par la suite. Troisièmement, il manque un modèle de détection de l'activité vocale dans notre fonction de transcription, qui transcrit pendant une durée fixe, parfois trop longue, parfois trop courte.

## Généralisation 🪄

Jusqu'à présent, nous avons vu comment générer des sorties vocales avec notre assistant vocal Marvin. Pour terminer, nous allons montrer comment nous pouvons généraliser ces sorties vocales au texte, à l'audio et à l'image.

Nous utiliserons [*Transformers Agents*](https://huggingface.co/docs/transformers/transformers_agents) pour créer notre assistant.
*Transformers Agents* fournit une API de langage naturel au-dessus des bibliothèques 🤗 *Transformers* et *Diffusers*, interprétant une entrée de langage naturel en utilisant un LLM avec des prompts soigneusement conçus, et en utilisant un ensemble d'outils pour fournir des sorties multimodales.

Allons-y et instançons un agent. Il y a [trois LLM disponibles](https://huggingface.co/docs/transformers/transformers_agents#quickstart) pour *Transformers Agents*, dont deux sont open-source et gratuits sur le *Hub*. Le troisième est un modèle d'OpenAI qui nécessite une clé API OpenAI. Nous utiliserons le modèle gratuit [Bigcode Starcoder](https://huggingface.co/bigcode/starcoder) dans cet exemple, mais vous pouvez également essayer l'un ou l'autre des autres LLM disponibles :

```python
from transformers import HfAgent

agent = HfAgent(
    url_endpoint="https://api-inference.huggingface.co/models/bigcode/starcoder"
)
```

Pour utiliser l'agent, il suffit d'appeler `agent.run` avec notre prompt de texte. A titre d'exemple, nous allons lui faire générer une image d'un chat 🐈 (qui, espérons-le, ait l'air un peu mieux que cet emoji) :

```python
agent.run("Generate an image of a cat")
```

     
 

    Notez que la première fois que vous appelez cette fonction, les poids du modèle sont téléchargés, ce qui peut prendre un certain temps en fonction de votre connexion internet.

C'est aussi simple que cela ! L'agent a interprété notre prompt et a utilisé [Stable Diffusion](https://huggingface.co/docs/diffusers/using-diffusers/conditional_image_generation) pour générer l'image, sans que nous ayons à nous soucier du chargement du modèle, de l'écriture de la fonction ou de l'exécution du code.

Nous pouvons maintenant remplacer notre fonction de requête LLM et l'étape de synthèse de texte par notre *Transformers Agent* dans notre assistant vocal, puisque l'Agent va s'occuper de ces deux étapes pour nous :

```python
launch_fn()
transcription = transcribe()
agent.run(transcription)
```

Essayez de prononcer le même prompt "Générer une image d'un chat" (en anglais "Generate an image of a cat") et voyez comment le système s'en sort. Si vous posez à l'agent une simple requête de type question/réponse, l'agent répondra par un texte. Vous pouvez l'encourager à générer des sorties multimodales en lui demandant de renvoyer une image ou de la parole. Par exemple, vous pouvez lui demander de générer une image d'un chat, la légender et prononcer la légende ("Generate an image of a cat, caption it, and speak the caption").

Bien que l'agent soit plus flexible que notre première itération de l'assistant Marvin 🤖, cette généralisation peut conduire à des performances inférieures sur les requêtes standard de l'assistant vocal. Pour récupérer des performances, vous pouvez essayer d'utiliser un LLM plus performant, comme celui d'OpenAI, ou définir un ensemble d'[outils personnalisés](https://huggingface.co/docs/transformers/transformers_agents#custom-tools) spécifiques à la tâche d'assistant vocal.

### Lectures et ressources complémentaires
https://huggingface.co/learn/audio-course/fr/chapter7/supplemental_reading.md

# Lectures et ressources complémentaires

Cette unité a rassemblé de nombreux éléments des unités précédentes, en introduisant les tâches de traduction vocale (audio à audio), les assistants vocaux et séparation des locuteurs. 
Le matériel de lecture supplémentaire est donc divisé en ces trois nouvelles tâches :

Traduction vocale (audio à audio) :
* [STST avec unités discrètes](https://ai.facebook.com/blog/advancing-direct-speech-to-speech-modeling-with-discrete-units/) par Meta AI : une approche directe de la STST par le biais de modèles encodeur-décodeur.
* [Hokkien direct speech-to-speech translation](https://ai.facebook.com/blog/ai-translation-hokkien/) par Meta AI : une approche directe de STST en utilisant des modèles encodeur-décodeur avec un décodeur en deux étapes.
* [Leveraging unsupervised and weakly-supervised data to improve direct STST](https://arxiv.org/abs/2203.13339) par Google : propose de nouvelles approches pour tirer parti des données non supervisées et faiblement supervisées pour entraîner les modèles STST directs et une petite modification de l'architecture du *transformer*.
* [Translatotron-2](https://google-research.github.io/lingvo-lab/translatotron2/) par Google : un système capable de conserver les caractéristiques du locuteur dans la traduction de parole.

Assistant vocal :
* [Accurate wakeword detection](https://www.amazon.science/publications/accurate-detection-of-wake-word-start-and-end-using-a-cnn) par Amazon : une approche à faible latence pour la détection des mots déclencheur pour les applications sur appareil.
* [Architecture RNN-Transducteur](https://arxiv.org/pdf/1811.06621.pdf) par Google : une modification de l'architecture CTC pour l'ASR en *streaming* sur appareil.

Transcriptions de réunions :
* [pyannote.audio Technical Report](https://huggingface.co/pyannote/speaker-diarization/blob/main/technical_report_2.1.pdf) par Hervé Bredin : ce rapport décrit les principes fondamentaux du pipeline de séparation des locuteurs `pyannote.audio`.
* [Whisper X](https://arxiv.org/pdf/2303.00747.pdf) par Max Bain et al. : une approche supérieure pour calculer les horodatages au niveau des mots en utilisant le modèle Whisper.

### Architectures Seq2Seq
https://huggingface.co/learn/audio-course/fr/chapter3/seq2seq.md

# Architectures Seq2Seq

Les modèles avec CTC abordés dans la section précédente utilisent uniquement la partie encodeur du *transformer*. Lorsque nous ajoutons également le décodeur pour créer un modèle encodeur-décodeur, on parle alors de modèle **séquence à séquence** ou seq2seq en abrégé. Le modèle essocie une séquence d'un type de données à une séquence d'un autre type de données.
Avec les *transformers* encodeur, l’encodeur fait une prédiction pour chaque élément de la séquence d'entrée. Par conséquent, les séquences d'entrée et de sortie auront toujours la même longueur. Dans le cas de modèles avec CTC tels que Wav2Vec2, la forme d'onde d'entrée est d'abord sous-échantillonnée, mais il y a toujours une prédiction pour chaque 20 ms d'audio.
Avec un modèle seq2seq, il n'y a pas une telle correspondance un-à-un et les séquences d'entrée et de sortie peuvent avoir des longueurs différentes. Cela rend les modèles seq2seq adaptés aux tâches de NLP telles que le résumé de texte ou la traduction entre différentes langues, mais aussi aux tâches audio telles que la reconnaissance vocale.
L'architecture d'un décodeur est très similaire à celle d'un encodeur, et les deux utilisent des couches similaires avec l'auto-attention comme caractéristique principale. Toutefois, le décodeur effectue une tâche différente de celle de l'encodeur. Pour voir comment cela fonctionne, examinons comment un modèle seq2seq peut effectuer une reconnaissance automatique de la parole.

## Reconnaissance automatique de la parole

L'architecture de **Whisper** est la suivante (figure provenant du blog d’[OpenAI](https://openai.com/blog/whisper/)) :

    

Cela devrait vous sembler assez familier. Sur la gauche se trouve l’**encodeur du *transformer***. Il prend comme entrée un spectrogramme log-mel et encode ce spectrogramme pour former une séquence d'états cachés de l’encodeur qui extraient des caractéristiques importantes de la parole. Ce tenseur à états cachés représente la séquence d'entrée dans son ensemble et code efficacement le « sens » du discours d'entrée.

💡 Il est courant que ces modèles seq2seq utilisent des spectrogrammes comme entrée. Cependant, un modèle seq2seq peut également être conçu pour fonctionner directement sur les formes d'onde audio.

La sortie de l’encodeur est ensuite passée dans le **décodeur du *transformer***, illustré à droite, à l'aide d'un mécanisme d’**attention croisée**. C'est comme l'auto-attention, mais assiste la sortie de l'encodeur. À partir de ce moment, l'encodeur n'est plus nécessaire.
Le décodeur prédit une séquence de *tokens* de texte de manière **autorégressive**, un seul *token* à la fois, à partir d'une séquence initiale qui contient juste un *token* « start » (`SOT` dans le cas de Whisper). À chaque pas de temps suivant, la séquence de sortie précédente est réintroduite dans le décodeur en tant que nouvelle séquence d'entrée. De cette manière, le décodeur émet un nouveau *token* à la fois, augmentant régulièrement la séquence de sortie, jusqu'à ce qu'il prédise qu'un *token* de fin ou un nombre maximum de pas de temps est atteint.
Alors que l'architecture du décodeur est en grande partie identique à celle de l'encodeur, il existe deux grandes différences:
1. Le décodeur a un mécanisme d'attention croisée qui lui permet de regarder la représentation de l'encodeur de la séquence d'entrée
2. L'attention du décodeur est causale : le décodeur n'est pas autorisé à regarder vers l'avenir.
Dans cette conception, le décodeur joue le rôle d'un **modèle de langage**, traitant les représentations à l'état caché de l'encodeur et générant les transcriptions de texte correspondantes. Il s'agit d'une approche plus puissante que la CTC (même si la CTC est combinée avec un modèle de langage externe), car le système seq2seq peut être entraîné de bout en bout avec les mêmes données d'apprentissage et la même fonction de perte, offrant une plus grande flexibilité et des performances généralement supérieures.

💡 Alors qu'un modèle avec CTC produit une séquence de caractères individuels, les *tokens* prédits par Whisper sont des mots complets ou des portions de mots. Il utilise le tokenizer de GPT-2 et dispose d’environ 50 000 *tokens* uniques. Un modèle seq2seq peut donc produire une séquence beaucoup plus courte qu'un modèle CTC pour la même transcription.

Une fonction de perte typique pour un modèle d’ASR seq2seq est la perte d'entropie croisée car la dernière couche du modèle prédit une distribution de probabilité sur les *tokens* possibles. Ceci est généralement combiné avec des techniques telles que [recherche en faisceau pour générer la séquence finale](https://huggingface.co/blog/how-to-generate). La métrique de la reconnaissance vocale est le WER (*word error rate*) ou taux d'erreur de mots, qui mesure le nombre de substitutions, d'insertions et de suppressions nécessaires pour transformer le texte prédit en texte cible. Moins il y en a, meilleur est le score.

## Synthèse vocale

Cela ne vous surprendra peut-être pas : un modèle seq2seq pour la synthèse vocale fonctionne essentiellement de la même manière que décrit ci-dessus, mais avec les entrées et les sorties inversées ! L'encodeur du *transformer* prend une séquence de *tokens* de texte et extrait une séquence d'états masqués qui représentent le texte d'entrée. Le décodeur du *transformer* applique une attention croisée à la sortie de l’encodeur et prédit un spectrogramme.

💡 Rappelons qu'un spectrogramme est fabriqué en prenant le spectre de fréquences de tranches de temps successives d'une forme d'onde audio et en les empilant ensemble. En d'autres termes, un spectrogramme est une séquence où les éléments sont des spectres de fréquence (log-mel), un pour chaque pas de temps.

Avec le modèle d’ASR, le décodeur a été démarré à l'aide d'une séquence qui contient simplement le *token* spécial « start ». Pour le modèle de synthèse vocale, on peut commencer le décodage avec un spectrogramme de longueur 1 et rempli de 0 qui agit comme le « *token* de départ ». Compte tenu de ce spectrogramme initial et des attentions croisées sur les représentations à l'état caché de l’encodeur, le décodeur prédit ensuite la prochaine tranche de temps pour ce spectrogramme, augmentant régulièrement le spectrogramme un pas de temps à la fois.

    

Mais comment le décodeur sait-il quand s'arrêter ? Dans le modèle **SpeechT5**, cela est géré en faisant prédire au décodeur une deuxième séquence. Il contient la probabilité que le pas de temps actuel soit le dernier. Lors de la génération audio au moment de l'inférence, si cette probabilité dépasse un certain seuil (disons 0,5), le décodeur indique que le spectrogramme est terminé et que la boucle de génération doit se terminer.
Une fois le décodage terminé et que nous avons une séquence de sortie contenant le spectrogramme, SpeechT5 utilise un **post-net** qui est composé de plusieurs couches de convolution pour affiner le spectrogramme.
Lors de l'entraînement du modèle de synthèse vocale, les cibles sont aussi des spectrogrammes et la perte est la L1 ou la MSE. Au moment de l'inférence, nous voulons convertir le spectrogramme de sortie en une forme d'onde audio afin que nous puissions réellement l'écouter. Pour cela, un modèle externe est utilisé, le **vocodeur**. Ce vocodeur ne fait pas partie de l'architecture seq2seq et est entraîné séparément.
Ce qui rend la synthèse vocale difficile, est qu'il s'agit d'une association un-à-plusieurs. Avec la reconnaissance de la parole, il n'y a qu'un seul texte de sortie correct correspondant au discours d'entrée, mais avec la synthèse vocale, le texte d'entrée peut être associé à de nombreux sons possibles. Différents orateurs peuvent choisir de mettre l'accent sur différentes parties de la phrase, par exemple. Cela rend les modèles de synthèse vocale difficiles à évaluer. Pour cette raison, la valeur de perte L1 ou MSE n'est pas vraiment significative : il existe plusieurs façons de représenter le même texte dans un spectrogramme. C'est pourquoi les modèles TTS sont généralement évalués par des auditeurs humains, en utilisant une métrique connue sous le nom de MOS (*mean opinion score*) ou score d'opinion moyen.

## Conclusion

L'approche seq2seq est plus puissante qu'un modèle d'encodeur. En séparant l'encodage de la séquence d'entrée du décodage de la séquence de sortie, l'alignement de l'audio et du texte est moins problématique.  Le modèle apprend à effectuer cet alignement grâce au mécanisme d'attention.
Cependant, un modèle encodeur-décodeur est également plus lent car le processus de décodage se produit une étape à la fois, plutôt que tout à la fois. Plus la séquence est longue, plus la prédiction est lente. Les modèles autorégressifs peuvent également rester bloqués dans des répétitions ou sauter des mots. Des techniques telles que la recherche en faisceau peuvent aider à améliorer la qualité des prédictions, mais aussi ralentir encore plus le décodage.

### Unité 3 : Architectures de transformers pour l'audio
https://huggingface.co/learn/audio-course/fr/chapter3/introduction.md

# Unité 3 : Architectures de transformers pour l'audio

Dans ce cours, nous examinons principalement les *transformers* et comment ils peuvent être appliqués aux tâches audio. Bien que vous n'ayez pas besoin de connaître les détails internes de ces modèles, il est utile de comprendre les principaux concepts qui les font fonctionner. Nous faisons donc ici un rappel rapide. Pour une plongée profonde dans les *transformers*, consultez notre [cours de NLP](https://huggingface.co/learn/nlp-course/fr/chapter1/1).

## Comment fonctionne un transformer ?

Le *transformer* original a été conçu pour traduire du texte écrit d'une langue à une autre. Son architecture ressemble à ceci :

    

À gauche se trouve l’**encodeur** et à droite le **décodeur**.

- L'encodeur reçoit une entrée, dans ce cas une séquence de *tokens* de texte, et construit une représentation de celle-ci (ses caractéristiques). Cette partie du modèle est entraînée pour acquérir une compréhension à partir de l'entrée.
- Le décodeur utilise la représentation de l'encodeur (les caractéristiques) ainsi que d'autres entrées (les *tokens* prédits précédemment) pour générer une séquence cible. Cette partie du modèle est entraînée pour générer des extrants. Dans la conception originale, la séquence de sortie se composait de *tokens* de texte.
Il existe également des modèles basés sur des *transformers* n'utilisant que la partie encodeur (bon pour les tâches qui nécessitent une compréhension de l'entrée, comme la classification), ou uniquement la partie décodeur (bon pour les tâches telles que la génération de texte). Un exemple de modèle d'encodeur seul est BERT ; un exemple de modèle de décodeur seul est GPT2.
Une caractéristique clé des *transformers* est qu'ils sont construits avec des couches spéciales appelées **couches d'attention**. Ces couches indiquent au modèle d'accorder une attention particulière à certains éléments de la séquence d'entrée et d'en ignorer d'autres lors du calcul des représentations d'entités.

## Utilisation de *transformers* pour l'audio

Les modèles audio que nous aborderons dans ce cours ont généralement un *transformer* standard comme indiqué ci-dessus, mais avec une légère modification du côté de l'entrée ou de la sortie pour gérer des données audio au lieu de texte. Puisque tous ces modèles sont des *transformers* dans l'âme, ils ont pour la plupart une architecture commune et les principales différences sont dans la façon dont ils sont entraînés et utilisés.

    

Pour les tâches audio, les séquences d'entrée et/ou de sortie sont de l’audio au lieu de texte :
- Reconnaissance automatique de la parole (ASR pour *Automatic speech recognition*) : l'entrée est la parole, la sortie est du texte.
- Synthèse vocale (TTS pour *Text-to-speech*) : l'entrée est du texte, la sortie est de la parole.
- Classification audio : l'entrée est de l’audio, la sortie est une probabilité de classe (une pour chaque élément de la séquence ou une probabilité de classe unique pour la séquence entière).
- Conversion vocale ou amélioration de la parole : l'entrée et la sortie sont de l’audio.

Il existe différentes façons de gérer l'audio afin qu'il puisse être utilisé via un *transformer*. La principale considération est de savoir s'il faut utiliser l'audio dans sa forme brute (comme une forme d'onde) ou le traiter comme un spectrogramme à la place.

## Entrées du modèle

L'entrée d'un modèle audio peut être du texte ou du son. L'objectif est de convertir cette entrée en un enchâssement pouvant être traité par le *transformer*.

### Entrée textuelle

Un modèle de synthèse vocale prend du texte comme entrée. Cela fonctionne comme le *transformer* d'origine en NLP : le texte d'entrée est d'abord tokenisé, ce qui donne une séquence de *tokens* de texte. Cette séquence est envoyée via une couche d’enchâssement d'entrée pour convertir les *tokens* en vecteurs de 512 dimensions. Ces enchâssements sont ensuite transmis dans l’encodeur du *transformer*.

### Entrée sous forme de forme d'onde

Un modèle de reconnaissance de la parole automatique prend l'audio comme entrée. Pour pouvoir utiliser un *transformer* pour l’ASR, nous devons d'abord convertir l'audio en une séquence d’enchâssements d'une manière ou d'une autre.
Des modèles tels que **[Wav2Vec2](https://arxiv.org/abs/2006.11477)** et **[HuBERT](https://arxiv.org/abs/2106.07447)** utilisent la forme d'onde audio directement comme entrée du modèle. Comme vous l'avez vu dans [le chapitre sur les données audio (../chapter1/introduction), une forme d'onde est une séquence unidimensionnelle de nombres à virgule flottante, où chaque nombre représente l'amplitude échantillonnée à un moment donné. Cette forme d'onde brute est d'abord normalisée à la moyenne nulle et à la variance unitaire, ce qui permet de normaliser les échantillons audio sur différents volumes (amplitudes).

    

Après la normalisation, la séquence d'échantillons audio est transformée en un enchâssement à l'aide d'un petit réseau neuronal convolutionnel, connu sous le nom d'encodeur de caractéristiques. Chacune des couches convolutives de ce réseau traite la séquence d'entrée, sous-échantillonnant l'audio pour réduire la longueur de la séquence, jusqu'à ce que la couche convolutive finale produise un vecteur à 512 dimensions avec l’enchâssement pour chaque 25 ms d'audio. Une fois que la séquence d'entrée a été transformée en une séquence de tels enchâssements, le *transformer* traitera les données comme d'habitude.

### Entrée sous forme de spectrogramme

Un inconvénient de l'utilisation de la forme d'onde brute comme entrée est qu'elles ont tendance à avoir de longues longueurs de séquence. Par exemple, trente secondes d'audio à une fréquence d'échantillonnage de 16 kHz donnent une entrée de longueur `30 * 16000 = 480000`. Des longueurs de séquence plus longues nécessitent plus de calculs dans le *transformer* et donc une utilisation plus élevée de la mémoire.
Pour cette raison, les formes d'onde audio brutes ne sont généralement pas la forme la plus efficace de représenter une entrée audio. En utilisant un spectrogramme, nous obtenons la même quantité d'informations, mais sous une forme plus comprimée.

    

Des modèles tels que **[Whisper](https://arxiv.org/abs/2212.04356)** convertissent d'abord la forme d'onde en un spectrogramme log-mel. Whisper divise toujours l'audio en segments de 30 secondes, et le spectrogramme log-mel pour chaque segment a la forme ` (80, 3000) ` où 80 est le nombre de bacs mel et 3000 est la longueur de la séquence. En convertissant en spectrogramme log-mel, nous avons réduit la quantité de données d'entrée, mais plus important encore, il s'agit d'une séquence beaucoup plus courte que la forme d'onde brute. Le spectrogramme log-mel est ensuite traité par un petit réseau convolutif en une séquence d'enchâssements, allant ensuite dans le *transformer* comme d'habitude.

Dans les deux cas, l'entrée de la forme d'onde et du spectrogramme, il y a un petit réseau devant le *transformer* convertissant l'entrée en enchâssement, puis le *transformer*prend le relais pour faire son travail.

## Sorties du modèle

L'architecture du *transformer* génère une séquence de vecteurs à états cachés, également appelés enchâssement de sortie. Notre objectif est de transformer ces vecteurs en sortie textuelle ou audio.

### Sortie textuelle

L'objectif d'un modèle d’ASR est de prédire une séquence de *tokens* de texte. Cela se fait en ajoutant une tête de modélisation du langage (généralement une seule couche linéaire) suivie d'une softmax au-dessus de la sortie du *transformer*. On alors prédit les probabilités sur les *tokens* de texte dans le vocabulaire.

### Sortie sous forme de spectrogramme

Pour les modèles qui génèrent de l'audio, tels qu'un modèle de synthèse vocale, nous devons ajouter des couches pouvant produire une séquence audio. Il est très courant de générer un spectrogramme, puis d'utiliser un réseau neuronal supplémentaire, connu sous le nom de vocodeur, pour transformer ce spectrogramme en une forme d'onde.
Par exemple dans le modèle **[SpeechT5](https://arxiv.org/abs/2110.07205)** la sortie du *transformer* est une séquence de vecteurs à 768 éléments. Une couche linéaire projette cette séquence dans un spectrogramme log-mel. Un post-réseau, composé de couches linéaires et convolutives supplémentaires, affine le spectrogramme en réduisant le bruit. Le vocodeur crée alors la forme d'onde audio finale.

    

💡 Si vous prenez une forme d'onde existante et appliquez la transformée de Fourier à court terme (TFCT), il est possible d'effectuer l'opération inverse pour obtenir à nouveau la forme d'onde d'origine. Cela fonctionne parce que le spectrogramme créé par la TFCT contient à la fois des informations d'amplitude et de phase, et les deux sont nécessaires pour reconstruire la forme d'onde. Cependant, les modèles audio qui génèrent leur sortie sous forme de spectrogramme ne prédisent généralement que les informations d'amplitude, pas la phase. Pour transformer un tel spectrogramme en une forme d'onde, nous devons en quelque sorte estimer l'information de phase. C'est ce que fait un vocodeur.

### Sortie sous forme de forme d'onde

Il est également possible pour les modèles de produire directement une forme d'onde au lieu d'un spectrogramme comme étape intermédiaire, mais nous n'avons actuellement aucun modèle dans 🤗 *Transformers* qui le fait.

## Conclusion

En résumé: la plupart des *transformers* audio se ressemblent plus que différents. Ils sont tous construits sur la même architecture et les mêmes couches d'attention, bien que certains modèles n'utilisent que la partie encodeur du *transformer* tandis que d'autres utilisent à la fois l’encodeur et le décodeur.
Vous avez également vu comment obtenir des données audio dans et hors des *transformers*. Pour effectuer les différentes tâches audio d'ASR, TTS, etc., nous pouvons simplement échanger les couches qui prétraitent les entrées en enchâssements, et échanger les couches qui post-traitent les enchâssements prédites en sorties, tandis que le *backbone* du *transformer* reste le même.
Examinons  dans les suite différentes façons dont ces modèles peuvent être entraînés à effectuer une reconnaissance vocale automatique.

### Lectures et ressources supplémentaires
https://huggingface.co/learn/audio-course/fr/chapter3/supplemental_reading.md

# Lectures et ressources supplémentaires

Si vous souhaitez explorer les différentes architectures de transformers et découvrir leurs diverses applications dans le traitement de la parole, consultez ce papier : [Transformers in Speech Processing: A Survey](https://arxiv.org/abs/2303.11607) 
par Siddique Latif, Aun Zaidi, Heriberto Cuayahuitl, Fahad Shamshad, Moazzam Shoukat, Junaid Qadir

"Le succès remarquable des *transformers* dans le domaine du traitement du langage naturel a suscité l'intérêt de la communauté du traitement de la parole, ce qui a conduit à une exploration de leur potentiel pour modéliser les dépendances à longue portée dans les séquences de parole. Récemment, les *transformers* ont gagné en importance dans divers domaines liés à la parole, notamment la reconnaissance automatique de la parole, la synthèse de la parole, la traduction de la parole, la para-linguistique de la parole, l'amélioration de la parole, les systèmes de dialogue parlé et de nombreuses applications multimodales. Dans cet article, nous présentons une étude complète qui vise à faire le lien entre les études de recherche de divers sous-domaines de la technologie de la parole. En consolidant les résultats obtenus dans le domaine des technologies de la parole, nous fournissons une ressource précieuse aux chercheurs désireux d'exploiter la puissance des *transformers* pour faire avancer le domaine. Nous identifions les défis rencontrés par les *transformers* dans le traitement de la parole tout en proposant des solutions potentielles pour résoudre ces problèmes."

### Architectures avec CTC
https://huggingface.co/learn/audio-course/fr/chapter3/ctc.md

# Architectures avec CTC

CTC ou classification temporelle connexionniste est une technique utilisée avec les *transformers* encodeur pour la reconnaissance automatique de la parole. Des exemples de tels modèles sont **Wav2Vec2**, **HuBERT** et **M-CTC-T**.
Un *transformer* encodeur est le type de *transformer* le plus simple car il utilise uniquement la partie encodeur du modèle. L'encodeur lit la séquence d'entrée (la forme d'onde audio) et l’associe dans une séquence d'états cachés, également appelée enchâssement de sortie.
Avec un modèle avec CTC, nous appliquons un association linéaire supplémentaire sur la séquence des états cachés pour obtenir des prédictions d'étiquettes de classe. Les étiquettes de classe sont les **caractères de l'alphabet** (a, b, c, ...). De cette façon, nous sommes en mesure de prédire n'importe quel mot dans la langue cible avec une petite tête de classification, car le vocabulaire ne contient que 26 caractères plus quelques *tokens* spéciaux.

    

Jusqu'à présent, cela est très similaire à ce que nous faisons en NLP avec un modèle tel que BERT : un * transformer* encodeur associe nos *tokens* de texte dans une séquence d'états cachés de l'encodeur, puis nous appliquons une association linéaire pour obtenir une prédiction d'étiquette de classe pour chaque état caché.
Voici le hic : dans la parole, nous ne connaissons pas l'alignement des entrées audio et des sorties de texte. Nous savons que l'ordre dans lequel le discours est prononcé est le même que l'ordre dans lequel le texte est transcrit (l'alignement est dit monotone), mais nous ne savons pas comment les caractères de la transcription s'alignent sur l'audio. C'est là qu'intervient l'algorithme CTC.

💡 Dans les modèles de NLP, le vocabulaire est généralement composé de milliers de *tokens* qui décrivent non seulement des caractères individuels, mais des parties de mots ou même des mots complets. Pour la CTC, un petit vocabulaire fonctionne mieux et nous essayons généralement de le limiter à moins de 50 caractères. Nous ne nous soucions pas de la casse des lettres, donc seulement utiliser des majuscules (ou seulement des minuscules) est suffisant. Les chiffres sont épelés, par exemple « 20 » devient « vingt ». En plus des lettres, nous avons besoin d'au moins un *token* séparateur de mots (espace) et d'un *token* de rembourrage. Tout comme avec un modèle de NLP, le *token* de remplissage nous permet de combiner plusieurs exemples dans un batch, mais c'est aussi le *token* que le modèle prédira pour les silences. En anglais, il est également utile de garder le caractère `'` car `"it's"` et `"its"`ont des significations très différentes.

## Où est mon alignement?

L’ASR consiste à prendre l'audio en entrée et à produire du texte en sortie. Nous avons quelques choix pour prédire le texte:
- comme caractères
- comme phonèmes
- comme mots

Un modèle d’ASR est entraîné sur un ensemble de données composé de paires `(audio, texte)` où le texte est une transcription humaine du fichier audio. En règle générale, le jeu de données n'inclut aucune information de synchronisation indiquant quel mot ou syllabe apparaît où dans le fichier audio. Comme nous ne pouvons pas compter sur les informations de synchronisation pendant l'entraînement, nous n'avons aucune idée de la façon dont les séquences d'entrée et de sortie doivent être alignées.
Supposons que notre entrée soit un fichier audio d'une seconde. Dans **Wav2Vec2**, le modèle sous-échantillonne l'entrée audio à l'aide de l’encodeur ConvNet pour une séquence plus courte d'états cachés, où il y a un vecteur d'état caché pour chaque 20 millisecondes d'audio. Pour une seconde d'audio, nous transmettons ensuite une séquence de 50 états cachés à l’encodeur du *transformer*.  Les segments audio extraits de la séquence d'entrée se chevauchent partiellement, de sorte que même si un vecteur à état caché est émis toutes les 20 ms, chaque état caché représente en fait 25 ms d'audio.
L’encodeur du *transformer* prédit une représentation des caractéristiques pour chacun de ces états cachés, ce qui signifie que nous recevons du *transformer* une séquence de 50 sorties. Chacune de ces sorties a une dimensionnalité de 768. Dans cet exemple, la séquence de sortie de l’encodeur du transformer a donc la forme `(768, 50)`. Comme chacune de ces prédictions couvre 25 ms de temps, ce qui est plus court que la durée d'un phonème, il est logique de prédire des phonèmes ou des caractères individuels, mais pas des mots entiers. La CTC fonctionne mieux avec un petit vocabulaire, nous allons donc prédire les caractères.

    

Pour faire des prédictions de texte, nous associons chacune des sorties d'encodeur à 768 dimensions à nos étiquettes de caractères à l'aide d'une couche linéaire (la « tête CTC »). Le modèle prédit alors un tenseur `(50, 32)` contenant les logits, où 32 est le nombre de *tokens* dans le vocabulaire. Puisque nous faisons une prédiction pour chacune des caractéristiques de la séquence, nous nous retrouvons avec un total de prédictions de 50 caractères pour chaque seconde d'audio.
Cependant, si nous prédisons simplement un caractère toutes les 20 ms, notre séquence de sortie pourrait ressembler à ceci:

```text
BRIIONSAWWSOMEETHINGCLOSETOPANICONHHISOPPONENT'SSFAACEWHENTHEMANNFINALLLYRREECOGGNNIIZEDHHISSERRRRORR ...
``` 

Si vous regardez de plus près, cela ressemble un peu à de l'anglais, mais beaucoup de caractères ont été dupliqués. C'est parce que le modèle doit sortir *quelque chose* pour chaque 20 ms d'audio dans la séquence d'entrée, et si un caractère est étalé sur une période supérieure à 20 ms, il apparaîtra plusieurs fois dans la sortie. Il n'y a aucun moyen d'éviter cela, d'autant plus que nous ne savons pas quel est l’horodatage de la transcription pendant l’entraînement. La CTC est un moyen de filtrer ces doublons.
En réalité, la séquence prédite contient également beaucoup de *tokens* de remplissage lorsque le modèle n'est pas tout à fait sûr de ce que le son représente, ou pour l'espace vide entre les caractères. Nous avons supprimé ces *tokens* de remplissage de l'exemple pour plus de clarté. Le chevauchement partiel entre les segments audio est une autre raison pour laquelle les caractères sont dupliqués dans la sortie.)

## L'algorithme CTC
La clé de l'algorithme CTC est l'utilisation d'un *token* spécial, souvent appelé ***token* blanc**. C'est juste un autre *token* que le modèle prédira et cela fait partie du vocabulaire. Dans cet exemple, le *token* blanc est affiché sous la forme `_`. Ce *token* spécial sert de délimitation entre les groupes de caractères.
Le résultat complet du modèle CTC pourrait ressembler à ce qui suit :

```text
B_R_II_O_N_||_S_AWW_|||||_S_OMEE_TH_ING_||_C_L_O_S_E||TO|_P_A_N_I_C_||_ON||HHI_S||_OP_P_O_N_EN_T_'SS||_F_AA_C_E||_W_H_EN||THE||M_A_NN_||||_F_I_N_AL_LL_Y||||_RREE_C_O_GG_NN_II_Z_ED|||HHISS|||_ER_RRR_ORR||||
```

Le *token* `|` est le caractère séparateur de mots. Dans l'exemple, nous utilisons `|` au lieu d'un espace, ce qui permet de repérer plus facilement où se trouvent les sauts de mots, mais cela sert le même but.
Le caractère blanc de la CTC permet de filtrer les caractères en double. Par exemple, regardons le dernier mot de la séquence prédite, « _ER_RRR_ORR ». Sans le *token* blanc, le mot ressemblait à ceci:

```text
ERRRRORR
``` 

Si nous supprimions simplement les caractères en double, cela deviendrait « EROR ». Ce n'est pas l'orthographe correcte. Mais avec le *token* *blanc* d ela CTC, nous pouvons supprimer les doublons dans chaque groupe, de sorte que:

```text
_ER_RRR_ORR
``` 

devient:

```text
_ER_R_OR
``` 

Et maintenant, nous supprimons le jeton blanc `_` pour avoir le mot final :

```text
ERROR
``` 

Si nous appliquons cette logique à l'ensemble du texte, y compris `|`, et remplaçons les caractères `|` survivants par des espaces, la sortie finale décodée par CTC est la suivante :

```text
BRION SAW SOMETHING CLOSE TO PANIC ON HIS OPPONENT'S FACE WHEN THE MAN FINALLY RECOGNIZED HIS ERROR
``` 

Pour récapituler, le modèle prédit un *token* (caractère) pour chaque 20 ms d'audio (partiellement chevauchant) à partir de la forme d'onde d'entrée. Cela donne beaucoup de doublons. Grâce au *token* blanc de la CTC, nous pouvons facilement supprimer ces doublons sans détruire la bonne l'orthographe des mots. C'est un moyen très simple et pratique de résoudre le problème de l'alignement du texte de sortie avec l'audio d'entrée.

💡 Dans le modèle Wav2Vec2, le *token* blanc est le même que le *token* de remplissage ``. Le modèle prédira beaucoup de ces *tokens* ``, par exemple lorsqu'il n'y a pas de caractère clair à prédire pour les 20 ms actuelles d'audio. L'utilisation du même *token* pour le remplissage que pour les blancs simplifie l'algorithme de décodage et aide à garder le vocabulaire petit.

L'ajout de la CTC à un *transformer* encodeur est facile : la séquence de sortie de l’encodeur va dans une couche linéaire qui projette les caractéristiques acoustiques dans le vocabulaire. Le modèle est entraîné avec une perte de CTC spéciale.
Un inconvénient de la CTC est qu'elle peut produire des mots qui *sonnent* corrects mais ne sont pas *orthographiés* correctement. Après tout, la tête de la CTC ne prend en compte que les caractères individuels, pas les mots complets. Une façon d'améliorer la qualité des transcriptions audio est d'utiliser un modèle de langage externe. Ce modèle de langage agit essentiellement comme un correcteur orthographique au-dessus de la sortie de la CTC.

## Quelle est la différence entre Wav2Vec2, HuBERT, M-CTC-T, etc. ?

Tous les modèles de *transformer* avec CTC ont une architecture très similaire. Ils utilisent l’encodeur du *transformer* (mais pas le décodeur) avec une tête CTC sur le dessus. Du point de vue de l'architecture, ils se ressemblent plus que ne sont différents.
Une différence entre Wav2Vec2 et M-CTC-T est que le premier fonctionne sur des formes d'onde audio brutes tandis que le second utilise des spectrogrammes mel comme entrée. Les modèles ont également été entraînés à des fins différentes. M-CTC-T, par exemple, est entraîné à la reconnaissance vocale multilingue et possède donc une tête CTC relativement grande qui comprend des caractères chinois en plus d'autres alphabets.
Wav2Vec2 & HuBERT utilisent exactement la même architecture mais sont entraînés de manière très différente. Wav2Vec2 est pré-entraîné comme la modélisation du langage masqué de BERT, en prédisant les unités vocales pour les parties masquées de l'audio. HuBERT pousse l'inspiration de BERT un peu plus loin et apprend à prédire les « unités de parole discrètes », qui sont analogues aux *tokens* dans une phrase de texte, de sorte que la parole peut être traitée en utilisant des techniques de NLP établies.
Pour clarifier, les modèles mis en évidence ici ne sont pas les seuls modèles de *transformer* avec CTC. Il y en a beaucoup d'autres, mais maintenant vous savez qu'ils fonctionnent tous de la même manière.

### Architectures de classification d’audio
https://huggingface.co/learn/audio-course/fr/chapter3/classification.md

# Architectures de classification d’audio

L'objectif de la classification d’audio est de prédire une étiquette de classe pour une entrée audio. Le modèle peut prédire une étiquette de classe unique qui couvre toute la séquence d'entrée, ou il peut prédire une étiquette pour chaque trame audio (généralement toutes les 20 millisecondes d'entrée audio), auquel cas la sortie du modèle est une séquence de probabilités d'étiquette de classe. Un exemple du premier cas est la détection des chants des oiseaux. Un exemple du second est la séparation des locuteurs où le modèle prédit quel locuteur parle à un moment donné.

## Classification à l'aide de spectrogrammes

L'un des moyens les plus simples d'effectuer une classification audio est de prétendre qu'il s'agit d'un problème de classification d'image !
Rappelons qu'un spectrogramme est un tenseur bidimensionnel de forme `(frequencies, sequence length)`. Dans le [chapitre sur les données audio](.. /chapter1/audio_data) nous avons tracé ces spectrogrammes sous forme d'images. Devinez quoi ? Nous pouvons littéralement traiter le spectrogramme comme une image et le transmettre à un modèle de classification de type ConvNet standard tel qu’un ResNet ou ConvNext et obtenir de très bonnes prédictions. Même chose avec un modèle de type *transformer* tel que le ViT.
C'est ce que fait **Audio Spectrogram Transformer**. Il utilise le ViT et lui transmet des spectrogrammes en entrée au lieu d'images. Grâce aux couches d'auto-attention du *transformer*, le modèle est mieux en mesure de capturer le contexte global qu'un ConvNet.
Tout comme le ViT, le modèle AST divise le spectrogramme audio en une séquence de patchs d'image partiellement chevauchants de 16×16 pixels. Cette séquence de patchs est ensuite projetée dans une séquence d’enchâssement, et ceux-ci sont donnés à l’encodeur du *transformer* en entrée comme d'habitude. L’AST est un modèle de *transformer* encodeur et la sortie est donc une séquence d'états cachés, un pour chaque patch d'entrée 16×16. En plus de cela, il y a une couche de classification simple avec activation sigmoïde pour associer les états cachés aux probabilités de classification.

    

Image tirée du papier [*AST: Audio Spectrogram Transformer*](https://arxiv.org/pdf/2104.01778.pdf)

💡 Même si ici nous prétendons que les spectrogrammes sont comme les images, il existe des différences importantes. Par exemple, déplacer le contenu d'une image vers le haut ou vers le bas ne change généralement pas la signification de ce qui se trouve dans l'image. Cependant, déplacer un spectrogramme vers le haut ou vers le bas changera les fréquences qui sont dans le son et changera complètement son caractère. Les images sont invariantes sous translation mais les spectrogrammes ne le sont pas. Traiter les spectrogrammes comme des images peut très bien fonctionner dans la pratique, mais gardez à l'esprit que ce n'est pas vraiment la même chose.

## Tout transformer peut être un classifieur

Dans une [section précédente](CTC), vous avez vu que CTC est une technique efficace pour effectuer une reconnaissance automatique de la parole à l'aide d'un *transformer* encodeur.  De tels modèles sont déjà des classifieurs, prédisant les probabilités pour les étiquettes de classe à partir d'un vocabulaire de *tokenizer*. Nous pouvons prendre un modèle avec CTC et le transformer en un classifieur d’audio à usage général en changeant les étiquettes et en l'entraînant avec une fonction de perte d'entropie croisée standard au lieu de la perte CTC spéciale.
Par exemple, 🤗 *Transformers* a un modèle `Wav2Vec2ForCTC` mais aussi `Wav2Vec2ForSequenceClassification` et `Wav2Vec2ForAudioFrameClassification`. Les seules différences entre les architectures de ces modèles sont la taille de la couche de classification et la fonction de perte utilisée.
En fait, n'importe quel *transformer* encodeur audio peut être transformé en classifieur d’audio en ajoutant une couche de classification au-dessus de la séquence d'états cachés. Les classifieurs n'ont généralement pas besoin du décodeur du *transformer*.
Pour prédire un score de classification unique pour l'ensemble de la séquence (`Wav2Vec2ForSequenceClassification`), le modèle prend la moyenne sur les états masqués et l'introduit dans la couche de classification. Le résultat est une distribution de probabilité unique.
Pour créer une classification distincte pour chaque trame audio (`Wav2Vec2ForAudioFrameClassification`), le classifieur est exécuté sur la séquence d'états masqués, et donc la sortie du classifieur est également une séquence.

### Introduction aux données audio
https://huggingface.co/learn/audio-course/fr/chapter1/audio_data.md

# Introduction aux données audio

Le **taux d'échantillonnage** (également appelé fréquence d'échantillonnage) est le nombre d'échantillons prélevés en une seconde et est mesuré en hertz (Hz). 
Pour vous donner un point de référence, l'audio de qualité CD a un taux d'échantillonnage de 44 100 Hz, ce qui signifie que les échantillons sont prélevés 44 100 fois par seconde. À titre de comparaison, l'audio haute résolution a un taux d'échantillonnage de 192 000 Hz ou 192 kHz. 
Un taux d'échantillonnage couramment utilisé dans les modèles vocaux d'apprentissage est de 16 000 Hz ou 16 kHz.  

Le choix de la fréquence d'échantillonnage détermine principalement la fréquence la plus élevée qui peut être capturée à partir du signal. 
Ceci est également connu sous le nom de limite de Nyquist et correspond exactement à la moitié du taux d'échantillonnage. 
Les fréquences audibles dans la parole humaine sont inférieures à 8 kHz et, par conséquent, l'échantillonnage de la parole à 16 kHz est suffisant.
L'utilisation d'un taux d'échantillonnage plus élevé ne permettra pas de capturer plus d'informations et ne fera qu'augmenter le coût de calcul du traitement de ces fichiers. 
D'autre part, l'échantillonnage audio à un taux d'échantillonnage trop faible entraînera une perte d'informations. 
La parole échantillonnée à 8 kHz sonnera étouffée car les fréquences plus élevées ne peuvent pas être capturées à ce rythme.  

Il est important de vous assurer que tous les exemples audio de votre jeu de données ont le même taux d'échantillonnage lorsque vous travaillez sur une tâche audio.
Si vous prévoyez d'utiliser des données audio personnalisées pour finetuner un modèle pré-entraîné, le taux d'échantillonnage de vos données doit correspondre au taux d'échantillonnage des données sur lesquelles le modèle a été pré-entraîné. 
La fréquence d'échantillonnage détermine l'intervalle de temps entre les échantillons audio successifs, ce qui a un impact sur la résolution temporelle des données audio. 
Prenons un exemple : un son de 5 secondes à une fréquence d'échantillonnage de 16 000 Hz sera représenté comme une série de 80 000 valeurs, tandis que le même son de 5 secondes à une fréquence d'échantillonnage de 8 000 Hz sera représenté comme une série de 40 000 valeurs. 
Les *transformers* qui résolvent les tâches audio traitent les exemples comme des séquences et s'appuient sur des mécanismes d'attention pour apprendre l'audio ou la représentation multimodale. 
Étant donné que les séquences sont différentes pour les exemples audio à des taux d'échantillonnage différents, il sera difficile pour les modèles de généraliser entre les taux d'échantillonnage.
**Le rééchantillonnage** est le processus de mise en correspondance des taux d'échantillonnage et fait partie du [prétraitement](preprocessing#resampling-the-audio-data) des données audio.

## Amplitude et profondeur de bits

Bien que le taux d'échantillonnage vous indique à quelle fréquence les échantillons sont prélevés, quelles sont exactement les valeurs de chaque échantillon?
Le son est produit par des changements de pression atmosphérique à des fréquences audibles pour les humains. 
L'**amplitude** d'un son décrit le niveau de pression acoustique à un instant donné et est mesurée en décibels (dB). 
Nous percevons l'amplitude comme un volume sonore. Pour vous donner un exemple, une voix normale est inférieure à 60 dB, et un concert de rock peut être autour de 125 dB, repoussant les limites de l'audition humaine.
En audio, chaque échantillon enregistre l'amplitude de l'onde à un moment donné. 
La **profondeur de bits** de l'échantillon détermine avec quelle précision cette valeur d'amplitude peut être décrite. 
Plus la profondeur de bits est élevée, plus la représentation numérique se rapproche fidèlement de l'onde sonore continue d'origine.
Les profondeurs de bits audio les plus courantes sont 16 bits et 24 bits. 
Chacun est un terme binaire, représentant le nombre d'étapes possibles auxquelles la valeur d'amplitude peut être quantifiée lorsqu'elle est convertie de continue à discrète: 65 536 étapes pour l'audio 16 bits, 16 777 216 étapes pour l'audio 24 bits. 
Étant donné que la quantification implique d'arrondir la valeur continue à une valeur discrète, le processus d'échantillonnage introduit du bruit. Plus la profondeur de bits est élevée, plus ce bruit de quantification est faible. 
En pratique, le bruit de quantification de l'audio 16 bits est déjà suffisamment faible pour être inaudible et l'utilisation de profondeurs de bits plus élevées n'est généralement pas nécessaire.
Vous pouvez également rencontrer de l'audio 32 bits. 
Cela stocke les échantillons sous forme de valeurs à virgule flottante, tandis que l'audio 16 bits et 24 bits utilise des échantillons entiers. 
La précision d'une valeur à virgule flottante de 32 bits est de 24 bits, ce qui lui donne la même profondeur de bits que l'audio 24 bits.
Les échantillons audio en virgule flottante devraient se situer dans la plage [-1.0, 1.0]. 
Étant donné que les modèles d'apprentissage automatique fonctionnent naturellement sur des données en virgule flottante, l'audio doit d'abord être converti au format à virgule flottante avant de pouvoir être utilisé pour entraîner le modèle. 
Nous verrons comment faire cela dans la section suivante sur le [Prétraitement] (preprocessing).
Tout comme pour les signaux audio continus, l'amplitude de l'audio numérique est généralement exprimée en décibels (dB). 
L'audition humaine étant de nature logarithmique - nos oreilles sont plus sensibles aux petites fluctuations des sons calmes qu'à celles des sons forts - l'intensité d'un son est plus facile à interpréter si les amplitudes sont exprimées en décibels, qui sont également logarithmiques.
L'échelle de décibels pour l'audio réel commence à 0 dB, ce qui représente le son le plus faible possible que les humains peuvent entendre, et les sons plus forts ont des valeurs plus importantes. 
Cependant, pour les signaux audio numériques, 0 dB est l'amplitude la plus forte possible, tandis que toutes les autres amplitudes sont négatives. 
En règle générale: chaque -6 dB est une réduction de moitié de l'amplitude, et tout ce qui est inférieur à -60 dB est généralement inaudible à moins que vous n'augmentiez vraiment le volume.

## L'audio comme forme d'onde

Vous avez peut-être vu des sons visualisés sous la **forme d'onde** qui traçant les valeurs de l'échantillon au fil du temps et illustrant les changements d'amplitude du son. Ceci est aussi connu sous le nom de représentation du *domaine temporel* du son.
Ce type de visualisation est utile pour identifier des caractéristiques spécifiques du signal audio telles que la synchronisation des événements sonores individuels, l'intensité sonore globale du signal et toute irrégularité ou bruit présent dans l'audio.

Pour tracer la forme d'onde d'un signal audio, nous pouvons utiliser une bibliothèque Python `librosa`:

```bash
pip install librosa
```

Prenons un exemple de son appelé « trompette » qui vient avec la bibliothèque:

```py
import librosa

array, sampling_rate = librosa.load(librosa.ex("trumpet"))
```

L'exemple est chargé sous la forme d'un tuple de séries temporelles audio (ici nous l'appelons `array`) et de taux d'échantillonnage (`sampling_rate`).
Jetons un coup d'œil à la forme d'onde de ce son en utilisant la fonction `waveshow()` de librosa:

```py
import matplotlib.pyplot as plt
import librosa.display

plt.figure().set_figwidth(12)
librosa.display.waveshow(array, sr=sampling_rate)
```

    

Cela trace l'amplitude du signal sur l'axe des y et le temps le long de l'axe des x. 
En d'autres termes, chaque point correspond à une seule valeur d'échantillon qui a été prise lors de l'échantillonnage de ce son. 
Notez également que librosa renvoie déjà l'audio sous forme de valeurs à virgule flottante et que les valeurs d'amplitude sont effectivement comprises dans la plage [-1.0, 1.0].
Visualiser l'audio et l'écouter peut être un outil utile pour comprendre les données avec lesquelles vous travaillez.
Vous pouvez voir la forme du signal, observer des modèles, apprendre à repérer le bruit ou la distorsion. 
Si vous prétraitez les données d'une manière ou d'une autre, telle que la normalisation, le rééchantillonnage ou le filtrage, vous pouvez confirmer visuellement que les étapes de prétraitement ont été appliquées comme prévu.
Après avoir entraîné un modèle, vous pouvez également visualiser des exemples où des erreurs se produisent (par exemple, dans la tâche de classification audio) pour déboguer le problème.

## Le spectre de fréquences

Une autre façon de visualiser les données audio consiste à tracer le **spectre de fréquences** d'un signal audio, également connu sous le nom de représentation du *domaine fréquentiel*. 
Le spectre est calculé à l'aide de la transformée de Fourier discrète ou TFD. Il décrit les fréquences individuelles qui composent le signal et leur force.
Traçons le spectre de fréquences pour le même son de trompette en prenant la TFD en utilisant la fonction `rfft()` de numpy. Bien qu'il soit possible de tracer le spectre de l'ensemble du son, il est plus utile de regarder une petite région à la place. 
Ici, nous allons prendre la TFD sur les 4096 premiers échantillons, ce qui correspond à peu près à la longueur de la première note jouée:

```py
import numpy as np

TFD_input = array[:4096]

# calculer la TDF
window = np.hanning(len(TFD_input))
windowed_input = TFD_input * window
TFD = np.fft.rfft(windowed_input)

# obtenir le spectre d'amplitude en décibels
amplitude = np.abs(TFD)
amplitude_db = librosa.amplitude_to_db(amplitude, ref=np.max)

# obtenir les bacs de fréquence
frequency = librosa.fft_frequencies(sr=sampling_rate, n_fft=len(TFD_input))

plt.figure().set_figwidth(12)
plt.plot(frequency, amplitude_db)
plt.xlabel("Frequency (Hz)")
plt.ylabel("Amplitude (dB)")
plt.xscale("log")
```

    

Cela trace la force des différentes composantes de fréquence présentes dans ce segment audio. Les valeurs de fréquence sont sur l'axe des abscisses, généralement tracées sur une échelle logarithmique, tandis que leurs amplitudes sont sur l'axe des y.

Le spectre de fréquences que nous avons tracé montre plusieurs pics. 
Ces pics correspondent aux harmoniques de la note jouée, les harmoniques supérieures étant plus calmes. Puisque le premier pic est à environ 620 Hz, c'est le spectre de fréquence d'une♭ note Mi.

La sortie de la TDF est un tableau de nombres complexes, composé de composants réels et imaginaires. 
Prendre la magnitude avec ` np.abs(TFD)`  extrait l'information d'amplitude du spectrogramme.
L'angle entre les composants réels et imaginaires fournit ce que l'on appelle le spectre de phase, mais il est souvent écarté dans les applications d'apprentissage automatique.
Nous utilions `librosa.amplitude_to_db()` pour convertir les valeurs d'amplitude en échelle de décibels, ce qui facilite la visualisation des détails les plus fins du spectre. 
Parfois, les gens utilisent le **spectre de puissance**, qui mesure l'énergie plutôt que l'amplitude. Il s'agit simplement d'un spectre avec les valeurs d'amplitude au carré.

 
💡 En pratique, les gens utilisent le terme FFT de manière interchangeable avec TFD, car la FFT ou transformée de Fourier rapide est le seul moyen efficace de calculer la TFD sur un ordinateur.

Le spectre de fréquences d'un signal audio contient exactement la même information que sa forme d'onde. Ce sont simplement deux façons différentes de regarder les mêmes données (ici, les 4096 premiers échantillons du son de la trompette). 
Là où la forme d'onde trace l'amplitude du signal audio au fil du temps, le spectre visualise les amplitudes des fréquences individuelles à un moment donné.

## Spectrogramme

Et si nous voulons voir comment les fréquences d'un signal audio changent ? La trompette joue plusieurs notes et elles ont toutes des fréquences différentes. 
Le problème est que le spectre ne montre qu'un instantané figé des fréquences à un instant donné.
La solution consiste à prendre plusieurs TFD, chacune ne couvrant qu'une petite tranche de temps, et à empiler les spectres résultants dans un **spectrogramme**.

Un spectrogramme trace le contenu en fréquence d'un signal audio au fil du temps. Il vous permet de voir le temps, la fréquence et l'amplitude sur un seul graphique. L'algorithme qui effectue ce calcul est la TFCT ou transformée de Fourier à court terme.
Le spectrogramme est l'un des outils audio les plus informatifs à notre disposition. 
Par exemple, lorsque nous travaillons avec un enregistrement musical, nous pouvons voir les différents instruments et pistes vocales et comment ils contribuent au son global. Dans la parole, nous pouvons identifier différents sons de voyelles car chaque voyelle est caractérisée par des fréquences particulières.
Traçons un spectrogramme pour le même son de trompette, en utilisant les fonctions `stft()` et `specshow()` de librosa:

```py
import numpy as np

D = librosa.stft(array)
S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)

plt.figure().set_figwidth(12)
librosa.display.specshow(S_db, x_axis="time", y_axis="hz")
plt.colorbar()
```

    

Dans ce graphique, l'axe des x représente le temps comme dans la visualisation de la forme d'onde, mais maintenant l'axe des y représente la fréquence en Hz.
L'intensité de la couleur donne l'amplitude ou la puissance de la composante fréquence à chaque point dans le temps, mesurée en décibels (dB).

Le spectrogramme est créé en prenant de courts segments du signal audio, généralement de quelques millisecondes, et en calculant la transformée de Fourier discrète de chaque segment pour obtenir son spectre de fréquences. 
Les spectres résultants sont ensuite empilés sur l'axe temporel pour créer le spectrogramme. 
Chaque tranche verticale de cette image correspond à un spectre de fréquences unique, vu du haut. 
Par défaut, `librosa.stft()` divise le signal audio en segments de 2048 échantillons, ce qui donne un bon compromis entre la résolution de fréquence et la résolution temporelle.
Étant donné que le spectrogramme et la forme d'onde sont des vues différentes des mêmes données, il est possible de retourner le spectrogramme dans la forme d'onde d'origine en utilisant la TFCT inverse. 
Cependant, cela nécessite les informations de phase en plus des informations d'amplitude. Si le spectrogramme a été généré par un modèle d'apprentissage automatique, il ne produit généralement que les amplitudes. 
Dans ce cas, nous pouvons utiliser un algorithme de reconstruction de phase tel que l'algorithme classique de Griffin-Lim, ou en utilisant un réseau neuronal appelé vocodeur, pour reconstruire une forme d'onde à partir du spectrogramme.

Les spectrogrammes ne sont pas seulement utilisés pour la visualisation. De nombreux modèles d'apprentissage automatique prendront des spectrogrammes en entrée, par opposition aux formes d'onde, et produiront des spectrogrammes en sortie.
Maintenant que nous savons ce qu'est un spectrogramme et comment il est fabriqué, jetons un coup d'œil à une variante de celui-ci largement utilisée pour le traitement de la parole: le spectrogramme mel.

## Spectrogramme Mel

Un spectrogramme mel est une variante du spectrogramme couramment utilisée dans les tâches de traitement de la parole et d'apprentissage automatique.
Il est similaire à un spectrogramme en ce sens qu'il montre le contenu en fréquence d'un signal audio au fil du temps, mais sur un axe de fréquence différent.
Dans un spectrogramme standard, l'axe de fréquence est linéaire et est mesuré en hertz (Hz). 
Cependant, le système auditif humain est plus sensible aux changements dans les basses fréquences que dans les fréquences plus élevées, et cette sensibilité diminue logarithmiquement à mesure que la fréquence augmente. 
L'échelle mel est une échelle perceptuelle qui se rapproche de la réponse en fréquence non linéaire de l'oreille humaine.
Pour créer un spectrogramme mel, le STFT est utilisé comme auparavant, divisant l'audio en segments courts pour obtenir une séquence de spectres de fréquence. 
De plus, chaque spectre est envoyé à travers un ensemble de filtres, appelé *mel filterbank*, pour transformer les fréquences à l'échelle mel.
Voyons comment nous pouvons tracer un spectrogramme mel en utilisant la fonction `melspectrogram()` de librosa, qui effectue toutes ces étapes pour nous:

```py
S = librosa.feature.melspectrogram(y=array, sr=sampling_rate, n_mels=128, fmax=8000)
S_dB = librosa.power_to_db(S, ref=np.max)

plt.figure().set_figwidth(12)
librosa.display.specshow(S_dB, x_axis="time", y_axis="mel", sr=sampling_rate, fmax=8000)
plt.colorbar()
```

    

Dans l'exemple ci-dessus, `n_mels` représente le nombre de bandes mel à générer. 
Les bandes mel définissent un ensemble de gammes de fréquences qui divisent le spectre en composantes perceptuellement significatives, en utilisant un ensemble de filtres dont la forme et l'espacement sont choisis pour imiter la façon dont l'oreille humaine répond à différentes fréquences.
Les valeurs courantes pour `n_mels` sont 40 ou 80. `fmax` indique la fréquence la plus élevée (en Hz) qui nous intéresse.
Tout comme avec un spectrogramme standard, il est courant d'exprimer la force des composantes de fréquence mel en décibels. 
C'est ce qu'on appelle communément un **spectrogramme log-mel**, car la conversion en décibels implique une opération logarithmique. 
L'exemple ci-dessus utilisé `librosa.power_to_db()` car `librosa.feature.melspectrogram()` crée un spectrogramme de puissance.

💡 Tous les spectrogrammes mel ne sont pas identiques ! Il existe deux échelles mel différentes d'usage courant (« htk » et « slaney »), et au lieu du spectrogramme de puissance, le spectrogramme d'amplitude peut être utilisé. 
La conversion en spectrogramme log-mel ne calcule pas toujours les décibels vrais, mais peut simplement prendre le « log ». 
Par conséquent, si un modèle d'apprentissage automatique attend un spectrogramme mel en entrée, vérifiez deux fois pour vous assurer que vous le calculez de la même manière.

La création d'un spectrogramme mel est une opération avec perte car elle implique le filtrage du signal. 
La conversion d'un spectrogramme mel en une forme d'onde est plus difficile que de le faire pour un spectrogramme régulier, car cela nécessite d'estimer les fréquences qui ont été jetées. 
C'est pourquoi des modèles d'apprentissage automatique tels que le vocodeur HiFiGAN sont nécessaires pour produire une forme d'onde à partir d'un spectrogramme mel.
Comparé à un spectrogramme standard, un spectrogramme mel peut capturer des caractéristiques plus significatives du signal audio pour la perception humaine, ce qui en fait un choix populaire dans des tâches telles que la reconnaissance vocale, l'identification du locuteur et la classification des genres musicaux.
Maintenant que vous savez comment visualiser des exemples de données audio, essayez de voir à quoi ressemblent vos sons préférés :)

### Streaming de données audio
https://huggingface.co/learn/audio-course/fr/chapter1/streaming.md

# Streaming de données audio

L'un des plus grands défis auxquels sont confrontés les ensembles de données audio est leur taille. 
Une seule minute d'audio non compressé de qualité CD (44,1 kHz, 16 bits) occupe un peu plus de 5 Mo de stockage. En règle générale, un jeu de données audio contient des heures d'enregistrements.
Dans les sections précédentes, nous avons utilisé un très petit sous-ensemble de jeux de données audio MINDS-14, mais les jeux de données audio typiques sont beaucoup plus volumineux.
Par exemple, la configuration `xs` (la plus petite) de [GigaSpeech de SpeechColab](https://huggingface.co/datasets/speechcolab/gigaspeech) ne contient que 10 heures de données d'entraînement, mais prend plus de 13 Go d'espace de stockage pour le téléchargement et la préparation. 
Alors, que se passe-t-il lorsque nous voulons nous entraîner sur un split plus grand ? 
La configuration `xl` complète du même jeu de données contient 10 000 heures de données d'entraînement, nécessitant plus de 1 To d'espace de stockage. 
Pour la plupart d'entre nous, cela dépasse largement les spécifications d'un disque dur typique. Devons-nous débourser et acheter du stockage supplémentaire ? Ou existe-t-il un moyen de nous entraîner sur ces ensembles de données sans contraintes d'espace disque ?

 🤗 *Datasets* vient à la rescousse en proposant le mode [streaming](https://huggingface.co/docs/datasets/stream). 
 Le streaming nous permet de charger les données progressivement au fur et à mesure que nous itérons sur le jeu de données. Plutôt que de télécharger l'ensemble du jeu de données en une seule fois, nous chargeons le jeu de données un exemple à la fois.
 Nous itérons sur le jeu de données, chargeant et préparant des exemples à la volée lorsqu'ils sont nécessaires. De cette façon, nous ne chargeons que les exemples que nous utilisons, et non ceux que nous ne sommes pas !
Une fois que nous avons terminé avec un exemple d'exemple, nous continuons à itérer sur le jeu de données et chargeons le suivant.
Le mode streaming présente trois avantages principaux par rapport au téléchargement simultané de l'ensemble du jeu de données :
* Espace disque : les exemples sont chargés en mémoire un par un au fur et à mesure que nous itérons sur l'ensemble de données. Étant donné que les données ne sont pas téléchargées localement, il n'y a pas d'espace disque requis, vous pouvez donc utiliser des jeux de données de taille arbitraire.
* Temps de téléchargement et de traitement: les ensembles de données audio sont volumineux et nécessitent beaucoup de temps pour être téléchargés et traités. Avec le streaming, le chargement et le traitement se font à la volée, ce qui signifie que vous pouvez commencer à utiliser le jeu de données dès que le premier exemple est prêt.
* Expérimentation facile : vous pouvez expérimenter sur une poignée d'exemples pour vérifier que votre script fonctionne sans avoir à télécharger l'ensemble du jeu de données.

Il y a une mise en garde au mode streaming. Lors du téléchargement d'un jeu de données complet sans streaming, les données brutes et les données traitées sont enregistrées localement sur le disque. 
Si nous voulons réutiliser ce jeu de données, nous pouvons charger directement les données traitées à partir du disque, en sautant les étapes de téléchargement et de traitement.  
Par conséquent, nous ne devons effectuer les opérations de téléchargement et de traitement qu'une seule fois, après quoi nous pouvons réutiliser les données préparées.

Avec le mode streaming, les données ne sont pas téléchargées sur le disque. Ainsi, ni les données téléchargées ni les données prétraitées ne sont mises en cache.
Si nous voulons réutiliser le jeu de données, les étapes de streaming doivent être répétées, avec les fichiers audio chargés et traités à nouveau à la volée.
Pour cette raison, il est conseillé de télécharger des jeux de données que vous êtes susceptible d'utiliser plusieurs fois.

Comment activer le mode streaming ? Facile! Il suffit de définir `streaming=True` lorsque vous chargez votre jeu de données. Le reste sera pris en charge pour vous :

```py
gigaspeech = load_dataset("speechcolab/gigaspeech", "xs", streaming=True)
```

Tout comme nous avons appliqué des étapes de prétraitement à un sous-ensemble téléchargé de MINDS-14, vous pouvez effectuer le même prétraitement avec un jeu de données en streaming exactement de la même manière.
La seule différence est que vous ne pouvez plus accéder à des échantillons individuels à l'aide de l'indexation Python (c'est-à-dire `gigaspeech["train"][sample_idx]`).
Au lieu de cela, vous devez itérer sur le jeu de données. Voici comment accéder à un exemple lors de la diffusion en continu d'un jeu de données :

```py
next(iter(gigaspeech["train"]))
```
 
**Sortie :**

```out
{
    "segment_id": "YOU0000000315_S0000660",
    "speaker": "N/A",
    "text": "AS THEY'RE LEAVING  CAN KASH PULL ZAHRA ASIDE REALLY QUICKLY ",
    "audio": {
        "path": "xs_chunks_0000/YOU0000000315_S0000660.wav",
        "array": array(
            [0.0005188, 0.00085449, 0.00012207, ..., 0.00125122, 0.00076294, 0.00036621]
        ),
        "sampling_rate": 16000,
    },
    "begin_time": 2941.89,
    "end_time": 2945.07,
    "audio_id": "YOU0000000315",
    "title": "Return to Vasselheim | Critical Role: VOX MACHINA | Episode 43",
    "url": "https://www.youtube.com/watch?v=zr2n1fLVasU",
    "source": 2,
    "category": 24,
    "original_full_path": "audio/youtube/P0004/YOU0000000315.opus",
}
```
Si vous souhaitez prévisualiser plusieurs exemples d'un grand jeu de données, utilisez `take()` pour obtenir les $n$ premiers éléments. Prenons les deux premiers exemples dans le jeu de données gigaspeech :

```py
gigaspeech_head = gigaspeech["train"].take(2)
list(gigaspeech_head)
```

**Sortie :**

```out
[
    {
        "segment_id": "YOU0000000315_S0000660",
        "speaker": "N/A",
        "text": "AS THEY'RE LEAVING  CAN KASH PULL ZAHRA ASIDE REALLY QUICKLY ",
        "audio": {
            "path": "xs_chunks_0000/YOU0000000315_S0000660.wav",
            "array": array(
                [
                    0.0005188,
                    0.00085449,
                    0.00012207,
                    ...,
                    0.00125122,
                    0.00076294,
                    0.00036621,
                ]
            ),
            "sampling_rate": 16000,
        },
        "begin_time": 2941.89,
        "end_time": 2945.07,
        "audio_id": "YOU0000000315",
        "title": "Return to Vasselheim | Critical Role: VOX MACHINA | Episode 43",
        "url": "https://www.youtube.com/watch?v=zr2n1fLVasU",
        "source": 2,
        "category": 24,
        "original_full_path": "audio/youtube/P0004/YOU0000000315.opus",
    },
    {
        "segment_id": "AUD0000001043_S0000775",
        "speaker": "N/A",
        "text": "SIX TOMATOES ",
        "audio": {
            "path": "xs_chunks_0000/AUD0000001043_S0000775.wav",
            "array": array(
                [
                    1.43432617e-03,
                    1.37329102e-03,
                    1.31225586e-03,
                    ...,
                    -6.10351562e-05,
                    -1.22070312e-04,
                    -1.83105469e-04,
                ]
            ),
            "sampling_rate": 16000,
        },
        "begin_time": 3673.96,
        "end_time": 3675.26,
        "audio_id": "AUD0000001043",
        "title": "Asteroid of Fear",
        "url": "http//www.archive.org/download/asteroid_of_fear_1012_librivox/asteroid_of_fear_1012_librivox_64kb_mp3.zip",
        "source": 0,
        "category": 28,
        "original_full_path": "audio/audiobook/P0011/AUD0000001043.opus",
    },
]
```

Le mode streaming peut faire passer vos recherches au niveau supérieur : non seulement les plus grands jeux de données vous sont accessibles mais vous pouvez facilement évaluer les systèmes sur plusieurs jeux de données en une seule fois sans vous soucier de votre espace disque. 
Par rapport à l'évaluation sur un seul jeu de données, l'évaluation multi-jeux de données donne une meilleure mesure des capacités de généralisation d'un système de reconnaissance vocale (cf. *End-to-end Speech Benchmark* (ESB)).

### Prétraitement d'un jeu de données audio
https://huggingface.co/learn/audio-course/fr/chapter1/preprocessing.md

# Prétraitement d'un jeu de données audio

Le chargement d'un jeu de données avec 🤗 *Datasets* n'est que la moitié du plaisir. 
Si vous prévoyez de l'utiliser pour entraîner un modèle ou pour exécuter l'inférence, vous devrez d'abord prétraiter les données. En général, cela impliquera les étapes suivantes:
* Rééchantillonnage des données audio
* Filtrage du jeu de données
* Conversion des données audio en entrée attendue du modèle

## Rééchantillonnage des données audio

La fonction `load_dataset` télécharge des exemples audio avec le taux d'échantillonnage avec lequel ils ont été publiés.
Ce n'est pas toujours le taux d'échantillonnage attendu par un modèle que vous prévoyez d'entraîner ou d'utiliser pour l'inférence. 
S'il existe un écart entre les taux d'échantillonnage, vous pouvez rééchantillonner l'audio à la fréquence d'échantillonnage attendue du modèle.
La plupart des modèles pré-entraînés disponibles ont été pré-entraînés sur des jeux de données audio à une fréquence d'échantillonnage de 16 kHz.
Lorsque nous avons exploré le jeu de données MINDS-14, vous avez peut-être remarqué qu'il est échantillonné à 8 kHz, ce qui signifie que nous devrons probablement le suréchantillonner.
Pour ce faire, utilisez la méthode `cast_column` de 🤗 Datasets. 
Cette opération ne modifie pas l'audio sur place, mais plutôt les signaux aux jeux de données pour rééchantillonner les exemples audio à la volée lorsqu'ils sont chargés. 
Le code suivant définira la fréquence d'échantillonnage à 16 kHz :

```py
from datasets import Audio

minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
```

Rechargez le premier exemple audio dans le jeu de données MINDS-14 et vérifiez qu'il a été rééchantillonné à la « fréquence d'échantillonnage » souhaitée :

```py
minds[0]
```

**Sortie :**

```out
{
    "path": "/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-AU~PAY_BILL/response_4.wav",
    "audio": {
        "path": "/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-AU~PAY_BILL/response_4.wav",
        "array": array(
            [
                2.0634243e-05,
                1.9437837e-04,
                2.2419340e-04,
                ...,
                9.3852862e-04,
                1.1302452e-03,
                7.1531429e-04,
            ],
            dtype=float32,
        ),
        "sampling_rate": 16000,
    },
    "transcription": "I would like to pay my electricity bill using my card can you please assist",
    "intent_class": 13,
}

```
Vous remarquerez peut-être que les valeurs de tableau sont maintenant également différentes. C'est parce que nous avons maintenant deux fois plus de valeurs d'amplitude pour chacune d'entre elles que nous avions auparavant.

 
💡 Quelques informations sur le rééchantillonnage: Si un signal audio a été échantillonné à 8 kHz, de sorte qu'il a 8000 lectures d'échantillon par seconde, nous savons que l'audio ne contient aucune fréquence supérieure à 4 kHz. 
Ceci est garanti par le théorème d'échantillonnage de Nyquist. Pour cette raison, nous pouvons être certains qu'entre les points d'échantillonnage, le signal continu d'origine fait toujours une courbe lisse.
L'augmentation du prélèvement vers un taux d'échantillonnage plus élevé consiste alors à calculer des valeurs d'échantillonnage supplémentaires qui se situent entre les valeurs existantes, en approximant cette courbe. 
Le sous-échantillonnage, cependant, nécessite que nous filtrons d'abord toutes les fréquences qui seraient supérieures à la nouvelle limite de Nyquist, avant d'estimer les nouveaux points d'échantillonnage. 
En d'autres termes, vous ne pouvez pas sous-échantillonner d'un facteur 2x en jetant simplement tous les autres échantillons - cela créera des distorsions dans le signal appelées alias. 
Faire un rééchantillonnage correct est délicat et mieux laissé à des bibliothèques bien testées telles que librosa ou 🤗 *Datasets*.

## Filtrage du jeu de données

Vous devrez peut-être filtrer les données en fonction de certains critères. L'un des cas courants consiste à limiter les exemples audio à une certaine durée. 
Par exemple, nous pourrions vouloir filtrer tous les exemples de plus de 20 secondes pour éviter les erreurs de mémoire insuffisante lors de l'entraînement d'un modèle.
Nous pouvons le faire en utilisant la  méthode `filter` de 🤗 *Datasets* et en lui passant une fonction avec une logique de filtrage. Commençons par écrire une fonction qui indique quels exemples conserver et lesquels rejeter. 
Cette fonction, `is_audio_length_in_range', renvoie `True` si un échantillon est inférieur à 20s et `False` s'il est plus long que 20s.

```py
MAX_DURATION_IN_SECONDS = 20.0

def is_audio_length_in_range(input_length):
    return input_length 

Vous pouvez maintenant voir à quoi ressemble l'entrée audio du modèle Whisper après le prétraitement.

La classe d'extracteur de caractéristiques du modèle se charge de transformer les données audio brutes au format attendu par le modèle. Cependant, de nombreuses tâches impliquant l'audio sont multimodales, par exemple la reconnaissance vocale. 
Dans de tels cas, 🤗 *Transformers* offrent également des tokeniseurs spécifiques au modèle pour traiter les entrées de texte. Pour une plongée approfondie dans les tokeniseurs, veuillez vous référer à notre [cours de NLP](https://huggingface.co/learn/nlp-course/fr/chapter2/4).

Vous pouvez charger séparément l'extracteur de caractéristiques et le tokeniseur pour Whisper et d'autres modèles multimodaux, ou vous pouvez charger les deux via un processeur. 
Pour rendre les choses encore plus simples, utilisez `AutoProcessor` pour charger l'extracteur de caractéristiques et le processeur d'un modèle à partir d'un *checkpoint*, comme ceci :

```py
from transformers import AutoProcessor

processor = AutoProcessor.from_pretrained("openai/whisper-small")
```

Nous avons illustré ici les étapes fondamentales de préparation des données. Bien entendu, les données personnalisées peuvent nécessiter un prétraitement plus complexe.
Dans ce cas, vous pouvez étendre la fonction `prepare_dataset` pour effectuer n'importe quel type de transformations de données personnalisées.
Avec 🤗 *Datasets*, si vous pouvez l'écrire en tant que fonction Python, vous pouvez l'appliquer à votre jeu de données !

### Unité 1 : Travailler avec des données audio
https://huggingface.co/learn/audio-course/fr/chapter1/introduction.md

# Unité 1 : Travailler avec des données audio

## Ce que vous apprendrez dans cette unité

Chaque tâche audio ou vocale commence par un fichier audio. Avant de pouvoir résoudre ces tâches, il est important de comprendre ce que ces fichiers contiennent réellement et comment les utiliser.

Dans cette unité, vous acquerrez une compréhension de la terminologie fondamentale liée aux données audio, notamment la forme d'onde, la fréquence d'échantillonnage et le spectrogramme. Vous apprendrez également à travailler avec des jeux de données audio, y compris le chargement et le prétraitement des données audio, et à streamer efficacement de grands jeux de données.

À la fin de cette unité, vous maîtriserez la terminologie essentielle des données audio et serez équipé des compétences nécessaires pour travailler avec des jeux de données audio pour diverses applications. Les connaissances issues de cette unité vont jeter les bases de la compréhension du reste du cours.

### Charger et explorer un jeu de données audio
https://huggingface.co/learn/audio-course/fr/chapter1/load_and_explore.md

# Charger et explorer un jeu de données audio

Dans ce cours, nous utiliserons la bibliothèque 🤗 *Datasets* pour travailler avec des jeux de données audio. 
🤗 *Datasets* est une bibliothèque open-source permettant de télécharger et de préparer des jeux de données à partir de toutes les modalités, y compris l'audio. 
La bibliothèque offre un accès facile à une sélection inégalée de jeux de données d'apprentissage automatique accessibles sur Hugging Face Hub. 
De plus, 🤗 *Datasets* comprend de multiples fonctionnalités adaptées aux jeux de données audio simplifiant le travail avec de tels jeux de données pour les chercheurs et les praticiens.
Pour commencer à utiliser des jeux de données audio, assurez-vous que la 🤗 *Datasets* est installée :

```bash
pip install datasets[audio] soundfile librosa torchcodec
```

L'une des principales caractéristiques déterminantes de 🤗 *Datasets*  est la possibilité de télécharger et de préparer un jeu de données en une seule ligne de code Python à l'aide de la fonction `load_dataset()`.
Chargeons et explorons un jeu de données audio appelé [MINDS-14](https://huggingface.co/datasets/PolyAI/minds14), qui contient des enregistrements de personnes posant des questions à un système bancaire électronique dans plusieurs langues et dialectes.
Pour charger le jeu de données MINDS-14, nous devons copier l'identifiant du jeu de données sur le Hub (`PolyAI/minds14`) et le transmettre à la fonction `load_dataset`.
Nous préciserons également que nous ne nous intéressons qu'au sous-ensemble australien ('en-AU') des données, et le limiterons à la division de l'entraînement :

```py
from datasets import load_dataset

minds = load_dataset("PolyAI/minds14", name="en-AU", split="train")
minds
```

**Sortie :**

```out
Dataset(
    {
        features: [
            "path",
            "audio",
            "transcription",
            "english_transcription",
            "intent_class",
            "lang_id",
        ],
        num_rows: 654,
    }
)
```

Le jeu de données contient 654 fichiers audio, chacun étant accompagné d'une transcription, d'une traduction en anglais et d'une étiquette indiquant l'intention derrière la requête de la personne. 
La colonne audio contient les données audio brutes. Examinons de plus près l'un des exemples:

```py
example = minds[0]
example
```

**Sortie :**

```out
{
    "path": "/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-AU~PAY_BILL/response_4.wav",
    "audio": {
        "path": "/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-AU~PAY_BILL/response_4.wav",
        "array": array(
            [0.0, 0.00024414, -0.00024414, ..., -0.00024414, 0.00024414, 0.0012207],
            dtype=float32,
        ),
        "sampling_rate": 8000,
    },
    "transcription": "I would like to pay my electricity bill using my card can you please assist",
    "english_transcription": "I would like to pay my electricity bill using my card can you please assist",
    "intent_class": 13,
    "lang_id": 2,
}
```

Vous remarquerez peut-être que la colonne audio contient plusieurs caractéristiques :
* `path` : le chemin d'accès au fichier audio (`*.wav` dans ce cas).
*  `array`: les données audio décodées, représentées sous la forme d'un tableau NumPy à 1 dimension.
* `sampling_rate` : taux d'échantillonnage du fichier audio (8 000 Hz dans cet exemple).
Le `intent_class` est une catégorie de classification de l'enregistrement audio. Pour convertir ce nombre en une chaîne significative, nous pouvons utiliser la méthode `int2str()`:

```py
id2label = minds.features["intent_class"].int2str
id2label(example["intent_class"])
```

**Sortie :**

```out
"pay_bill"
```

Si vous regardez la fonction de transcription, vous pouvez voir que le fichier audio a effectivement enregistré une personne posant une question sur le paiement d'une facture.
Si vous envisagez d'entraîner un classifieur audio sur ce sous-ensemble de données, vous n'aurez pas nécessairement besoin de toutes les caractéristiques. 
Par exemple, le `lang_id` aura la même valeur pour tous les exemples et ne sera pas utile. 
Les `english_transcription` dupliqueront probablement la `transcription` de ce sous-ensemble, afin que nous puissions les supprimer en toute sécurité.

Vous pouvez facilement supprimer les caractéristiques non pertinentes à l'aide de la méthode `remove_columns` de 🤗 *Datasets* :

```py
columns_to_remove = ["lang_id", "english_transcription"]
minds = minds.remove_columns(columns_to_remove)
minds
```

**Sortie :**

```out
Dataset({features: ["path", "audio", "transcription", "intent_class"], num_rows: 654})
```

Maintenant que nous avons chargé et inspecté le contenu brut du jeu de données, écoutons quelques exemples ! Nous utiliserons les fonctionnalités `Blocs` et `Audio` de *Gradio* pour décoder quelques échantillons aléatoires du jeu de données:

```py
import gradio as gr

def generate_audio():
    example = minds.shuffle()[0]
    audio = example["audio"]
    return (
        audio["sampling_rate"],
        audio["array"],
    ), id2label(example["intent_class"])

with gr.Blocks() as demo:
    with gr.Column():
        for _ in range(4):
            audio, label = generate_audio()
            output = gr.Audio(audio, label=label)

demo.launch(debug=True)
```

Si vous le souhaitez, vous pouvez également visualiser certains des exemples. Traçons la forme d'onde pour le premier exemple.

```py
import librosa
import matplotlib.pyplot as plt
import librosa.display

array = example["audio"]["array"]
sampling_rate = example["audio"]["sampling_rate"]

plt.figure().set_figwidth(12)
librosa.display.waveshow(array, sr=sampling_rate)
```

    

Essayez ! Téléchargez un autre dialecte ou une autre langue du jeu de données MINDS-14, écoutez et visualisez quelques exemples pour avoir une idée des variations du jeu de données. 
Vous pouvez trouver la liste complète des langues disponibles [ici](https://huggingface.co/datasets/PolyAI/minds14).

### En apprendre encore plus
https://huggingface.co/learn/audio-course/fr/chapter1/supplemental_reading.md

# En apprendre encore plus

Cette unité couvre de nombreux concepts fondamentaux permettant de comprendre les données audio et de travailler avec elles.
Vous voulez en savoir plus ? Vous trouverez ici des ressources supplémentaires qui vous aideront à approfondir votre compréhension des sujets et à améliorer votre expérience d'apprentissage.

Dans la vidéo suivante, Monty Montgomery de xiph.org présente une démonstration en temps réel de l'échantillonnage, de la quantification, la profondeur de bits et le dither sur un équipement audio réel en utilisant à la fois une analyse numérique moderne et un équipement analogique vintage, regardez-la :

Si vous souhaitez approfondir le traitement des signaux numériques, consultez le livre gratuit (en anglais) [*Digital Signals Theory*](https://brianmcfee.net/dstbook-site/content/intro.html) écrit par Brian McFee, professeur assistant de technologie musicale et de science des données à l'Université de New York et principal responsable de `librosa`.

### Vérifier votre compréhension de l'unité
https://huggingface.co/learn/audio-course/fr/chapter1/quiz.md

# Vérifier votre compréhension de l'unité

### 1. En quelles unités le taux d'échantillonnage est-il mesuré ?

### 2. Lorsqu'un grand jeu de données audio est streamé, à quel moment peut-on commencer à l'utiliser ?

### 3. Qu'est-ce qu'un spectrogramme ?

### 4. Quel est le moyen le plus simple de convertir des données audio brutes en spectrogramme log-mel attendu par Whisper ?

A.

```python
librosa.feature.melspectrogram(audio["array"])
```

B.

```python
feature_extractor = WhisperFeatureExtractor.from_pretrained("openai/whisper-small")
feature_extractor(audio["array"])
```

C.

```python
dataset.feature(audio["array"], model="whisper")
```

Transformers, ceci est fait par le préprocesseur du modèle."
		}
	]}
/>

### 5. Comment charger un jeu de données depuis me 🤗 Hub ?

A.

```python
from datasets import load_dataset

dataset = load_dataset(DATASET_NAME_ON_HUB)
```

B.

```python
import librosa

dataset = librosa.load(PATH_TO_DATASET)
```

C.

```python
from transformers import load_dataset

dataset = load_dataset(DATASET_NAME_ON_HUB)
```

Datasets.",
			correct: true
		},
		{
			text: "B",
			explain: "Librosa.load est utile pour charger un fichier audio individuel à partir d'un chemin dans un tuple avec des séries temporelles audio et une fréquence d'échantillonnage, mais pas un jeu de données entier avec de nombreux exemples et de multiples caractéristiques. "
		},
		{
			text: "C",
			explain: "La méthode load_dataset se trouve dans la bibliothèque 🤗 Datasets, pas dans 🤗 Transformers."
		}
	]}
/>

### 6. Votre jeu de données personnalisé contient des données audio de haute qualité avec une fréquence d'échantillonnage de 32 kHz. Vous souhaitez entraîner un modèle de reconnaissance vocale qui s'attend à ce que les exemples audio aient une fréquence d'échantillonnage de 16 kHz. Que devez-vous faire ?

Audio de la bibliothèque 🤗 Datasets pour sous-échantillonner les exemples du jeu de données personnalisé.",
			explain: "",
			correct: true
		},
		{
			text: "Réduire l'échantillonnage d'un facteur 2 en éliminant tous les autres échantillons.",
			explain: "Cela créera des distorsions dans le signal, appelées alias. Le rééchantillonnage est une opération délicate qu'il vaut mieux confier à des bibliothèques éprouvées telles que librosa ou 🤗 Datasets."
		}
	]}
/>

### 7. Comment convertir un spectrogramme généré par un modèle d'apprentissage automatique en une forme d'onde ?
