Skip to main content

Penulis

Vikas Reddy - University of Maryland

Abstrak

Dalam landskap teknologi komunikasi yang berkembang pesat, kejayaan terkini, terutamanya model OpenAI Whisper, telah meningkatkan ketepatan dan kebolehcapaian keupayaan pertuturan-ke-teks berbilang bahasa dengan ketara. Walau bagaimanapun, walaupun perkembangan ini, masih ada ruang untuk peningkatan, terutamanya dari segi ketepatan. Penyelidikan ini didedikasikan untuk meningkatkan keupayaan model pengecaman pertuturan automatik (ASR), dengan tumpuan khusus pada bahasa Vietnam dan Jepun. Penilaian kami menggunakan ukuran standard untuk mengukur prestasi. Untuk bahasa Vietnam, kami menggunakan metrik Word Error Rate (WER), yang menilai seberapa kerap perkataan yang dikenali menyimpang dari perkataan yang sebenarnya diucapkan. Untuk bahasa Jepun, kami menggunakan metrik Character Error Rate (CER), yang meneliti ketepatan aksara individu. Keputusan Utama:
  • Vietnam (FOSD + Common Voice + Google Fleurs + Vivos): WER 9.46%
  • Jepun (ReazonSpeech + Common Voice + Google Fleurs): CER 8.15%

Isi Kandungan

  1. Maklumat Latar Belakang
  2. Persediaan Persekitaran
  3. Muatkan Set Data
  4. Pra-pemprosesan Data
  5. Latihan
  6. Penalaan Halus Cekap Parameter
  7. Keputusan
  8. Penilaian
  9. Azure Speech Studio
  10. Kesimpulan

1. Maklumat Latar Belakang

Dalam masyarakat hari ini, komunikasi dan teknologi telah menjadi sangat diperlukan, namun beberapa cabaran masih wujud yang memberi kesan kepada kebolehcapaian, keterangkuman, dan penyebaran pengetahuan yang cekap. Di sinilah kemajuan seperti pengecaman pertuturan automatik (ASR) membantu, memperkemas interaksi antara manusia dan komputer, terutamanya jelas dalam panggilan mesyuarat dalam talian. ASR adalah proses menukar isyarat pertuturan kepada teks yang sepadan. Baru-baru ini, tugas ini telah mendapat tarikan dengan pelbagai syarikat, berkat kebolehcapaian set data pertuturan yang besar, bersama dengan transkrip yang sepadan.
Seni Bina OpenAI Whisper
OpenAI Whisper adalah model encoder-decoder berasaskan Transformer, direka khusus sebagai seni bina sequence-to-sequence. Ia mengambil ciri spektrogram audio sebagai input dan menukarnya kepada urutan token teks. Ini melibatkan:
  1. Pengekstrak ciri yang mengubah audio mentah kepada spektrogram log-Mel
  2. Encoder Transformer yang menjana urutan keadaan tersembunyi encoder
  3. Decoder yang meramalkan token teks menggunakan mekanisme perhatian silang

2. Persediaan Persekitaran

Terdapat dua pendekatan berbeza untuk menala halus Whisper: menggunakan Google Colab dan menjalankan kod pada PC tempatan.

Pakej Diperlukan

python -m pip install -U pip
pip install evaluate pandas numpy huggingface_hub pydub tqdm spacy ginza audiomentations
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install datasets>=2.6.1
pip install git+https://github.com/huggingface/transformers
pip install librosa
pip install evaluate>=0.30
pip install jiwer
pip install gradio
pip install -q bitsandbytes datasets accelerate loralib
pip install -q git+https://github.com/huggingface/transformers.git@main git+https://github.com/huggingface/peft.git@main
Konfigurasi komputer yang digunakan untuk tugas penalaan halus artikel ini melibatkan PC Windows 11 Pro dengan Pemproses AMD Ryzen 7 3700X 8-Teras dengan 80GB RAM dan Kad Grafik NVIDIA GeForce RTX 3090.

3. Muatkan Set Data

Kaedah 1: Menggunakan Hugging Face

from datasets import load_dataset, DatasetDict

common_voice = DatasetDict()
common_voice["train"] = load_dataset(
    "mozilla-foundation/common_voice_11_0", "ja",
    split="train+validation", use_auth_token=True
)
common_voice["test"] = load_dataset(
    "mozilla-foundation/common_voice_11_0", "ja",
    split="test", use_auth_token=True
)
common_voice = common_voice.remove_columns([
    "accent", "age", "client_id", "down_votes",
    "gender", "locale", "path", "segment", "up_votes"
])

