mouadElmansour's picture
run 6, step 12000 : WER 0.1509 sur eval_isma, 0 % d'hallucinations sur le silence
6da7ea9 verified
|
Raw History Blame Contribute Delete
3.14 kB
metadata
language:
  - ar
  - fr
  - en
tags:
  - whisper
  - automatic-speech-recognition
  - darija
  - code-switching
pipeline_tag: automatic-speech-recognition

run6_checkpoint_12000s : Whisper darija-v5 fine-tuné (run 6, step 12000)

Fine-tuning de darija-v5 (whisper-darija-v5-checkpoint-2800) pour la transcription de la darija marocaine avec alternance français/anglais. Ce modèle a aussi appris à ne rien écrire sur du silence ou du bruit.

Entraînement

  • Données : lmaana, Dataset13, batch2, batch4, batch5 (309 346 segments)
    • 400 segments de silence/bruit répétés 5 fois (0,64 %)
  • 12 000 steps d'un programme de 19 458 (2 époques), batch 32, LR 1e-6 (warmup 500, décroissance linéaire), weight decay 0,01, SpecAugment, bf16
  • Choisi par une règle fixée avant les mesures : le plus ancien checkpoint du plateau, aucun plus tardif ne faisant mieux de plus de 0,2 point

Résultats (fp32, décodage greedy, normalisation darija)

eval_isma : 357 phrases annotées par des humains.

Modèle WER CER Sub. Del. Ins.
darija-v5 (départ) 0.1871 0.0845 0.1407 0.0257 0.0207
run 5 (run5_bestcheckpoint) 0.1577 0.0703 0.1207 0.0202 0.0168
ce modèle 0.1509 0.0711 0.1125 0.0212 0.0172

Silence : 80 segments de bruit jamais vus à l'entraînement, fin de texte permise dès le premier token.

Modèle Segments où le modèle écrit quelque chose
darija-v5 100 %
ce modèle 0 %

Autoriser la sortie vide ne change rien sur eval_isma (mêmes WER et suppressions au chiffre près). eval_isma a aussi servi au choix du checkpoint : les chiffres peuvent être légèrement optimistes.

Utilisation

Par défaut, Whisper interdit la fin de texte comme premier token (begin_suppress_tokens) : il écrit toujours au moins un mot, même sur du silence. Pour profiter de l'apprentissage du silence, on calcule d'abord le premier token ; s'il s'agit de la fin de texte, la transcription est vide.

import torch
from transformers import WhisperForConditionalGeneration, WhisperProcessor

repo = "mouadElmansour/run6_checkpoint_12000s"
processor = WhisperProcessor.from_pretrained(repo)
model = WhisperForConditionalGeneration.from_pretrained(repo).eval()
tok = processor.tokenizer

def transcrire(audio):  # tableau float32 mono à 16 kHz
    features = processor(audio, sampling_rate=16000, return_tensors="pt").input_features
    prompt = [tok.convert_tokens_to_ids(t) for t in
              ("<|startoftranscript|>", "<|ar|>", "<|transcribe|>", "<|notimestamps|>")]
    with torch.no_grad():
        logits = model(input_features=features, decoder_input_ids=torch.tensor([prompt])).logits[0, -1]
        interdits = set(model.generation_config.suppress_tokens or []) | {220}
        logits[sorted(interdits)] = float("-inf")
        if logits.argmax().item() == tok.eos_token_id:
            return ""  # silence
        ids = model.generate(features, language="ar", task="transcribe", num_beams=1)
    return processor.batch_decode(ids, skip_special_tokens=True)[0]