Phân loại văn bản tiếng Việt sử dụng machine learning

1
2025

Phân loại văn bản (Text classification) là một bài toán phổ biến trong xử lý ngôn ngữ tự nhiên (Nature language processing). Đối với phân loại văn bản tiếng Việt, sẽ có đôi chút khác biệt so với phân loại văn bản tiếng anh. Trong bài viết này, Lập Trình Không Khó (LTKK) sẽ hướng dẫn bạn chi tiết, từng bước quá trình xây dựng một số mô hình phân loại văn bản tiếng Việt. Bài viết sẽ đặc biệt tập trung vào quá trình tiền xử lý dữ liệu tiếng Việt làm sao để có được một mô hình phân loại đủ tốt.

Sau khi đọc xong bài viết này, bạn sẽ nắm được một số kiến thức như sau:

  1. Nắm được cấu trúc tổng quát của một mô hình phân loại văn bản (Text classification)
  2. Quy trình chi tiết cách xây dựng một hệ thống phân loại văn bản
  3. Các công việc cần làm khi tiền xử lý dữ liệu tiếng Việt
  4. Thử nghiệm và đánh giá trên một số mô hình phân loại khác nhau.

Bài toán phân loại văn bản

Phân loại văn bản (Text Classification) là bài toán thuộc nhóm học có giám sát (Supervised learning) trong học máy. Bài toán này yêu cầu dữ liệu cần có nhãn (label). Mô hình sẽ học từ dữ liệu có nhãn đó, sau đó được dùng để dự đoán nhãn cho các dữ liệu mới mà mô hình chưa gặp.

Lấy ví dụ, bạn cần xây dựng một mô hình học máy để dự đoán chủ đề (Kinh tế, Xã hội, Thể thao,…) của một bài báo bất kỳ. Khi đó, bạn cần rất nhiều dữ liệu có gán nhãn; tức là bạn cần rất nhiều bài báo mà mỗi bài báo đó chúng ta phải biết trước nó nằm trong chủ đề nào rồi. Vấn đề dữ liệu có lẽ là vấn đề nan giải nhất của mô hình học giám sát này ^^.

Hình ảnh dưới đây sẽ cho chúng ta cái nhìn tổng quát về cách hoạt động của một bài toán phân loại văn bản:

Mô hình phân loại văn bản tiếng Việt tự động với Machine learning
Mô hình phân loại văn bản tiếng Việt tự động với Machine learning (credit: MonkeyLearn.com)

  • Giai đoạn (a): Huấn luyện (training) là giai đoạn học tập của mô hình phân loại văn bản. Ở bước này, mô hình sẽ học từ dữ liệu có nhãn (trong ảnh trên nhãn là Possitive, Negative, Neutral). Dữ liệu văn bản sẽ được số hóa thông qua bộ trích xuất đặc trưng (feature extractor) để mỗi mẫu dữ liệu trong tập huấn luyện trở thành 1 vector nhiều chiều (đặc trưng). Thuật toán máy học sẽ học và tối ưu các tham số để đạt được kết quả tốt trên tập dữ liệu này. Nhãn của dữ liệu được dùng để đánh giá việc mô hình học tốt không và dựa vào đó để tối ưu.
  • Giai đoạn (b): Dự đoán (prediction), là giai đoạn sử dụng mô hình học máy sau khi nó đã học xong. Ở giai đoạn này, dữ liệu cần dự đoán cũng vẫn thực hiện các bước trích xuất đặc trưng. Mô hình đã học sau đó nhận đầu vào là đặc trưng đó và đưa ra kết quả dự đoán.

Tiếp sau đây, chúng ta sẽ đi vào từng bước của quá trình xây dựng một mô hình phân loại văn bản tin tức tiếng Việt sau:

Bài toán: Xây dựng mô hình phân loại văn bản tin tức tiếng Việt cho trang báo điện tử X. Mỗi khi một bài báo được đăng, chương trình cần phải tự động xác định được bài báo đó nằm trong danh mục nào. Các danh mục gồm có: Kinh tế, Thể thao, Giáo dục, Sức khỏe, Du lịch, Pháp luật,…

Chuẩn bị dữ liệu

Dữ liệu là yếu tố quan trọng nhất và cũng là vấn đề mà chúng ta cần quan tâm nhất. Trong quá trình xây dựng một hệ thống phân loại văn bản, bước chuẩn bị và tiền xử lý dữ liệu quyết định tới thành bại của hệ thống hơn cả.

Với bài toán phân loại văn bản tin tức tiếng Việt, dữ liệu bạn cần chuẩn bị là dữ liệu các bài báo tiếng Việt kèm theo chủ đề của bài báo đó. Loại dữ liệu này nhìn chung là rất dễ kiếm, bởi vì có vô số website tin tức mỗi ngày đăng vài chục tin cơ mà.

Nếu bạn quan tâm tới việc thu thập dữ liệu tự động, có thể bạn nên đọc bài viết này:


Trong trường hợp bạn muốn có sẵn dữ liệu, bạn có thể tham khảo 1 trong 2 nguồn dữ liệu tin tức dưới đây:

  1. binhvq/news-corpus, lưu ý tải bản 76GB của tác giả (định dạng mongodb dump)
  2. duyvuleo/VNTC

Đây là các nguồn dữ liệu có kích thước tương đối lớn có thể dùng để thực hành bài toán phân loại văn bản. Các bạn sau khi tại về có thể xử lý và loại bỏ các thành phần không sử dụng trong dữ liệu. Chỉ giữ lại nội dung bài báo và chủ đề bài báo – 2 thành phần mà chúng ta quan tâm trong bài toán này.

Bước tiếp theo, chúng ta sẽ tiến hành tiền xử lý dữ liệu trước khi đưa vào huấn luyện mô hình phân loại văn bản. Việc tiền xử lý dữ liệu là hết sức quan trọng để đảm bảo mô hình đạt được kết quả tốt.

Tiền xử lý dữ liệu

Bước tiền xử lý dữ liệu là bước đầu tiên cần làm, nó cần được làm trước bước feature extractor. Việc tiền sử lý dữ liệu là quá trình chuẩn hóa dữ liệuloại bỏ các thành phần không có ý nghĩa cho việc phân loại văn bản.

Tiền xử lý dữ liệu tiếng Việt cho bài toán phân loại văn bản thường gồm các việc sau:

  • Xóa HTML code (nếu có)
  • Chuẩn hóa bảng mã Unicode (đưa về Unicode tổ hợp dựng sẵn)
  • Chuẩn hóa kiểu gõ dấu tiếng Việt (dùng òa úy thay cho oà uý)
  • Thực hiện tách từ tiếng Việt (sử dụng thư viện tách từ như pyvi, underthesea, vncorenlp,…)
  • đưa về văn bản lower (viết thường)
  • Xóa các ký tự đặc biệt: “.”, “,”, “;”, “)”, …

Nếu bạn chưa từng xử lý dữ liệu văn bản với Python, bạn nên đọc trước 2 bài viết dưới đây trước khi tiếp tục:

Xóa HTML code trong dữ liệu

Dữ liệu được thu thập từ các website đôi khi vẫn còn sót lại các đoạn mã HTML. Các mã HTML code này là rác, chẳng những không có tác dụng cho việc phân loại mà còn làm kết quả phân loại văn bản bị kém đi.

Việc xóa các HTML code này cũng khá đơn giản, chúng ta có thể sử dụng regex trong Python để xóa đi một cách đơn giản:

Chuẩn hóa Unicode tiếng Việt

Hiện nay, có 2 loại mã Unicode được sử dụng phổ biến, Unicode tổ hợp và Unicode dựng sẵn. Điều đó dẫn tới vấn đề sau đây:

Hướng xử lý: Đưa về 1 chuẩn Unicode dựng sẵn (thằng này phổ biến hơn). Chi tiết cách xử lý thì mình đã trình bày ở bài Xử lý tiếng Việt trong NLP đã nhắc ở trên.

Nếu bạn không xử lý vấn đề này, khi đưa vào mô hình học máy tính sẽ hiểu đó là các từ khác nhau mặc dù ta đang nhìn thấy chúng chẳng khác nhau gì.

Chuấn hóa kiểu gõ dấu

Kiểu gõ dấu khác nhau thì bạn nhìn mắt thường cũng sẽ thấy được sự khác nhau: òa với lần lượt là kiểu gõ cũ (phổ biến hơn) và kiểu gõ mới. Chi tiết về vấn đề này bạn có thể tham khảo tại Wikipedia.

Script dưới đây sẽ giúp chúng ta chuẩn hóa lại dữ liệu về kiểu gõ dấu cũ:

Tách từ tiếng Việt

Như các bạn đã học ở tiểu học hay trung học gì đó (quên rồi), đơn vị từ trong tiếng Việt bao gồm từ đơn (yêu) và từ ghép (học sinh). Nên chúng ta cần phải nói cho mô hình học máy biết đâu là từ đơn, đâu là từ ghép. Nếu không thì từ nào cũng sẽ là từ đơn hết.

Bởi vì mô hình của chúng ta sẽ coi các từ là đặc trưng, tách nhau theo dấu cách. Do đó, chúng ta phải nối các từ ghép lại thành một từ để không bị tách sai:

Học sinh học sinh học ⇒ Học_sinh học sinh_học

Bài toán này là một bài toán cơ sở trong NLP – bài toán tách từ (word tokenize). Thật may là hiện nay có khá nhiều thư viện mã nguồn mở của bài toán này. Do đó, chúng ta chỉ việc cài đặt và sử dụng.

Với ngôn ngữ Python, bạn có thể lựa chọn underthesea hoặc pyvi nhé.

Đưa về viết thường (lowercase)

Việc đưa dữ liệu về chữ viết thường là rất cần thiết. Bởi vì đặc trưng này không có tác dụng ở bài toán phân loại văn bản. Đưa về chữ viết thường giúp giảm số lượng đặc trưng (vì máy tính hiểu hoa thường là 2 từ khác nhau) và tăng độ chính xác hơn cho mô hình.

Xóa các ký tự không cần thiết

Như mình đã nói, tiền xử lý bao gồm việc loại bỏ các dữ liệu không có tác dụng cho việc phân loại văn bản. Việc này giúp:

  • Giảm số chiều đặc trưng, tăng tốc độ học và xử lý
  • Tránh làm ảnh hưởng xấu tới kết quả của mô hình

Các dấu ngắt câu, số đếm và các ký tự đặc biệt khác không giúp bạn phân loại một văn bản thuộc chuyên mục nào. Do đó, chúng ta nên loại bỏ nó đi.

Riêng với số đếm, ngày tháng, email (Các token đặc biệt). Nếu có thể bạn nên đưa nó về các token chung như: <number>, <date>, <email>, … Việc này có thể không giúp ích cho mô hình học tốt hơn nhưng sẽ giúp ích cho bạn trong việc giữ được mạch của dữ liệu.

Và đây là hàm tiền xử lý tổng hợp tất cả các bước ở trên, bạn tham khảo và bổ sung thêm nếu cần:

Mình thử ví dụ xem nó tiền xử lý dữ liệu mình ra sản phẩm gì nhé.

Dữ liệu gốc, copy đại 1 bài báo trên Vnexpress:

Và dữ liệu sau khi xử lý:

Mình quan sát thì thấy vừa ý rồi, nên mình sẽ chuyển sang bước tiếp theo.

Loại bỏ các stopword tiếng Việt

