Transformers documentation
Nhận dạng giọng nói tự động
Nhận dạng giọng nói tự động
Nhận dạng giọng nói tự động (ASR) chuyển đổi tín hiệu giọng nói thành văn bản, ánh xạ một chuỗi đầu vào âm thanh sang đầu ra văn bản. Các trợ lý ảo như Siri và Alexa sử dụng các mô hình ASR để hỗ trợ người dùng mỗi ngày, và có nhiều ứng dụng hữu ích khác hướng đến người dùng như phụ đề trực tiếp và ghi chú trong các cuộc họp.
Hướng dẫn này sẽ cho bạn thấy cách:
- Tinh chỉnh Wav2Vec2 trên bộ dữ liệu MInDS-14 để chuyển đổi âm thanh thành văn bản.
- Sử dụng mô hình đã tinh chỉnh của bạn để suy luận.
Để xem tất cả các kiến trúc và checkpoint tương thích với tác vụ này, chúng tôi khuyến nghị bạn kiểm tra trang tác vụ
Trước khi bắt đầu, hãy đảm bảo bạn đã cài đặt tất cả các thư viện cần thiết:
pip install transformers datasets evaluate jiwer soundfile torchcodec
Chúng tôi khuyến khích bạn đăng nhập vào tài khoản Hugging Face của mình để có thể tải lên và chia sẻ mô hình của bạn với cộng đồng. Khi được yêu cầu, hãy nhập token của bạn để đăng nhập:
>>> from huggingface_hub import notebook_login
>>> notebook_login()Tải bộ dữ liệu MInDS-14
Bắt đầu bằng cách tải một tập con nhỏ hơn của bộ dữ liệu MInDS-14 từ thư viện 🤗 Datasets. Điều này sẽ cho bạn cơ hội thử nghiệm và đảm bảo mọi thứ hoạt động trước khi dành thêm thời gian huấn luyện trên toàn bộ bộ dữ liệu.
>>> from datasets import load_dataset, Audio
>>> minds = load_dataset("PolyAI/minds14", name="en-US", split="train[:100]")Chia split train của bộ dữ liệu thành tập train và tập test bằng phương thức ~Dataset.train_test_split:
>>> minds = minds.train_test_split(test_size=0.2)Sau đó, hãy xem xét bộ dữ liệu:
>>> minds
DatasetDict({
train: Dataset({
features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
num_rows: 16
})
test: Dataset({
features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
num_rows: 4
})
})Mặc dù tập dữ liệu chứa nhiều thông tin hữu ích, chẳng hạn như lang_id và english_transcription, hướng dẫn này tập trung vào audio và transcription. Hãy xóa các cột còn lại bằng phương thức remove_columns:
>>> minds = minds.remove_columns(["english_transcription", "intent_class", "lang_id"])Xem lại ví dụ một lần nữa:
>>> minds["train"][0]
{'audio': {'array': array([-0.00024414, 0. , 0. , ..., 0.00024414,
0.00024414, 0.00024414], dtype=float32),
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'sampling_rate': 8000},
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'transcription': "hi I'm trying to use the banking app on my phone and currently my checking and savings account balance is not refreshing"}Có hai trường:
audio: mộtarraymột chiều của tín hiệu giọng nói, phải được gọi để tải và lấy mẫu lại tệp âm thanh.transcription: văn bản đích.
Tiền xử lý
Bước tiếp theo là nạp một bộ xử lý Wav2Vec2 để xử lý tín hiệu âm thanh:
>>> from transformers import AutoProcessor
>>> processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base")Bộ dữ liệu MInDS-14 có tần số lấy mẫu là 8000Hz (bạn có thể tìm thấy thông tin này trong thẻ dữ liệu), điều này có nghĩa là bạn sẽ cần lấy mẫu lại bộ dữ liệu lên 16000Hz để sử dụng mô hình Wav2Vec2 được huấn luyện trước:
>>> minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
>>> minds["train"][0]
{'audio': {'array': array([-2.38064706e-04, -1.58618059e-04, -5.43987835e-06, ...,
2.78103951e-04, 2.38446111e-04, 1.18740834e-04], dtype=float32),
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'sampling_rate': 16000},
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602ba9e2963e11ccd901cd4f.wav',
'transcription': "hi I'm trying to use the banking app on my phone and currently my checking and savings account balance is not refreshing"}Như bạn có thể thấy trong transcription ở trên, văn bản chứa cả chữ hoa và chữ thường. Tokenizer Wav2Vec2 chỉ được huấn luyện trên các ký tự hoa nên bạn cần đảm bảo văn bản khớp với từ vựng của tokenizer:
>>> def uppercase(example):
... return {"transcription": example["transcription"].upper()}
>>> minds = minds.map(uppercase)Bây giờ hãy tạo một hàm tiền xử lý mà:
- Gọi cột
audiođể tải và lấy lại mẫu tệp âm thanh. - Trích xuất
input_valuestừ tệp âm thanh và mã hóa cộttranscriptionbằng bộ xử lý.
>>> def prepare_dataset(batch):
... audio = batch["audio"]
... batch = processor(audio["array"], sampling_rate=audio["sampling_rate"], text=batch["transcription"])
... batch["input_length"] = len(batch["input_values"][0])
... return batchĐể áp dụng hàm tiền xử lý lên toàn bộ bộ dữ liệu, hãy sử dụng hàm map của 🤗 Datasets. Bạn có thể tăng tốc map bằng cách tăng số lượng tiến trình với tham số num_proc. Xóa các cột không cần thiết bằng phương thức remove_columns:
>>> encoded_minds = minds.map(prepare_dataset, remove_columns=minds.column_names["train"], num_proc=4)🤗 Transformers không có data collator cho ASR, vì vậy bạn sẽ cần điều chỉnh DataCollatorWithPadding để tạo một batch các ví dụ. Nó cũng sẽ đệm động văn bản và nhãn của bạn đến độ dài của phần tử dài nhất trong batch của nó (thay vì toàn bộ dataset) để chúng có độ dài đồng nhất. Mặc dù có thể đệm văn bản của bạn trong hàm tokenizer bằng cách đặt padding=True, nhưng đệm động hiệu quả hơn.
Khác với các data collator khác, data collator cụ thể này cần áp dụng phương pháp padding khác nhau cho input_values và labels:
>>> import torch
>>> from dataclasses import dataclass, field
>>> from typing import Any, Dict, List, Optional, Union
>>> @dataclass
... class DataCollatorCTCWithPadding:
... processor: AutoProcessor
... padding: Union[bool, str] = "longest"
... def __call__(self, features: list[dict[str, Union[list[int], torch.Tensor]]]) -> dict[str, torch.Tensor]:
... # split inputs and labels since they have to be of different lengths and need
... # different padding methods
... input_features = [{"input_values": feature["input_values"][0]} for feature in features]
... label_features = [{"input_ids": feature["labels"]} for feature in features]
... batch = self.processor.pad(input_features, padding=self.padding, return_tensors="pt")
... labels_batch = self.processor.pad(labels=label_features, padding=self.padding, return_tensors="pt")
... # replace padding with -100 to ignore loss correctly
... labels = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100)
... batch["labels"] = labels
... return batchBây giờ khởi tạo DataCollatorCTCWithPadding của bạn:
>>> data_collator = DataCollatorCTCWithPadding(processor=processor, padding="longest")Đánh giá
Việc đưa một chỉ số vào trong quá trình huấn luyện thường hữu ích để đánh giá hiệu suất của mô hình. Bạn có thể nhanh chóng tải một phương pháp đánh giá bằng thư viện 🤗 Evaluate. Đối với tác vụ này, hãy tải chỉ số word error rate (WER) (xem 🤗 Evaluate quick tour để tìm hiểu thêm về việc tải và tính toán các chỉ số):
>>> import evaluate
>>> wer = evaluate.load("wer")Sau đó, tạo một hàm truyền các dự đoán và nhãn của bạn vào compute để tính WER:
>>> import numpy as np
>>> def compute_metrics(pred):
... pred_logits = pred.predictions
... pred_ids = np.argmax(pred_logits, axis=-1)
... pred.label_ids[pred.label_ids == -100] = processor.tokenizer.pad_token_id
... pred_str = processor.batch_decode(pred_ids)
... label_str = processor.batch_decode(pred.label_ids, group_tokens=False)
... wer_score = wer.compute(predictions=pred_str, references=label_str)
... return {"wer": wer_score}Hàm compute_metrics của bạn đã sẵn sàng, và bạn sẽ quay lại với nó khi thiết lập quá trình huấn luyện.
Huấn luyện
Nếu bạn chưa quen với việc tinh chỉnh mô hình bằng Trainer, hãy xem hướng dẫn cơ bản tại đây!
Bạn đã sẵn sàng để bắt đầu huấn luyện mô hình của mình! Nạp Wav2Vec2 bằng AutoModelForCTC. Chỉ định phép giảm cần áp dụng bằng tham số ctc_loss_reduction. Thường thì tốt hơn là dùng trung bình thay vì phép cộng mặc định:
>>> from transformers import AutoModelForCTC, TrainingArguments, Trainer
>>> model = AutoModelForCTC.from_pretrained(
... "facebook/wav2vec2-base",
... ctc_loss_reduction="mean",
... pad_token_id=processor.tokenizer.pad_token_id,
... )Tới bước này, chỉ còn ba bước nữa:
- Định nghĩa các siêu tham số huấn luyện của bạn trong TrainingArguments. Tham số bắt buộc duy nhất là
output_dir, chỉ định nơi lưu trữ mô hình của bạn. Bạn sẽ đẩy mô hình này lên Hub bằng cách đặtpush_to_hub=True(bạn cần đăng nhập vào Hugging Face để tải lên mô hình). Vào cuối mỗi epoch, Trainer sẽ đánh giá WER và lưu checkpoint huấn luyện. - Truyền các đối số huấn luyện vào Trainer cùng với mô hình, tập dữ liệu, tokenizer, data collator và hàm
compute_metrics. - Gọi train() để tinh chỉnh mô hình của bạn.
>>> training_args = TrainingArguments(
... output_dir="my_awesome_asr_mind_model",
... per_device_train_batch_size=8,
... gradient_accumulation_steps=2,
... learning_rate=1e-5,
... warmup_steps=500,
... max_steps=2000,
... gradient_checkpointing=True,
... fp16=True,
... train_sampling_strategy="group_by_length",
... eval_strategy="steps",
... per_device_eval_batch_size=8,
... save_steps=1000,
... eval_steps=1000,
... logging_steps=25,
... load_best_model_at_end=True,
... metric_for_best_model="wer",
... greater_is_better=False,
... push_to_hub=True,
... report_to="trackio",
... )
>>> trainer = Trainer(
... model=model,
... args=training_args,
... train_dataset=encoded_minds["train"],
... eval_dataset=encoded_minds["test"],
... processing_class=processor,
... data_collator=data_collator,
... compute_metrics=compute_metrics,
... )
>>> trainer.train()Khi quá trình huấn luyện hoàn tất, hãy chia sẻ mô hình của bạn lên Hub bằng phương thức push_to_hub() để mọi người có thể truy cập:
>>> trainer.push_to_hub()Để có một ví dụ chi tiết hơn về cách tinh chỉnh một mô hình cho nhận dạng giọng nói tự động, hãy xem bài đăng này cho ASR tiếng Anh và bài đăng này cho ASR đa ngôn ngữ.
Suy luận
Tuyệt, giờ đây bạn đã tinh chỉnh xong một mô hình, bạn có thể sử dụng nó để suy luận!
Nạp tệp âm thanh mà bạn muốn chạy suy luận. Hãy nhớ lấy mẫu lại tần số lấy mẫu của tệp âm thanh cho khớp với tần số lấy mẫu của mô hình nếu cần!
>>> from datasets import load_dataset, Audio
>>> dataset = load_dataset("PolyAI/minds14", "en-US", split="train")
>>> dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
>>> sampling_rate = dataset.features["audio"].sampling_rate
>>> audio_file = dataset[0]["audio"]["path"]Cách đơn giản nhất để thử nghiệm mô hình đã tinh chỉnh của bạn cho suy luận là sử dụng nó trong một pipeline(). Khởi tạo một pipeline cho nhận dạng giọng nói tự động với mô hình của bạn, và truyền tệp âm thanh của bạn vào đó:
>>> from transformers import pipeline
>>> transcriber = pipeline("automatic-speech-recognition", model="stevhliu/my_awesome_asr_minds_model")
>>> transcriber(audio_file)
{'text': 'I WOUD LIKE O SET UP JOINT ACOUNT WTH Y PARTNER'}Việc chuyển văn bản thành chữ khá ổn, nhưng có thể tốt hơn! Hãy thử tinh chỉnh mô hình của bạn trên nhiều ví dụ hơn để đạt được kết quả tốt hơn nữa!
Bạn cũng có thể tự động tái tạo kết quả của pipeline nếu muốn:
Tải một processor để tiền xử lý tệp âm thanh và bản ghi âm, sau đó trả về input dưới dạng tensor PyTorch:
>>> from transformers import AutoProcessor
>>> processor = AutoProcessor.from_pretrained("stevhliu/my_awesome_asr_mind_model")
>>> inputs = processor(dataset[0]["audio"]["array"], sampling_rate=sampling_rate, return_tensors="pt")Truyền các đầu vào của bạn vào mô hình và trả về logits:
>>> from transformers import AutoModelForCTC
>>> model = AutoModelForCTC.from_pretrained("stevhliu/my_awesome_asr_mind_model")
>>> with torch.no_grad():
... logits = model(**inputs).logitsLấy input_ids dự đoán có xác suất cao nhất, và sử dụng processor để giải mã input_ids dự đoán trở lại thành văn bản:
>>> import torch
>>> predicted_ids = torch.argmax(logits, dim=-1)
>>> transcription = processor.batch_decode(predicted_ids)
>>> transcription
['I WOUL LIKE O SET UP JOINT ACOUNT WTH Y PARTNER']