Kaedah 2: Penyediaan Set Data Manual

import os, csv, codecs

def text_change_csv(input_path, output_path):
    file_csv = os.path.splitext(output_path)[0] + ".csv"
    output_dir = os.path.dirname(input_path)
    output_file = os.path.join(output_dir, file_csv)
    encodings = ["utf-8", "latin-1"]

    for encoding in encodings:
        try:
            with open(input_path, 'r', encoding=encoding) as rf:
                with codecs.open(output_file, 'w', encoding=encoding, errors='replace') as wf:
                    readfile = rf.readlines()
                    for read_text in readfile:
                        read_text = read_text.split('|')
                        writer = csv.writer(wf, delimiter=',')
                        writer.writerow(read_text)
            print(f"CSV has been created using encoding: {encoding}")
            return True
        except UnicodeDecodeError:
            continue

Set Data Yang Digunakan

Set DataBahasaPenggunaanAudio Pertuturan (Jam)
Common Voice 13.0Vietnam, JepunHugging Face19j (VN), 10j (JP)
Google FleursVietnam, JepunHugging Face11j (VN), 8j (JP)
VivosVietnamHugging Face15j
FPT Open Speech DatasetVietnamMuat turun & ekstrak30j
VLSP2020VietnamMuat turun & ekstrak100j
ReazonSpeechJepunHugging Face5j
JSUTJepunMuat turun & ekstrak10j
JVSJepunMuat turun & ekstrak30j

4. Pra-pemprosesan Data

Penambahan Data

from audiomentations import Compose, AddGaussianNoise, TimeStretch, PitchShift

common_voice = common_voice.cast_column("audio", Audio(sampling_rate=16000))

augment_waveform = Compose([
    AddGaussianNoise(min_amplitude=0.005, max_amplitude=0.015, p=0.2),
    TimeStretch(min_rate=0.8, max_rate=1.25, p=0.2, leave_length_unchanged=False),
    PitchShift(min_semitones=-4, max_semitones=4, p=0.2)
])

def augment_dataset(batch):
    audio = batch["audio"]["array"]
    augmented_audio = augment_waveform(samples=audio, sample_rate=16000)
    batch["audio"]["array"] = augmented_audio
    return batch

common_voice['train'] = common_voice['train'].map(augment_dataset, keep_in_memory=True)

Normalisasi Transkrip

import string

def remove_punctuation(sentence):
    translator = str.maketrans('', '', string.punctuation)
    modified_sentence = sentence.translate(translator)
    return modified_sentence

def fix_sentence(sentence):
    transcription = sentence
    if transcription.startswith('"') and transcription.endswith('"'):
        transcription = transcription[1:-1]
    transcription = remove_punctuation(transcription)
    transcription = transcription.lower()
    return transcription

Sediakan Set Data untuk Whisper

def prepare_dataset(batch):
    audio = batch["audio"]
    batch["input_features"] = processor.feature_extractor(
        audio["array"], sampling_rate=audio["sampling_rate"]
    ).input_features[0]
    batch["input_length"] = len(audio["array"]) / audio["sampling_rate"]

    transcription = fix_sentence(batch["transcription"])
    batch["labels"] = processor.tokenizer(
        transcription, max_length=225, truncation=True
    ).input_ids
    return batch

common_voice = common_voice.map(
    prepare_dataset,
    remove_columns=common_voice.column_names['train'],
    num_proc=1,
    keep_in_memory=True
)

5. Latihan

Data Collator

import torch
from dataclasses import dataclass
from typing import Any, Dict, List, Union

@dataclass
class DataCollatorSpeechSeq2SeqWithPadding:
    processor: Any

    def __call__(self, features: List[Dict[str, Union[List[int], torch.Tensor]]]) -> Dict[str, torch.Tensor]:
        input_features = [{"input_features": feature["input_features"]} for feature in features]
        batch = self.processor.feature_extractor.pad(input_features, return_tensors="pt")

        label_features = [{"input_ids": feature["labels"]} for feature in features]
        labels_batch = self.processor.tokenizer.pad(label_features, return_tensors="pt")

        labels = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100)

        if (labels[:, 0] == self.processor.tokenizer.bos_token_id).all().cpu().item():
            labels = labels[:, 1:]

        batch["labels"] = labels
        return batch