Cũng giống như việc loại bỏ các ký tự đặc biệt ở trên, nhưng bây giờ là các từ tiếng Việt hẳn hoi. Vậy tại sao cần loại bỏ?

  • Stopword là các từ xuất hiện nhiều ở tất cả các chuyên mục cần phân loại. Do đó, chúng là các đặc trưng không có tác dùng cho việc phân loại văn bản.
  • Các stopword thường là các từ nối (của, là, có, được, những,…) và các từ đặc trưng của dữ liệu (ví dụ như các từ “máy bay, tiếp viên” là các stopword nếu làm bài phân loại đánh giá khách hàng của doanh nghiệp vận tải hàng không.

Vậy làm sao để xây dựng bộ stopword?

Danh sách stopword phải nên được xây dựng từ bộ dữ liệu văn bản lớn, tầm cỡ vài chục GB là hợp lý. Nếu là dữ liệu trong miền bài toán bạn đang làm thì càng tốt!

Việc xây dựng bộ từ điển stopword tiếng Việt cũng rất đơn giản. Bạn chỉ cần thống kê các từ xuất hiện nhiều trong tất cả các chuyên mục và lấy top đầu là được.

Ví dụ, với dữ liệu tin tức của mình, thống kê trên khoảng 2000 bài báo mỗi chủ đề, thì mình được kết quả như sau (Đã sắp xếp giảm dần, lấy demo một ít top đầu):

Việc lấy bao nhiêu từ trong danh sách kết quả này cần dựa vào quan sát & loại trừ. Giả sử như mình trong bài này, mình chỉ lấy 100 từ đầu tiên để làm stopword.

Trong trường hợp bạn không muốn xây dựng bộ stopword hoặc không có dữ liệu để làm, bạn có thể tham khảo một số bộ stopword tiếng Việt đã được chia sẻ trên internet.

Loại stopword khỏi dữ liệu ra sao?

Việc cần làm bây giờ của bạn là duyệt qua từng bản ghi dữ liệu và xóa tất cả các từ trong dữ liệu mà có trong danh sách stopword.

Sau khi thực hiện tiền xử lý dữ liệu xong, giờ chúng ta bắt tay vào xây dựng các mô hình học máy cho bài toán phân loại văn bản trên dữ liệu đã tiền xử lý.

Xây dựng mô hình phân loại văn bản

Trước khi huấn luyện mô hình phân loại văn bản, ta cần xây dựng tập huấn luyện và tập kiểm thử. Việc này là cần thiết để đánh giá kết quả huấn luyện, lựa chọn mô hình cũng như tinh chỉnh để mô hình cho tốt hơn.

Xây dựng tập train/test

Dữ liệu dùng cho bài toán phân loại văn bản của mình sau khi tiền xử lý được lưu thành 1 file duy nhất. Mỗi dòng là một bài báo kèm theo thông tin danh mục của nó.

Mục đích mình để theo format này là để về sau train với thư viện Fasttext

Thống kê dữ liệu sử dụng:

Và đây là thống kê dữ liệu được mình sử dụng trên mỗi nhãn (mình dùng ít cho nhanh):

Các nhãn có số lượng khá cân bằng rồi, nên việc xử lý dữ liệu mất cân bằng không cần phải lo. Nếu bạn dùng thực tế, nên thêm dữ liệu nhiều hơn gấp 10 lần nhé ^^.

Mình sẽ sử dụng thư viện sklearn trong Python giúp mình tách dữ liệu làm 2 tập train/test riêng biệt:

Ở trên, mình thực hiện các công việc sau:

  1. Đọc dữ liệu từ file và tách làm 2 list text (dữ liệu) và label (nhãn). Dữ liệu text[i] sẽ có nhãn là label[i].
  2. Chia làm 2 tập train (X_train, y_train) và test (X_test, y_test) theo tỉ lệ 80% train, 20% test.
  3. Lưu train/test data ra file để sử dụng cho việc train với thư viện Fasttext.
  4. Đưa label về dạng vector để tiện cho tính toán sử dụng LabelEncoder.

Ok, bậy giờ chúng ta sẽ sử dụng tập train để đi thử nghiệm với các mô hình phân loại văn bản tiếng Việt khác nhau nhé. Mình sẽ thử nghiệm trên các mô hình mà các bạn có thể dễ dàng cài đặt:

  • Naive Bayes (thư viện sklearn)
  • Logistic Regression (thư viện sklearn)
  • Support Vector Machine (thư viện sklearn)
  • Fasttext (https://fasttext.cc/)

Với các thuật toán machine learning truyền thống sử dụng thư viện sklearn, mình sẽ xây dựng bộ trích xuất đặc trưng (feature extractor) sử dụng TF-IDF.

Sử dụng Naive Bayes

Sử dụng Logistic Regression

Sử dụng mô hình SVM

Sử dụng thư viện Fasttext

Đầu tiên, bạn cần cài đặt thư viện này như sau:

Tiếp theo, bạn cần chuẩn bị dữ liệu giống như 2 file “train.txt” và “test.txt” mà mình đã chuẩn bị ở phần Xây dựng tập train/test:

Kết quả phân loại văn bản

Trong mỗi mô hình trên, mình đều tiến hành đo thời gian huấn luyện. Bạn có thể dựa vào thông tin đó để biết mô hình nào huấn luyện nhanh hay chậm, mất bao lâu để huấn luyện xong.

So sánh các mô hình

Còn bây giờ, chúng ta sẽ đánh giá các mô hình vừa rồi để xem mô hình nào cho kết quả tốt nhất trên tập test:

Và đây là kết quả sau khi chạy đoạn code đánh giá trên:

Mình cũng thử xem kết quả trên từng nhãn của mô hình naive bayes xem thế nào:

Thì được kết quả như sau:

Nhận xét & đánh giá

  • Mô hình Logistic Regression và SVM cho kết quả vượt trội hơn Naive Bayes. Điều này do khả năng học của 2 mô hình này tốt hơn một mô hình ngây thơ (naive).
  • Một số nhãn cho độ chính xác phân loại thấp (giải trí, nhịp sống, sống trẻ). Nguyên nhân có thể do các chuyên mục này không thực sự quá rõ ràng, nổi bật so với các chuyên mục khác nên mô hình dễ bị sai hơn. Ví dụ: Bài “Cô giáo dành cả thành xuân để dạy các em vùng cao” thì có thể là ở Nhịp sống hoặc Sống trẻ đều ổn. Về vấn đề này, chúng ta cần phải dành thời gian để quan sát dữ liệu, lọc ra các bài báo bị phân loại sai và tìm hiểu nguyên nhân.
  • Mô hình sử dụng thư viện Fasttext cho kết quả thấp nhất (không như kỳ vọng của mình). Nguyên nhân mình đoán là do hơi ít dữ liệu nên chưa học tốt việc biểu diễn từ. Nếu có thể, bạn hãy train lại với pretrain word2vec hoặc sử dụng nhiều dữ liệu hơn để nó có thể cho kết quả tốt hơn.
  • Tăng số lượng dữ liệu huấn luyện cho các mô hình sẽ giúp các mô hình trên đây học tốt hơn đó.

Demo & tự thực hành

Source code phân loại văn bản tiếng việt trình bày trong bài viết này được lưu tại Github, bạn mở nó lên và click vào mục Demo để thực hành nhé!

Mọi ý kiến đóng góp, nhận xét cũng như các thắc mắc liên quan tới bài viết. Các bạn vui lòng để lại bình luận phía dưới bài viết. Xin cám ơn!

Tài liệu tham khảo

  1. Dữ liệu huấn luyện trong bài viết
  2. Thư viện fasttext của Facebook
  3. Thư viện học máy scikit-learn
Subscribe
Notify of
guest
1 Bình luận
Inline Feedbacks
View all comments