Skip to content
tinAI
Go back

Công cụ dạy phát âm Tiếng Quan Thoại với 9 triệu tham số

Bài gốc: A 9M-parameter Mandarin pronunciation tutor

Tác giả: Unknown

Ngày đăng: Dịch ngày:

TL;DR

Phát âm Tiếng Quan Thoại không dễ, vì thế tôi đã sử dụng 300 giờ ghi âm để huấn luyện một mô hình nhỏ với CTC nhằm chấm điểm phát âm của mình. Bạn có thể thử qua trình duyệt với tải trọng chỉ ~13MB.

Công cụ dạy phát âm Tiếng Quan Thoại với 9 triệu tham số

Giới thiệu

Trong bài viết trước về Langseed, tôi đã giới thiệu một nền tảng để định nghĩa từ chỉ sử dụng từ vựng mà tôi đã thành thạo. Mặc dù từ vựng của tôi đã phát triển, người đối diện vẫn thấy khó hiểu điều tôi nói.

Vấn đề chính là ở chỗ âm điệu. Chúng khá xa lạ với tôi, và tôi không giỏi trong việc nhận ra lỗi của mình - điều này thực sự khó chịu khi không có giáo viên hướng dẫn.

Nỗ lực đầu tiên: Hình ảnh hóa âm điệu

Lúc đầu, tôi định xây dựng một công cụ hình ảnh hóa âm điệu: chia âm thanh đầu vào thành từng phần nhỏ, chạy FFT, trích xuất âm điệu chính theo thời gian, và ánh xạ nó bằng một thuật toán dựa trên năng lượng giống như Praat.

Nhưng cách tiếp cận này nhanh chóng trở nên kém hiệu quả do nhiều trường hợp đặc biệt như tiếng ồn nền, sự biến đổi đồng thoại, và sự khác biệt giữa người nói.

Thay vào đó, tôi quyết định xây dựng một hệ thống Computer-Assisted Pronunciation Training (CAPT) dựa trên học sâu hoàn toàn có thể chạy trên thiết bị. Các API thương mại cũng có khả năng này, nhưng tự mình làm sẽ thú vị hơn nhiều.

Kiến trúc

Tôi coi đây là một nhiệm vụ Nhận diện Giọng nói Tự động (ASR) chuyên biệt. Thay vì chỉ dịch âm thanh thành văn bản, mô hình cần phải nắm bắt cách phát âm một cách chi tiết.

Tôi đã chọn Conformer encoder được huấn luyện với CTC (Connectionist Temporal Classification) loss.

Tại sao chọn Conformer?

Speech có các đặc điểm cần cả mẫu hình cục bộ và toàn cục:

Conformers kết hợp cả hai: convolution cho chi tiết cục bộ, attention cho cấu trúc tổng thể.

Tại sao chọn CTC?

Hầu hết các mô hình ASR hiện đại (như Whisper) là sequence-to-sequence: chúng chuyển âm thanh thành văn bản có khả năng xảy ra nhất. Đây là lợi thế cho việc dịch văn bản, nhưng là một nhược điểm cho việc học ngôn ngữ.

CTC hoạt động khác biệt. Nó đưa ra phân phối xác suất cho mọi khung âm thanh. Để xử lý căn chỉnh, nó đưa vào một token <blank> đặc biệt.

Ví dụ, nếu âm thanh là “hello”, dữ liệu thô có thể trông như thế này:

h h h <blank> e e <blank> l l l l <blank> l l o o o

Căn chỉnh bắt buộc: biết khi nào bạn đã nói gì

CTC cho biết điều gì đã được nói, nhưng không biết chính xác khi nào.

Một đoạn clip 3 giây có thể có ma trận với ~150 bước thời gian, mỗi bước chứa xác suất cho tất cả các token. Đa phần ma trận này chỉ là <blank>.

Để tìm đường đi tối ưu qua ma trận này, tôi đã sử dụng Viterbi algorithm với lập trình động, nhằm tối đa hóa xác suất tổng.

Phân loại: Pinyin và âm sắc như các token chính

Hầu hết các hệ thống ASR Tiếng Quan Thoại xuất ra Hán tự, điều này che giấu lỗi phát âm. Thay vào đó, tôi đã tạo ra một token cho mỗi âm tiết Pinyin + âm điệu.

Tôi cũng chuẩn hóa âm trung tính bằng cách ép nó thành âm điệu 5 (ma5). Điều này dẫn đến một từ vựng gồm 1.254 tokens, cùng với <unk><blank>.

Huấn luyện

Tôi đã kết hợp các tập dữ liệu AISHELL-1Primewords (~300 giờ), tăng cường bằng SpecAugment. Huấn luyện trên 4× NVIDIA GeForce RTX 4090 chỉ mất khoảng 8 giờ.

  1. TER (Tỷ lệ lỗi Token): độ chính xác tổng thể.
  2. Tone Accuracy: độ chính xác của các âm điệu từ 1 đến 5.
  3. Confusion Groups: lỗi giữa các cặp âm khó như zh/ch/sh và z/c/s.

Thu nhỏ mô hình

Ban đầu, tôi bắt đầu với một mô hình “trung bình” (~75M tham số). Tuy nhiên, tôi muốn một cái gì đó có thể chạy trên trình duyệt hoặc điện thoại mà không hao pin.

Kết quả là, mô hình 9M tham số chỉ tệ hơn một chút, cho thấy rằng nhiệm vụ này phụ thuộc vào dữ liệu hơn là khả năng tính toán.

Mô hình FP32 ban đầu khoảng ~37 MB. Sau khi lượng tử hóa INT8, nó thu nhỏ còn ~11 MB với sự giảm chính xác không đáng kể.

Lỗi căn chỉnh: sự im lặng phá hỏng mọi thứ

Một lỗi phổ biến là sự im lặng dẫn đầu. Ví dụ, khi tôi ghi âm “我喜欢…” và tạm dừng một giây trước khi nói, mô hình chắc chắn rằng âm tiết đầu tiên của tôi là sai. Tại sao? Sự căn chỉnh đã gán các khung im lặng cho wo3, khiến xác suất <blank> lấn át wo3.

Cách sửa lỗi

Tôi đã tách biệt UI spans (những gì được đánh dấu) khỏi scoring frames (những gì ảnh hưởng đến điểm số tự tin). Chúng tôi đơn giản bỏ qua các khung nơi mô hình chắc chắn rằng nó đang thấy im lặng.

def _filter_nonblank_frames(span_logp: torch.Tensor, blank_id: int = 0, thr: float = 0.7):
    """
    Chỉ giữ các khung mà xác suất của <blank> dưới ngưỡng.
    Nếu chúng tôi lọc mọi thứ (hoàn toàn im lặng), chúng tôi quay lại để tính điểm toàn bộ khoảng cách.
    """
    p_blank = span_logp[:, blank_id].exp()
    keep = p_blank < thr
    if keep.any():
        return span_logp[keep]
    return span_logp  # Quay lại

Kết luận

Hiện tại, tôi cảm thấy phát âm của mình đang cải thiện đáng kể trong giai đoạn thử nghiệm này. Hệ thống rất nghiêm khắc và không thỏa hiệp, đúng như tôi cần.

Bạn có thể thử bản demo ngay đây. Nó chạy hoàn toàn trong trình duyệt và dung lượng tải xuống chỉ ~13MB.


Read Original (EN) Quay lại Newsletter