[NLP Series #3] Lảm nhảm cuối tuần về biểu diễn văn bản bằng trong học máy (1/2)

Hi anh em, hôm nay mình xin được nói một chút lý thuyết về biểu diễn văn bản, về word embedding theo cách hiểu của Mì AI.

Mình cũng xin nói luôn, đây hoàn toàn là cách hiểu theo kiểu Mì Ăn Liền để có thể làm việc được với văn bản, NLP. Mình không care đến các từ chuyên ngành, các khái niệm bác học đâu nhé. Các chuyên gia đi qua xin bỏ quá cho em.

Ok, như vậy đã xong phần trình bày để tránh bị ăn mắng, ăn chê khi publish. Bây giờ mình xin trình bày lý do vì sao lại có bài này. Lý do là vì sau 2 bài về NLP:

thì mình nhận được nhiều câu hỏi, đề nghị của các bạn về việc giải thích rõ hơn về biểu diễn văn bản, nhúng từ vì nó khá trừu tượng, không rõ ràng như Computer Vision.

Rồi! Bây giờ không làm mất thời gian của các bạn hơn nữa! Go!

Phần 1 – Vì sao phải biểu diễn văn bản?

Đầu tiên chúng ta cần biết văn bản là gì? Cái này chắc ai cũng biết, là một tập hợp các từ chứ gì. Yep! Hiểu thế cho nhanh.

Ví dụ 1 câu văn bản: “Hôm nay chúng ta học NLP với Mì AI”

Chúng ta muốn xử lý ngôn ngữ tự nhiên (NLP) thì chúng ta phải lưu trữ được văn bản, nhét văn bản vào mạng Deep và train, rồi predict…. Nếu như ta cứ nhét cả cái câu kia vào thì căng, máy tính không hiểu được, nên phải nghĩ ra trò để biến 1 câu thành cái vector đặc trưng toàn số là số thì máy tính mới hiểu được. Và thế là các món biểu diễn văn bản, nhúng từ (word embedding) ra đời.

Nhiệm vụ của chúng ta là đi tìm hiểu từng cái để mà xài chứ ko cần sáng tạo ra cái gì quá cao siêu đâu, anh em yên tâm kaka!

Phần 2 – Biểu diễn văn bản bằng thuật toán BOW

Đây có thể nói là cách biểu diễn khá đơn giản và cũng vì thế mà dễ hiểu cho anh em.

Trước khi bắt đầu anh em cần có khái niệm về corpus – một cái kho dữ liệu chứa toàn bộ các văn bản mà anh em có thể có. Ví dụ: Anh em tải một lượng lớn các bài báo trên Vnexpress -> anh em có corpus về báo chí Tiếng Việt.

Bây giờ ta giả sử corpus của chúng ta gồm 2 văn bản sau: (giả sử thế cho đơn giản và dễ hiểu, thực tế thì corpus phải khủng long bạo chúa mới cho ra hiệu quả).

  • Câu 1: “Hôm nay chúng ta học Mì AI theo cách Mì ăn liền”
  • Câu 2: “Chúng ta cứ học giỏi là có tiền liền”

Rồi, bây giờ chúng ta tìm các biểu diễn 2 câu trên thành các vector đặc trưng toàn số là số cho nó pờ rồ nào.

Đâu tiên em anh tổng kết giúp xem trong cả 2 câu trên có bao nhiêu từ khác nhau nào? Dễ thấy gồm các từ: “hôm, nay, chúng, ta, học, mì , ai, theo, cách, ăn, liền, cứ, giỏi, là, có, tiền”.

biểu diễn văn bản
Nguồn: https://chrisalbon.com/

Với các từ thu được, ta đánh số thứ tự cho bọn nó, mỗi thằng một số tăng dần:

{
'hôm':0,
'nay':1,
'chúng':2,
'ta':3,
'học':4,
'mì':5,
'ai':6,
'theo':7,
'cách':8,
'ăn':9
'liền':10,
'cứ':11,
'giỏi':12,
'là':13,
'có':14,
'tiền':15
}Code language: JavaScript (javascript)

Xong rồi! Vậy là có tất cả 16 từ, đánh số từ 0 đến 15.

Bây giờ ta tạo cho mỗi câu trên 1 vector đặc trưng F có độ dài 16 (bằng tổng số từ trong corpus) và giá trị tại vị trí thứ i của F sẽ là số lần xuất hiện của từ có mã i trong câu.

#Vector ca câu 1
#Giá trthứ 5 bng 2, lý do? Là bi vì tcó mã thứ 5 - "mì" xut hin 2 ln trong câu 1
[1,1,1,1,1,2,1,1,1,1,0,0,0,0,0]
#Vector ca câu 2
#Giá trthứ 1 bng 0, lý do? Là bi vì tcó mã số 1 - "nay" không xut hin ln nào trong câu 2
[0,0,1,1,1,0,0,0,0,1,1,1,1,1,1]Code language: CSS (css)

Xong con ong! Thế là mỗi câu đã có 1 vector đặc trưng rồi nhé. Tuy nhiên cách biểu diễn này nảy sinh vài nhược điểm khiến Tây lông phải nghĩa ra các phương án khác, đó là:

  • Cách biểu diễn này không quan tâm đến thứ tự xuất hiện của các từ mà chỉ quan tâm đến số lần xuất hiện. Trong khi đó đổi thứ tự từ cũng làm thay đổi ý nghĩa câu phết đấy. Ví dụ đang là câu “Anh yêu em không?” mà đổi thành “Anh không yêu em” là căng đó 😀
  • Khi số lượng từ khác nhau trong corpus tăng lên (thuật ngữ gọi là số từ vựng vocabulary) thì vector đặc trưng sẽ dài lê thê và toán số 0 là chính, chỉ có vài vị trí có số khác 0 thôi (các câu thường chỉ chứa 1 số từ ít ỏi so với từ điển Tiếng Việt). Điều này gây lãng phí bộ nhớ.
  • Mỗi từ được biểu diễn bằng 1 số và chúng ta không có được sự tương quan giữa các từ với nhau. Ví dụ muốn tìm từ tương đồng với từ A nào đó thì chả có các nào mà tìm.

Thêm nữa, với phương pháp này thì các từ được coi là như nhau, đối xử như nhau trong khi với ngôn ngữ tự nhiên thì có một số từ có xu hướng xuất hiện thường xuyên nhưng lại không mang nhiều ý nghĩa cho lắm (gọi là stopwords) như “là”, “nhé”,”cứ”. Do vậy nếu chỉ xét theo tần số xuất hiện của từng từ thì việc phân loại văn bản rất có thể cho kết quả sai dẫn tỷ lệ chính xác sẽ thấp và phương pháp tiếp theo TFIDF ra đời.

Phần 3 – Biểu diễn câu bằng TFIDF

Để tìm hiểu chuyên sâu về cái món này thì các bạn lại đọc link này.

Còn với hiểu biết kiểu Mì thì sẽ đơn giản như sau:

  • Từ nào mà hầu hết câu nào trong corpus cũng có thì là từ không quan trọng
  • Từ nào xuất hiện trong 1 số câu thì là từ quan trọng, cần tóm lấy và đánh trọng số cao để biểu diễn văn bản.

Với tư tưởng như vậy ta sẽ tính 2 tham số và TF và IDF

TF là gì?

TF viết tắt của Term Frequency là tần suất xuất hiện cử từ cần xét trong văn bản hiện tại. Giá trị cao thể hiện độ quan trọng cao của từ với câu hiện tại.

Công thức tính TF của một từ t trong văn bản d sẽ là:

tf(t,d) = f(t,d)/ size(d)}