data_collator = DataCollatorSpeechSeq2SeqWithPadding(processor=processor)

Metrik Penilaian (Vietnam - WER)

import evaluate

metric = evaluate.load("wer")

def compute_metrics(pred):
    pred_ids = pred.predictions
    label_ids = pred.label_ids
    label_ids[label_ids == -100] = tokenizer.pad_token_id

    pred_str = tokenizer.batch_decode(pred_ids, skip_special_tokens=True)
    label_str = tokenizer.batch_decode(label_ids, skip_special_tokens=True)

    wer = 100 * metric.compute(predictions=pred_str, references=label_str)
    return {"wer": wer}

Metrik Penilaian (Jepun - CER)

import spacy, ginza

nlp = spacy.load("ja_ginza")
ginza.set_split_mode(nlp, "C")

def compute_metrics(pred):
    pred_ids = pred.predictions
    label_ids = pred.label_ids
    label_ids[label_ids == -100] = processor.tokenizer.pad_token_id

    pred_str = processor.tokenizer.batch_decode(pred_ids, skip_special_tokens=True)
    label_str = processor.tokenizer.batch_decode(label_ids, skip_special_tokens=True)

    # Tokenize teks Jepun untuk penilaian yang betul
    pred_str = [" ".join([str(i) for i in nlp(j)]) for j in pred_str]
    label_str = [" ".join([str(i) for i in nlp(j)]) for j in label_str]

    wer = 100 * metric.compute(predictions=pred_str, references=label_str)
    return {"wer": wer}

Argumen Latihan

from transformers import Seq2SeqTrainingArguments

model.config.dropout = 0.05

training_args = Seq2SeqTrainingArguments(
    output_dir="./whisper-fine-tuned",
    per_device_train_batch_size=16,
    gradient_accumulation_steps=1,
    learning_rate=1e-6,
    lr_scheduler_type='linear',
    optim="adamw_bnb_8bit",
    warmup_steps=200,
    num_train_epochs=5,
    gradient_checkpointing=True,
    evaluation_strategy="steps",
    fp16=True,
    per_device_eval_batch_size=8,
    predict_with_generate=True,
    generation_max_length=255,
    eval_steps=500,
    logging_steps=500,
    report_to=["tensorboard"],
    load_best_model_at_end=True,
    metric_for_best_model="wer",
    greater_is_better=False,
    push_to_hub=False,
    save_total_limit=1
)
Parameter latihan utama:
  • learning_rate: 1e-5 atau 1e-6 berfungsi paling baik
  • warmup_steps: Gunakan 10% daripada keseluruhan langkah
  • per_device_train_batch_size: Tetapkan berdasarkan kapasiti GPU (16 untuk RTX 3090)
  • dropout: 0.05 atau 0.10 untuk memerangi overfitting

6. Penalaan Halus Cekap Parameter (PEFT)

PEFT mencapai prestasi kompetitif sambil hanya menggunakan 1% parameter boleh latih.
Penalaan HalusPenalaan Halus Cekap Parameter
Masa latihan lebih pantasMasa latihan lebih lama
Memerlukan sumber pengiraan yang lebih besarMenggunakan sumber pengiraan yang lebih sedikit
Melatih semula keseluruhan modelMengubah suai hanya subset kecil parameter
Lebih cenderung kepada overfittingKurang cenderung kepada overfitting

Persediaan LoRA

from transformers import WhisperForConditionalGeneration, prepare_model_for_int8_training
from peft import LoraConfig, get_peft_model

model = WhisperForConditionalGeneration.from_pretrained(
    model_name_or_path, load_in_8bit=True, device_map="auto"
)
model = prepare_model_for_int8_training(model)

def make_inputs_require_grad(module, input, output):
    output.requires_grad_(True)

model.model.encoder.conv1.register_forward_hook(make_inputs_require_grad)

config = LoraConfig(
    r=32,
    lora_alpha=64,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05,
    bias="none"
)
model = get_peft_model(model, config)
model.print_trainable_parameters()
# Output: trainable params: 15728640 || all params: 1559033600 || trainable%: 1.01%

7. Keputusan

Keputusan Vietnam

