Avatar
Ba
Thuật toán tách token WordPiece

Thuật toán tách token WordPiece


Trong bài trước chúng ta đã cùng thảo luận thuật toán token BPE - sử dụng tần suất xuất hiện của những cặp ký tự để xây dựng từ điển. Xem chi tiết thêm tại đây.

Hôm nay chúng ta sẽ cùng nghiên cứu một thuật toán có tên WordPiece. Một mô hình rất nổi tiếng dùng thuật toán này đó chính là BERT - Bidirectional Encoder Representations from Transformers.

1) Tách từ thành các ký tự

Ví dụ trong mô hình Bert, một từ "ProtonX" sẽ được tách thành các ký tự và thêm ## vào phía trước

Ví dụ

Đầu vào:

ProtonX

Đầu ra:

P ##r ##o ##t ##o ##n ##X

Chú ý: Chỉ riêng từ ở đầu là không thêm "##"

2) Điểm khác biệt với thuật toán BPE

Thuật toán BPE đếm số cặp hai token xuất hiện liền nhau và lưu token hợp của chúng vào trong từ điển. Thuật toán WordPiece cũng đếm tuy nhiên thay vì chỉ lựa chọn cặp token xuất hiện nhiều nhất, thuật toán này sẽ thêm yếu tố tần suất của từng ký tự trong cặp này.

Công thức sẽ như sau:

Điểm (score) = (Số lần xuất hiện của cặp token) / (Số lần xuất hiện của token 1 x Số lần xuất hiện của token 2)

Các cặp token có điểm càng cao sẽ ưu tiên hợp (merge) trước.

Ý nghĩa của việc này là gì nhỉ?

Khi nhìn vào công thức chúng ta sẽ thấy nếu chúng ta có hai cặp token:

  • Cặp 1: "g ##a"

  • Cặp 2: "g #ấu"

Nếu số lượng xuất hiện của cả hai cặp này tuơng đương nhau, bộ học token (Token learner) sẽ ưu tiên cặp "g ##ấu" hơn vì token "##ấu" trong cặp này sẽ xuất hiện ít hơn nhiều so với token "##a" trong cặp "g ##a". Cả hai cặp token cùng chung token đầu "g".

Thậm chí cặp 1 cũng không cần hợp vì đơn giản là hai token xuất hiện rất nhiều trong bộ từ điển.

3) Thuật toán

3.1) Ví dụ đơn giản

Ngữ liệu:

5 g ##a 
6 g ##ấ ##u
8 g ##a ##n
7 g ##ấ ##m 
3 h ##a

Từ điển

'##a', '##m', '##n', '##u', '##ấ', 'g', 'h'

Trong ngữ liệu này:

  • Token "g" xuất hiện 5 + 6 + 7 + 8 = 26 lần

  • Token "##a" xuất hiện 5 + 8 + 3 = 16 lần

  • Token "##ấ" xuất hiện 6 + 7 = 13 lần

  • Cặp token "g ##a" xuất hiện 5 + 8 = 13 lần

  • Cặp token "g ##ấ" xuất hiện 6 + 7 = 13 lần

Điểm của cặp "g ##a" = (Số lần xuất hiện của cặp "g ##a") / (Số lần xuất hiện của token "g" x Số lần xuất hiện của token "##a") = 13 / (26 x 16) = 0.03125

Điểm của cặp "g ##ấ" = (Số lần xuất hiện của cặp "g ##ấ") / (Số lần xuất hiện của token "g" x Số lần xuất hiện của token "##ấ") = 13 / (26 x 13) = 0.0385

Trong trường hợp này điểm của cặp "g ##ấ" lớn hơn nên sẽ ưu tiên hợp cặp này vào từ điển hơn.

3.2) Cách hợp

  • Nếu ta hợp "g" và "##ấ" ta sẽ bỏ "##" trước "##ấ" ta sẽ có "gấ"

  • Nếu ta hợp "##ấ" và "##m" ta sẽ bỏ "##" trước "##m" ta sẽ có "##ấm"

Sau đó token hợp này sẽ được thêm vào từ điển.

3.3) Ví dụ phức tạp

3.3.1) Tiến hành đếm

Ngữ liệu có 2 câu:

"ProtonX là một công ty AI",
"ProtonX là một nơi ươm mầm tài năng AI"

Bộ đếm

'ProtonX': 2,
'là': 2,
'một': 2,
'công': 1,
'ty': 1,
'AI': 2,
'nơi': 1,
'ươm': 1,
'mầm': 1,
'tài': 1,
'năng': 1
  • Những ký tự đứng đầu câu thì không thêm '##'

  • Những ký tự đứng sau ký tự đầu đều thêm '##' vào phía trước

Ví dụ với từ "ProtonX" ta có kết quả như sau

