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
- Maklumat Latar Belakang
- Persediaan Persekitaran
- Muatkan Set Data
- Pra-pemprosesan Data
- Latihan
- Penalaan Halus Cekap Parameter
- Keputusan
- Penilaian
- Azure Speech Studio
- 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.
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:
- Pengekstrak ciri yang mengubah audio mentah kepada spektrogram log-Mel
- Encoder Transformer yang menjana urutan keadaan tersembunyi encoder
- 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 Data | Bahasa | Penggunaan | Audio Pertuturan (Jam) |
|---|
| Common Voice 13.0 | Vietnam, Jepun | Hugging Face | 19j (VN), 10j (JP) |
| Google Fleurs | Vietnam, Jepun | Hugging Face | 11j (VN), 8j (JP) |
| Vivos | Vietnam | Hugging Face | 15j |
| FPT Open Speech Dataset | Vietnam | Muat turun & ekstrak | 30j |
| VLSP2020 | Vietnam | Muat turun & ekstrak | 100j |
| ReazonSpeech | Jepun | Hugging Face | 5j |
| JSUT | Jepun | Muat turun & ekstrak | 10j |
| JVS | Jepun | Muat turun & ekstrak | 30j |
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 Halus | Penalaan Halus Cekap Parameter |
|---|
| Masa latihan lebih pantas | Masa latihan lebih lama |
| Memerlukan sumber pengiraan yang lebih besar | Menggunakan sumber pengiraan yang lebih sedikit |
| Melatih semula keseluruhan model | Mengubah suai hanya subset kecil parameter |
| Lebih cenderung kepada overfitting | Kurang 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
Model yang ditala halus pada set data FOSD + Google Fleurs + Vivos + CV mencapai WER terendah 9.46%.
Keputusan Jepun
Model yang ditala halus pada set data JSUT + ReazonSpeech + Google Xtreme + CV mencapai CER terendah 8.15%.
Keluk Kehilangan Pengoptimuman
8. Penilaian
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
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:
- DeepL adalah yang paling mahir untuk terjemahan Cina ke Inggeris
- Penalaan halus secara konsisten menghasilkan peningkatan prestasi yang ketara (WER 7.33-12.15% untuk Vietnam, CER 8.15-17.93% untuk Jepun)
- Penambahan data melalui pustaka audiomentations memperkenalkan kepelbagaian yang berharga
- Kualiti set data penting: Jumlah data, kejelasan audio, dan kepelbagaian topik semua memberi kesan kepada prestasi
- Whisper menunjukkan prestasi unggul dalam senario dunia sebenar berbanding Azure pada data yang tidak dilihat
Rujukan
- Radford, A., et al. (2022). Robust speech recognition via large-scale weak supervision. arXiv:2212.04356
- Ardila, R., et al. (2020). Common Voice: A Massively-Multilingual Speech Corpus. arXiv:1912.06670
- Conneau, A., et al. (2022). FLEURS: Few-Shot Learning Evaluation of Universal Representations of Speech. arXiv:2205.12446
- Gandhi, S. (2022). Fine-Tune Whisper for Multilingual ASR with Transformers. Hugging Face Blog
- Mangrulkar, S. & Paul, S. Parameter-Efficient Fine-Tuning Using PEFT. Hugging Face Blog