Bài viết này sẽ giúp bạn hiểu về tokenization - một khái niệm nền tảng trong NLP. Đầu tiên, ta sẽ tìm hiểu cách AI chuyển đổi văn bản thành dạng số để có thể xử lý, cùng với các kỹ thuật phổ biến như Stemming, Lemmatization, và Tokenization. Sau đó, ta sẽ tìm hiểu cách các mô hình như GPT-2 và GPT-4 thực hiện tokenization. Cuối cùng, ta sẽ so sánh tokenization giữa các ngôn ngữ khác nhau.

Mục tiêu bài viết

1

Hiểu ngôn ngữ tự nhiên

Hiểu được cách AI xử lý và “hiểu” ngôn ngữ tự nhiên

2

Phương pháp tokenization

Nắm được sự khác biệt giữa các phương pháp tokenization khác nhau

3

Ưu nhược điểm

Hiểu được ưu nhược điểm của từng phương pháp tokenization

4

Mô hình AI

Biết cách các mô hình như GPT-2 và GPT-4 thực hiện tokenization

5

Ngôn ngữ khác nhau

Hiểu được cách tokenization hoạt động với các ngôn ngữ khác nhau


1. Làm thế nào để AI hiểu được ngôn ngữ tự nhiên?

Đầu tiên hãy tìm hiểu xem làm thế nào mà AI có thể hiểu được ngôn ngữ tự nhiên.

Nhìn vào hình trên ta thấy Language Model (LM) không thể hiểu được ngôn ngữ tự nhiên như con người. Vậy nên, ta cần phải chuyển đổi ngôn ngữ tự nhiên thành .

Thông thường khi làm việc với data dạng text, bước đầu tiên ta sẽ tạo một bộ từ điển (vocabulary) chứa tất cả các từ không trùng lặp trong dataset. Sau đó, ta sẽ gán cho mỗi từ một số nguyên duy nhất.

Ví dụ trong hình trên, từ This được gán số 40134, từ is được gán số 2052, và cứ thế. Với cách làm này, mỗi câu văn bản sẽ được biểu diễn thành một chuỗi các số nguyên tương ứng với các từ trong câu đó.

Tuy nhiên, cách tiếp cận này có một số hạn chế đáng kể:

  1. Phân biệt chữ hoa/thường: Các từ giống nhau nhưng khác về chữ hoa/thường (như Thisthis) sẽ được xem là hai từ khác nhau và được gán hai số khác nhau, dù về mặt ngữ nghĩa chúng giống nhau.

  2. Dư thừa bộ nhớ: Khi text có nhiều từ trùng lặp, việc lưu trữ số mapping cho mỗi lần xuất hiện là không hiệu quả về mặt bộ nhớ.

  3. Mất thông tin ngữ cảnh: Cách biểu diễn này không thể phân biệt được thứ tự của các từ trong câu. Ví dụ: tôi thích bạnbạn thích tôi sẽ có cùng tập hợp các số, mặc dù ý nghĩa hoàn toàn khác nhau.

GPTForWork - Tokenizer

Các bạn có thể vào trang web https://gptforwork.com/tools/tokenizer để xem cách tokenizer của các mô hình khác nhau tokenize cùng một câu.

Để khắc phục những hạn chế này, một cải tiến là sử dụng vector 2 chiều để biểu diễn mỗi từ thay vì một số đơn lẻ.

-> Bằng cách này, ta có thể biểu diễn các từ trong không gian 2 chiều, cho phép mô tả được nhiều đặc trưng và mối quan hệ phức tạp hơn giữa các từ.

Trong ví dụ trên, ta đã sử dụng 1 vector có 2 chiều để biểu diễn 1 từ. Ví dụ:

  • Nếu xét về khía cạnh Animal, các từ như Black CatGolden Retriever sẽ nằm gần nhau trong không gian vì chúng đều là động vật, trong khi Yellow Car sẽ nằm xa hơn vì không phải động vật.

  • Ngược lại, nếu xét về khía cạnh Color, các từ như Golden RetrieverYellow Car sẽ nằm gần nhau vì chúng có màu sắc tương tự (vàng), trong khi Black Cat sẽ nằm xa hơn vì có màu đen.