'ProtonX': ['P', '##r', '##o', '##t', '##o', '##n', '##X']

Kết quả ta có trên cả hai câu như sau:

['##I', '##X', '##g', '##i', '##m', '##n', '##o', '##r', '##t', '##y', '##à', '##ô', '##ă', '##ơ', '##ầ', '##ộ', 'A', 'P', 'c', 'l', 'm', 'n', 't', 'ư']

Ta bắt đầu đi tính điểm cho các cặp token cạnh nhau trong cách từ

('P', '##r'): 0.5
('##r', '##o'): 0.25
('##o', '##t'): 0.125
('##t', '##o'): 0.125
('##o', '##n'): 0.125
('##n', '##X'): 0.25
('l', '##à'): 0.3333333333333333
('m', '##ộ'): 0.3333333333333333
('##ộ', '##t'): 0.25
('c', '##ô'): 1.0
('##ô', '##n'): 0.25
('##n', '##g'): 0.25
('t', '##y'): 0.5
('A', '##I'): 0.5
('n', '##ơ'): 0.25
('##ơ', '##i'): 0.25
('ư', '##ơ'): 0.5
('##ơ', '##m'): 0.25
('m', '##ầ'): 0.3333333333333333
('##ầ', '##m'): 0.5
('t', '##à'): 0.16666666666666666
('##à', '##i'): 0.16666666666666666
('n', '##ă'): 0.5
('##ă', '##n'): 0.25

Cặp token

('c', '##ô'): 1.0

có điểm cao nhất hơn hẳn cặp ('A', '##I') mặc dù cặp AI xuất hiện hai lần trong ngữ liệu nhưng chỉ có điểm là (2) / (2 x 2) = 0.5

Điểm thấp nhất là 3 cặp

('##o', '##t'): 0.125
('##t', '##o'): 0.125
('##o', '##n'): 0.125

Ví dụ cặp ('##o', '##t') có điểm (2) / (4 x 4) = 0.125

3.3.2) Tiến hành hợp và thêm vào từ điển

Cặp ('c', '##ô') được hợp thành "cô" và thêm vào từ điển.

Từ "công" sẽ được biểu diễn như sau sau lần hợp này:

'công': ['cô', '##n', '##g']

Sau một số lượng vòng lặp cài đặt sẵn ta sẽ thu được bộ từ điển sau:

['##I', '##X', '##g', '##i', '##m', '##n', '##o', '##r', '##t', '##y', '##à', '##ô', '##ă', '##ơ', '##ầ', '##ộ', 'A', 'P', 'c', 'l', 'm', 'n', 't', 'ư', 'cô', 'Pr', 'ty', 'AI', 'ươ', 'nơ', 'nă', 'nơi', 'ươm', '##ầm', 'là', 'tà', 'tài', 'mộ', 'mầm', 'Pro', 'Prot', 'Proto', 'một', 'Proton', 'ProtonX', 'côn', 'năn', 'công', 'năng'] 

4) Quá trình mã hóa (encode)

Với bộ từ điển trên thì với đầu vào câu:

"Thả tym cho ProtonX nào"

sau khi tách token sẽ có kết quả là

['[UNK]', 'ty', '##m', '[UNK]', 'ProtonX', 'n', '##à', '##o']
  • Từ "Thả" tính từ đầu (cố định vị trí đầu) đến cuối không chứa bất kỳ từ con (subword) nào nằm bên trong từ điển nên sẽ được kết luận là từ không biết với token "[UNK]".

    • Cách lặp

      • "T" không nằm trong từ điển

      • "Th" không nằm trong từ điển

      • "Thả" không nằm trong từ điển

    • Cho nên kết luận "Thả" là "[UNK]"

  • Từ "tym" được tách thành token "ty" và "##m"

    • Từ đầu đến "y" từ "ty" là một token nằm trong từ điển. Tiến hành tách khỏi từ ban đầu ra thành "ty" và phần còn lại là "m". Thêm "##" vào "m" thành "##m" và tiếp tục tách.

    • "##m" nằm trong từ điển và tách thành chính nó.

Vậy cách mã hóa ở đây sẽ là gì?

  • Chúng ta sẽ đặt mốc cố định là đầu chuỗi, tìm xem từ đầu đến vị trí nào chứa token dài nhất trong vocab thì ta bắt đầu tách token. Phần đằng sau sẽ thêm "##" vào phía trước.

  • Tiếp tục tách phần sau.

  • Trường hợp nào từ đầu đến đuôi của phần chuỗi đang làm việc không hề nằm trong từ điển, trả về token [UNK]

Trên đây team đã trình bày đầu đủ thuật toán WordPiece. Một trong những thuật toán tách từ quan trọng.

Hẹn gặp lại bạn tại những bài viết tiếp theo trong chuỗi bài viết về thuật toán tách từ.