Nói dễ hiểu là tf(t,d) sẽ bằng số lần xuất hiện của từ t trong câu d chia cho số từ văn bản d. Dễ thấy từ nào càng xuất hiện nhiều thì TF sẽ càng lớn.

Ví dụ từ “Chúng” xuất hiện 1 lần trong câu 1 trong khi câu này có 12 từ -> tf(‘chúng’) = 1/12 = 0.083333333333333.

Từ “tiền” xuất hiện 1 lần trong câu 2 trong khi câu này có 9 từ -> tf(‘tiền’) = 1/9 = 0.111111111111111

IDF là gì?

IDF viết tắt của Inverse Document Frequency (tạm dịch: Nghịch đảo tần suất của văn bản). Nghe cứ gọi là ù tai :D.

Tóm lại là mục đích sinh ra thằng IDF là để giảm độ quan trọng của những từ mà câu nào trong corpus cũng có như rằng, thì, là, mà….

Công thức tính IDF của từ t trong toàn bộ corpus C là:

idf(t,C) = log(|C|/|d thuộc C : t thuộc d|)

Lại công thức ảo vê lờ, nhưng thực ra hiểu như này cho đơn giản. Idf của từ t thuộc corpus C bằng số lượng câu có trong corpus C chia so số lượng các câu có chứa từ t. Sau đó tính log của giá trị tính được.