Như vậy, chỉ với 2 câu hỏi (hay 2 góc nhìn) được đặt ra thì không gian 2 chiều đã không thể thể hiện được các mối quan hệ phức tạp giữa các từ. Để biểu diễn đầy đủ các đặc trưng ngữ nghĩa phức tạp của từ như loài vật, màu sắc, kích thước, v.v., ta cần sử dụng không gian nhiều chiều hơn.

Số chiều của không gian biểu diễn từ (word embedding dimension) phụ thuộc vào độ phức tạp và kích thước của model. Ví dụ:

  • Các model Transformer cỡ trung bình (vài trăm triệu tham số) thường sử dụng:

    • 768 chiều (BERT base)
    • 1024 chiều (BERT large)
    • 768 chiều (GPT-2)
  • Các model lớn hơn cần số chiều cao hơn để nắm bắt được nhiều đặc trưng phức tạp hơn. Ví dụ GPT-3 với 175 tỷ tham số sử dụng tới 12288 chiều.

Việc tăng số chiều giúp model có thể biểu diễn được nhiều mối quan hệ và đặc trưng ngữ nghĩa phức tạp hơn giữa các từ, từ đó cải thiện khả năng hiểu ngôn ngữ tự nhiên. Đánh đổi lại, việc tăng số chiều cũng làm tăng đáng kể kích thước của model, từ đó làm tăng thời gian train và inference.

2. Stemming vs. Lemmatization vs. Tokenization

Ok, giờ ta đã biết được là ta cần biểu diễn các từ trong không gian nhiều chiều. Tiếp theo, ta sẽ quay lại tìm hiểu xem làm thế nào để chuyển đổi các văn bản thành các trước khi chuyển đổi chúng thành các vector nhiều chiều.

Trong quá trình này, ta sẽ tìm hiểu về Stemming, Lemmatization và Tokenization, đây là 3 kỹ thuật phổ biến để chuyển đổi các văn bản thành các token.

2.1 Stemming vs Lemmatization

Stemming và Lemmatization là 2 kỹ thuật để đưa các từ về dạng cơ bản nhất của chúng. Tuy nhiên, chúng có cách tiếp cận khác nhau.

Hình ảnh so sánh Stemming và Lemmatization.

Stemming

  • Là một kỹ thuật cắt bỏ phần đuôi hoặc tiền tố của từ một cách tự động nhằm xác định gốc từ.
  • Ví dụ:
    • running -> run
    • fishing -> fish
    • studies -> studi
  • Ưu điểm: Đơn giản và nhanh chóng.
  • Nhược điểm: Có thể tạo ra từ không có nghĩa hoặc sai nghĩa, dẫn đến hiểu lầm trong ngữ cảnh.

Lemmatization

  • Là một kỹ thuật chuyển đổi từ về dạng nguyên mẫu (lemma) dựa trên từ điển và ngữ cảnh ngữ pháp.
  • Ví dụ:
    • am, are, is -> be
    • better, best -> good
    • studies, studying -> study
  • Ưu điểm: Kết quả chính xác và có nghĩa, giúp duy trì ngữ cảnh.
  • Nhược điểm: Chậm hơn và yêu cầu từ điển để thực hiện.

Cả hai kỹ thuật này đều có những hạn chế và không hoàn toàn phù hợp trong các bài toán liên quan đến ngữ pháp và ngữ nghĩa.

2.2 Tokenization

Tokenization là quá trình chia văn bản thành các đơn vị nhỏ hơn gọi là token. Có nhiều phương pháp khác nhau để thực hiện điều này.