Keputusan Whisper Large Vietnam
Model yang ditala halus pada set data FOSD + Google Fleurs + Vivos + CV mencapai WER terendah 9.46%.

Keputusan Jepun

Keputusan Whisper Large Jepun
Model yang ditala halus pada set data JSUT + ReazonSpeech + Google Xtreme + CV mencapai CER terendah 8.15%.

Keluk Kehilangan Pengoptimuman

Keluk Kehilangan Pengoptimuman

8. Penilaian

Penilaian Vietnam

Keputusan Penilaian Vietnam
Antara set data yang dinilai, set data Google Fleurs + Common Voice + Vivos mencapai CER terendah 7.84%, menunjukkan transkripsi yang sangat tepat.

Penilaian Jepun

Keputusan Penilaian Jepun
Set data gabungan ReazonSpeech + Google Xtreme + CV mencapai CER terendah 7.44%.

Penukaran Faster-Whisper

from ctranslate2.converters import TransformersConverter

model_id = "./whisper-fine-tuned/checkpoint-5000"
output_dir = "whisper-ct2"

converter = TransformersConverter(model_id, load_as_float16=True)
converter.convert(output_dir, quantization="float16")
model = WhisperModel(output_dir, device="cuda", compute_type="float16")
Faster Whisper menawarkan kira-kira 40% inferens lebih pantas berbanding Whisper yang ditala halus standard sambil mengekalkan ketepatan yang setanding.

9. Azure Speech Studio

Azure Speech Studio menyediakan pendekatan alternatif untuk menala halus model ASR.

Transkripsi dengan Azure

import os, evaluate
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, AudioConfig

subscription_key = "your_subscription_key"
location = "japaneast"
endpoint = "your_endpoint"

config = SpeechConfig(subscription=subscription_key, region=location)
config.endpoint_id = endpoint
speech_config = SpeechConfig(
    subscription=subscription_key,
    region=location,
    speech_recognition_language="ja-JP"
)

predictions = []
for root, _, files in os.walk(wav_base_path):
    for file_name in files:
        if file_name.endswith(".wav"):
            audio_file_path = os.path.join(root, file_name)
            audio_config = AudioConfig(filename=audio_file_path)
            speech_recognizer = SpeechRecognizer(
                speech_config=speech_config,
                audio_config=audio_config
            )
            result = speech_recognizer.recognize_once()
            if result.text:
                predictions.append(result.text)

Keputusan Azure

Vietnam: Model yang dilatih pada Common Voice 14.0 mencapai WER 7.33% Jepun: Model yang dilatih pada JSUT mencapai CER 6.97%
Walaupun Azure Speech Studio mungkin menghasilkan WER yang lebih rendah semasa latihan, Whisper cenderung mencapai keputusan penilaian yang lebih baik pada data yang tidak dilihat, terutamanya pada audio yang pelbagai dan kompleks.

10. Kesimpulan

Proses penalaan halus model ASR Whisper muncul sebagai teknik yang teguh untuk meningkatkan prestasinya. Penemuan utama:
  1. DeepL adalah yang paling mahir untuk terjemahan Cina ke Inggeris
  2. Penalaan halus secara konsisten menghasilkan peningkatan prestasi yang ketara (WER 7.33-12.15% untuk Vietnam, CER 8.15-17.93% untuk Jepun)
  3. Penambahan data melalui pustaka audiomentations memperkenalkan kepelbagaian yang berharga
  4. Kualiti set data penting: Jumlah data, kejelasan audio, dan kepelbagaian topik semua memberi kesan kepada prestasi
  5. Whisper menunjukkan prestasi unggul dalam senario dunia sebenar berbanding Azure pada data yang tidak dilihat

Rujukan

  1. Radford, A., et al. (2022). Robust speech recognition via large-scale weak supervision. arXiv:2212.04356
  2. Ardila, R., et al. (2020). Common Voice: A Massively-Multilingual Speech Corpus. arXiv:1912.06670
  3. Conneau, A., et al. (2022). FLEURS: Few-Shot Learning Evaluation of Universal Representations of Speech. arXiv:2205.12446
  4. Gandhi, S. (2022). Fine-Tune Whisper for Multilingual ASR with Transformers. Hugging Face Blog
  5. Mangrulkar, S. & Paul, S. Parameter-Efficient Fine-Tuning Using PEFT. Hugging Face Blog