Ví dụ từ “tiền” xuất hiện trong 1 văn bản (trong khi corpus của ta có 2 văn bản) vậy tdf (‘tiền’) = log (2/1) = log (2) = 0.30102999566.

biểu diễn văn bản
Nguồn: https://chrisalbon.com/
Kết hợp thành TF-IDF

Cuối cùng ta lấy chỉ số TF nhân với IDF để ra chỉ số TF-IDF của một từ. Ví dụ từ ‘tiền’ nhé

tf-idf('tiền') = tf('tiền')*idf('tiền) = 0.111111111111111*0.30102999566 = 0.033447777295556Code language: JavaScript (javascript)

Thế rồi sau khi tính toán một hồi thì mỗi từ sẽ có một số tf-idf riêng và thay vì gán cho mỗi từ 1 số thứ tự như Phần 2 thì ta biểu diễn mỗi từ bằng một số tf-idf. Sau đó ta chỉ cần thay một câu với các từ bằng các vector các chỉ số tf-idf tưng ứng.

Độ dài vector bằng số từ vựng trong Corpus, gọi là vector W = [w1, w2, w3….wn]. Vậy vị trí wi sẽ là TF-IDF của từ thứ i trong corpus.

Phần này mình ngại tính nên mình ví dụ bằng một số ngẫu nhiên để các bạn hiểu thôi nhé

# Ví dcâu số 1 sthành
[0.4323638172	0.5561975930	0.7034177544	0.1705945480	0.9210246970	0.0904618263	0.0994741197	0.1579684549	0.3486829821	0.8902186243	0.1854797205	0.3825182868]Code language: CSS (css)

Phần 4 – Phương pháp biểu diễn bằng One-hot-vector

Chúng ta vẫn tiếp tục xét 2 câu văn bản bên trên cho dễ nhé:

  • Câu 1: “Hôm nay chúng ta học Mì AI theo cách Mì ăn liền”
  • Câu 2: “Chúng ta cứ học giỏi là có tiền liền”

Tổng số từ vẫn là 16 từ: “hôm, nay, chúng, ta, học, mì , ai, theo, cách, ăn, liền, cứ, giỏi, là, có, tiền” và cũng được oánh số từ 0 đến 15 như trên.

Tiếp theo ta gán cho mỗi từ 1 vector one-hot có độ dài 16 (là cái vector chỉ có 1 giá trị bằng 1 còn lại là 0). Vector này sẽ có một vị trí i (= số thứ tự của từ được gán) bằng 1, còn lại bằng 0. Cụ thể:

# Vector của từ 'Hôm'
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
# Vector của từ 'Nay'
[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
....
....
# Vector của từ 'có'
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0]
# Vector của từ 'tiền'
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]Code language: PHP (php)

Sau đó thì làm sao biểu diễn 1 câu? Thì đó, câu có từ nào thì ghép vector đặc trưng của từ đó vào.

biểu diễn văn bản
Nguồn: https://chrisalbon.com/

Ví dụ xét câu 2 đi, nó gồm các từ: “Chúng ta cứ học giỏi là có tiền liền” thì cứ lấy lần lượt vector của các từ “Chúng”, “ta”….”liền” và xếp chồng lên nhau là ra biểu diễn của câu văn bản:

[
[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0],
[0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0]
]Code language: JSON / JSON with Comments (json)

Nhìn qua chúng ta cũng lại thấy một số điểm yếu của phương pháp này:

  • Cách biểu diễn này rất tốn tài nguyên, đặc biệt khi số từ vựng lớn.
  • Chúng ta vẫn không biểu diễn được mối tương quan giữa 2 từ với nhau. Ví dụ khi chúng ta áp dụng hàm tính khoảng cách giữa các vector từ để xem từ nào “gần” từ nào, “xa” từ nào thì toàn = 0. và không tính được (ý mình là dùng cosine similarity).

Và thế là nhân loại lại phải đi tìm một phương pháp biểu diễn mới nào!

Phần 5 – Phương pháp biểu diễn Ma trận đồng xuất hiện

Chắc anh em nghe cái tên đã hiểu phương pháp này như nào rồi đúng ko? Nó sẽ thể hiện bằng ma trận các từ xuất hiện cùng nhau trong văn bản để mong sao biểu diễn được sự tương quan giữa các từ.

Con người ta thì có câu “Ngưu tầm ngưu, mã tầm mã” hay là “Hãy cho biết bạn của bạn là ai, tôi sẽ nói cho bạn biết bạn là con người như thế nào”? Còn từ ngữ thì từ năm 1957, nhà ngôn ngữ học J.R. Firth [1] đã định nghĩa “You shall know a word by the company it keeps” (tạm dịch ra là: bạn sẽ biết một từ bằng cách xem xét các từ đi cùng nó”). Đó chính là xuất phát điểm của phương pháp này.

Thế bây giờ làm như nào?

Để minh họa cho đơn giản, ta xét với trường hợp window_size=1 (nghĩa là chỉ xét 2 từ cạnh nhau). Bạn nào muốn tìm hiểu chuyên sâu hơn thì xem link tại đây.

Nào lại quay lại 2 câu thần thánh của chúng ta:

  • Câu 1: “Hôm nay chúng ta học Mì AI theo cách Mì ăn liền”
  • Câu 2: “Chúng ta cứ học giỏi là có tiền liền”

Số từ lại là 16 từ và chúng ta lập một ma trận 16×16 gọi là ma trận W. Tiếp theo chúng ta dò từng câu xem 2 từ nào xuất hiện cạnh nhau trong câu đó thì tăng giá trị W tại vị trí tương ứng lên 1. Ví dụ cụ thể cho 2 câu trên:

Okie rồi. Bây giờ các bạn để ý theo từng hàng sẽ thấy mỗi từ có một vector đặc trưng đó. Thử nào

#Vector của từ 'Hôm'
[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0]
#Vector của từ 'ta'
[0,0,2,0,1,0,0,0,0,0,1,0,0,0,0]Code language: PHP (php)

Rồi sau khi đã có vector của từng từ ta làm tương tự phần 4 để ghép thành một ma trận biểu diễn một câu nhé.

Phương pháp này tuy lưu trữ được thông tin nhiều hơn phần trên nhưng vẫn tồn tại ít nhất 2 vấn đề lớn là : chiều của vector tăng theo kích thước từ điển và do đó cần không gian nhớ lớn để lưu thông tin.

Okie, đến đây thì bài lãm nhảm cuối tuần của mình về biểu diễn văn bản đã khá dài rồi, mình xin tạm dừng. Hẹn gặp lại các bạn trong bài sau với chi tiết về Word2Vec nhé.

Chào tạm biết và chúc các bạn thành công!

Hãy join cùng cộng đồng Mì AI nhé!

Fanpage: http://facebook.com/miaiblog
Group trao đổi, chia sẻ: https://www.facebook.com/groups/miaigroup
Website: https://miai.vn
Youtube: http://bit.ly/miaiyoutube

Related Post

One Reply to “[NLP Series #3] Lảm nhảm cuối tuần về biểu diễn văn bản bằng trong học máy (1/2)”

Leave a Reply

Your email address will not be published. Required fields are marked *