https://mlarchive.com/natural-language-processing/tokenization-the-cornerstone-for-nlp-tasks/

  1. Word-based Tokenization
  • Chia văn bản thành các từ dựa trên khoảng trắng và dấu câu.
  • Ví dụ: I love coding! -> I, love, coding, !
  1. Character-based Tokenization
  • Chia văn bản thành từng ký tự.
  • Ví dụ: Hello -> H, e, l, l, o
  1. Subword Tokenization
  • Chia văn bản thành các phần nhỏ hơn từ nhưng lớn hơn ký tự, giúp cải thiện khả năng xử lý ngôn ngữ tự nhiên.
  • Ví dụ: unhappy -> un, happy
  1. Byte-Pair Encoding (BPE)
  • Phương pháp tokenization xác định các cặp ký tự liên tiếp xuất hiện thường xuyên nhất trong văn bản để tạo ra các token mới. BPE tạo ra các token nhỏ hơn nhưng vẫn giữ nghĩa của từ.
  • Ví dụ:
    • unhappy -> un, happy
    • internationally -> international, ly
    • seamlessly -> se, am, lessly
    • tokenizer -> token, izer
  • BPE được sử dụng rộng rãi trong các mô hình Transformer như GPT-2, GPT-3, RoBERTa, BART, và DeBERTa để cải thiện khả năng xử lý ngôn ngữ tự nhiên, tạo ra từ vựng phong phú hơn và giảm số lượng token không xác định.

Ví dụ về thuật toán BPE với câu sau:

We propose a new simple network

Trong thực tế, ta sẽ dùng một lượng lớn data để train BPE tokenizer và data này có thể khác với data sử dụng để train model LM hay LLM. Data này chỉ để train tokenizer.

1

Bước 1: Pre-tokenization

Tách câu thành các từ và thêm ký tự (space) vào cuối mỗi từ

We
propose
a
new
simple
network
2

Bước 2: Tạo từ điển ban đầu

  • Tách mỗi từ thành các ký tự riêng lẻ để tạo từ điển cơ sở:
initial_vocab: {
 'W', 'e', 'p', 'r', 'o', 's',
 'a', 'n', 'w', 'i', 'm', 'l',
 't', 'h', 'f', 'c', 'v', 'u',
 'd', 'g', ' '
}
3

Bước 3: Tìm và gộp cặp ký tự xuất hiện nhiều nhất

Lặp lại các bước sau cho đến khi đạt số lượng vocabulary mong muốn:

  • 3.1 Đếm tần suất xuất hiện của các cặp ký tự liền kề
  • 3.2 Chọn cặp có tần suất cao nhất
  • 3.3 Gộp cặp đó thành một token mới
  • 3.4 Cập nhật từ điển và dữ liệu
  • 3.5 Tiếp tục đếm chọn cặp ký tự liền kề có tần suất cao nhất và thêm token mới vào từ điển cho đến khi đạt số lượng vocabulary mong muốn.

Ví dụ:

# Bước 3.1: Đếm tần suất
pairs: {
  ('e', ' '): 3,  # từ "We", "propose", "simple"
  (' ', 'n'): 2,  # từ "new", "network"
  ('n', 'e'): 2,  # từ "new", "network"
  ('W', 'e'): 1,  # từ "We"
  (' ', 'p'): 1,  # từ "propose"
  ('p', 'r'): 1,  # từ "propose"
  ('r', 'o'): 1,  # từ "propose"
  ('o', 'p'): 1,  # từ "propose"
  ('p', 'o'): 1,  # từ "propose"
  ...
}


# Bước 3.2 & 3.3: Tạo token mới

new_token: 'e '

# Cập nhật từ điển
vocab: {
'W', 'e', 'p', 'r', 'o', 's',
'a', 'n', 'w', 'i', 'm', 'l',
't', 'h', 'f', 'c', 'v', 'u',
'd', 'g', ' ', 'e ' # new token
}

# Bước 3.5: Tiếp tục đếm chọn cặp ký tự liền kề có tần suất cao nhất và thêm token mới vào từ điển cho đến khi đạt số lượng vocabulary mong muốn.

Mỗi phương pháp tokenization có ưu điểm và nhược điểm riêng, và việc lựa chọn phương pháp phù hợp phụ thuộc vào yêu cầu cụ thể của bài toán xử lý ngôn ngữ tự nhiên.

Phương phápMô tảƯu điểmNhược điểmVí dụ
Word-basedChia văn bản thành các từ dựa trên khoảng trắng và dấu câuĐơn giản, dễ hiểu. Phù hợp với ngôn ngữ có ranh giới từ rõ ràngKhông xử lý được OOV. Kích thước từ điển lớn"I love coding!"["I", "love", "coding", "!"]
Character-basedChia văn bản thành từng ký tự riêng lẻTừ điển nhỏ gọn. Không có vấn đề OOVMất thông tin ngữ nghĩa. Chuỗi đầu vào dài"Hello"["H", "e", "l", "l", "o"]
SubwordChia văn bản thành các phần nhỏ hơn từ nhưng lớn hơn ký tựCân bằng giữa word và character. Xử lý được từ ghépCó thể tạo ra các token không có nghĩa"unhappy"["un", "happy"]
BPEGộp các cặp ký tự xuất hiện thường xuyên thành token mớiHiệu quả với từ có cùng gốc/hậu tố. Tối ưu kích thước từ điểnCần training trên dữ liệu lớn. Phụ thuộc vào kích thước từ điển"internationally"["inter", "nat", "ion", "ally"]

2.3 So sánh Tokenization giữa GPT-2 và GPT-4

https://tiktokenizer.vercel.app/

Ok quan sát hình trên ta thấy sự khác biệt thú vị trong cách GPT-2 và GPT-4 tokenize cùng một đoạn văn bản:

  • GPT-2 sử dụng 114 token
  • GPT-4 sử dụng 89 token (sử dụng ít hơn khoảng 22% token cho cùng một nội dung)
  • GPT-4 group các token lại với nhau để tạo ra các token lớn hơn, giúp giảm số lượng token sử dụng, ví dụ token space được tạo ra từ (khoảng trắng)
  • GPT-2 sử dụng rất nhiều token space (khoảng trắng) khi coding, điều này dẫn đến việc lãng phí bộ nhớ và tăng thời gian xử lý. Đây cũng là lí do thường gian đầu GPT-2 coding rất tệ.

2.4 So sánh tokenization với các ngôn ngữ khác nhau

Ví dụ sau sử dụng tokenizer của GPT-4O để tokenize cùng một nội dung được viết bằng 3 ngôn ngữ khác nhau:

https://tiktokenizer.vercel.app/

  1. Tiếng Anh

    • Số token: 9
    • Tokenizer tách các từ một cách tự nhiên theo khoảng trắng
  2. Tiếng Việt

    • Số token: 15
    • Do đặc thù tiếng Việt, mỗi từ đơn thường được tokenize riêng biệt
    • Các dấu thanh và dấu phụ cũng ảnh hưởng đến việc tokenize
  3. Tiếng Nhật

    • Số token: 20
    • Tiếng Nhật có số token nhiều nhất do cách viết đặc biệt kết hợp Kanji, Hiragana và Katakana
    • Mỗi ký tự Kanji thường được xem như một token riêng biệt

Điều này cho thấy hiệu quả của tokenizer phụ thuộc rất nhiều vào đặc điểm của từng ngôn ngữ. Khi xây dựng mô hình cho các ngôn ngữ khác nhau, chúng ta cần chú ý đến sự khác biệt này để có thể tối ưu kích thước từ điển (vocabulary) và độ dài chuỗi token một cách phù hợp.


Như vậy, ta đã tìm hiểu xong cách tokenizer hoạt động. Trong phần tiếp theo, ta sẽ tìm hiểu về word embedding.