Bài Toán Spam_FIltering

classification
tutorial

#1

Xin chào mọi người, E hiện tại đang là SV năm cuối 1 trường ĐH, hiện tại đang hướng học tập và phát triển về Machine Learning. E học được rất nhiều từ web machinelearningcoban.com của a Tiệp và cả Forum, thấy forum đang phát triển rất nhanh làm e thực sự rất vui. Sau đây, e xin chia sẻ 1 chút kiến thức của mình để đóng góp cho forum ạ. Bài viết của e chắc chắn vẫn còn nhiều thiếu sót do e còn kém và chưa có nhiều kinh nghiệm nên mong các a/c có gì chỉ bảo cho e ạ! E cảm ơn rất nhiều ạ <3 <3 <3

Bài Toán Spam-Filtering

1.Giới thiệu bài toán

Tin nhắn rác (spam) thực sự là một vấn đề khó chịu đối với người sử dụng điện thoại di động. Bài viết này chúng ta sẽ áp dụng một thuật

  • Danh sách các mục

toán phân loại đơn giản có tên là Naive Bayes classifier dựa trên công thức xác suất Bayes có ở tất cả các giáo trình thống kê cơ bản để xây dựng một cỗ máy phân loại tin nhắn rác.

2.Xác định bài toán

  • Input: Tập văn bản mail tiếng việt và có gán nhãn spam or ham (File DataTrain 80 văn bản)
  • Output: Với mỗi văn bản phải xác định loại của văn bản đó là ham or spam (File DataTest 20 văn bản)

3. Khám phá dữ liệu

  • Đây là văn bản tiếng việt nên cần phải tách từ tiếng việt.
  • Số lượng file spam và hàm trong file train đã cân bằng.

4.Giải quyết bài toán

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

  • Sử dụng tool pyvi để tách từ tiếng việt
  • Chúng ta phải loại bỏ hết dấu câu để quá trình lọc spam-ham được chính xác. Nhận thấy, trong tiếng việt, chỉ đánh dấu vào các chứ cái a,d,e,i,o,u,y nên ta sẽ cần loại bỏ dấu trong các chữ này (ở chữ d là trong trường hợp đ).
  • Tách Data và Nhãn ra riêng biệt để phục vụ cho quá trình training

4.2. Bắt đầu training

  • Ở đây có một vấn đề, các giải thuật Machine Learning chỉ làm việc được với số, nên mình sẽ convert “ham”, “spam” và cả các sms về định dạng số. Bắt đầu với “ham” (tương ứng với số 0) và “spam” (tương ứng với số 1).
  • Tiếp theo, ta sẽ transform sms messages thành dạng số ( dùng module mà scikit learn cung cấp ). Module mà scikit learn cung cấp cho phép chuyển đổi định dạng text thành vector, mình sẽ import CountVectorizer và transform text thành vector. Cách transform thế này: mình có một mảng các string, mình sẽ transform mảng này sao mỗi string sẽ chuyển đổi thành 1 vector có độ dài d (số từ xuất hiện ít nhất 1 lần), giá trị của thành phần thứ i trong vector chính là số lần từ đó xuất hiện trong string.
  • Sau đó, Ta sẽ import Naive Bayes, fit rồi predict là xong.

  • Kết quả:

5.Các cách để nâng cao accurancy bài toán.

Ta có thể thấy accurancy chỉ đạt 85% có thể do nhiều lý do và có 1 số cách để raise nó lên như sau:

  1. Do data train quá ít nên kết quả chưa ra đc accurancy cao. Chúng ta nên tăng thêm data train cho nó

2.Apply grid search với MultinomialNB để tăng accurancy. Param mà mình apply Grid Search ở đây là alpha, người ta thêm nó vào cải thiện độ chính xác.

Nhưng kết quả cho ra k tăng lên (ta in ra best_param và kết quả của nó) :

3.Ta nhận thấy, có vẻ như thuật toán NaiveBayes cho ta kết quả không được cao và một số tài liệu trên mạng có suggest thuật toán SVM cho bài toán lọc thư rác với một kết quả tốt hơn nên chúng ta sẽ test với thuật toán này với dữ liệu ham và spam riêng.

Kết quả có raise lên nhưng có vẻ chưa đc như ý mình muốn:

Có vẻ như chúng ta lại phải tinh chỉnh mô hình thêm để tăng thêm accurancy rồi.Có lẽ các param1 và 2 trong GridSearch chưa khớp nhau rùi. Ta thử tham số C thành “C”: [0.50,0.51,0.52,0.53,0.54,0.55] xem sao. Thật đáng ngạc nhiên, Accurancy lên cao lên tương đối:

6.Cơ sở lý thuyết

Thuật toán mình dùng trong bài này là Naive Bayes.

Lý thuyết Bayes thì có lẽ không còn quá xa lạ với chúng ta nữa rồi. Nó chính là sự liên hệ giữa các xác suất có điều kiện. Điều đó gợi ý cho chúng ta rằng chúng ta có thể tính toán một xác suất chưa biết dựa vào các xác suất có điều kiện khác. Thuật toán Naive Bayes cũng dựa trên việc tính toán các xác suất có điều kiện đó. Nghe tên thuật toán là đã thấy gì đó ngây ngô rồi. Tại sao lại là Naive nhỉ. Không phải ngẫu nhiên mà người ta đặt tên thuật toán này như thế. Tên gọi này dựa trên một giả thuyết rằng các chiều của dữ liệu X=(x_1, x_2, …, x_n)X=(x 1 ​ ,x 2 ​ ,…,x n ​ ) là độc lập về mặt xác suất với nhau.. Chúng ta có thể thấy rằng giả thuyết này có vẻ khá ngây thơ vì trên thực tế điều này có thể nói là không thể xảy ra tức là chúng ta rất ít khi tìm được một tập dữ liệu mà các thành phần của nó không liên quan gì đến nhau. Tuy nhiên, giả thiết ngây ngô này lại mang lại những kết quả tốt bất ngờ. Giả thiết về sự độc lập của các chiều dữ liệu này được gọi là Naive Bayes (xin phép không dịch). Cách xác định class của dữ liệu dựa trên giả thiết này có tên là Naive Bayes Classifier (NBC). Tuy nhiên dựa vào giả thuyết này mà bước training và testing trở nên vô cùng nhanh chóng và đơn giản. Chúng ta có thể sử dụng nó cho các bài toán large-scale. Trên thực tế, NBC hoạt động khá hiệu quả trong nhiều bài toán thực tế, đặc biệt là trong các bài toán phân loại văn bản, ví dụ như lọc tin nhắn rác hay lọc email spam.

Vài nét về thuật toán SVM

Áp dụng SVM trong phân loại thư rác Đối với bài toán phân loại rác, giống như phần phân loại Bayes (mục 2.1.3), thuật toán SVM xem mỗi vector i xi là một vector đặc trưng biểu diễn cho nội dung thư và yi là nhãn phân loại đối với dữ liệu huấn luyện. Tương tự như phần phân loại Bayes, giá trị xi có thể là 0 hoặc 1.

E biết kiến thức e còn kém nên a/c nào qua thì cho e xin chút nhận xét ạ. E còn viết thêm 1 số bài nữa nhưng chưa dám up T.T. Nếu bài viết này đạt kết quả tốt thì e xin mạn phép đc up nốt và up đầy đủ cả link github cho bài này luôn ạ. <3<3<3


#2

Tốt lắm em ơi. Anh có một góp ý nhỏ là phần code em paste vào trong này, để ở dang code block (em xem bài Hướng dẫn sử dụng markdown). Cả phần toán em cũng đưa dần sang markdown để bài viết được hoàn thiện hơn.

Cảm ơn em rất nhiều.


#4

Đây là lần đầu tiên mình nghe tới việc loại bỏ dấu câu tiếng Việt. Bạn có thể giải thích kỹ hơn hay có chứng minh hiệu quả của bước tiền xử lý này không?

p/s: Mình thì đang kỳ công để chuẩn hóa dấu tiếng Việt về 1 chuẩn.


#5

Em làm về cái fake news. Em chưa nghĩ ra cách gì để xử lý tiếng Việt. Vì thế em cũng như bạn trên, hiện phải chuyển thành tiếng việt không dấu để xử lý. Anh có thể chia sẻ về ý tưởng của anh đk không ạ?


#6

Bạn gặp vấn đề gì khi xử lý tiếng Việt(nói chi tiết hơn giúp mình nhé).

Tiếng việt hay tiếng gì đi nữa thì ở mức đơn giản người ta vẫn coi mỗi word là 1 feature mà.


#7

Dạ. Là khi em đưa dữ liệu vào mảng thì phải đổi sang ascii, khi đó tụi em phải xử lý bỏ dấu tiếng Việt đi mới qua bước làm sạch được. Em hiện đang dùng Naive Bayes để test thử


#8

không cần thiết đâu bạn, có gói underthesea cho phép tách token bằng tiếng việt https://github.com/undertheseanlp/underthesea


#9

Mình thực sự chưa hiểu cách bạn làm.

Với mình, cách đơn giản nhất là tách từ theo “khoảng trắng” và sử dụng one-hot vector/ tf-idf để tính và biểu diễn các câu text sang vector. Từ vector thích dùng thuật toán gì thì tùy thôi.

Nếu dữ liệu của bạn sạch, có thể dùng tokenize như bạn @Tung_Trinh bình luận để việc trích xuất đặc trưng hiệu quả hơn.

Mình có 1 repo phân loại văn bản dùng naive bayes và svm sử dùng sklearn trong python. Bạn có thể đọc thử xem sao.


#10

bạn có thể review mộ số phương pháp hiệu quả nhất cho bài toán spam detect hiện nay đc ko? Phương pháp nào đang hiệu quả nhất cho bài toán trên?


#11

Theo mình có 2 hướng là classify và clustering. Với classify thì có một số phương pháp cổ điển như: Biểu diễn dữ liệu thành bag-of-word và dùng Naive Bayes để classify, cũng có thể dùng SVM, SGD làm các thuật toán phân loại. Clustering thường dùng nếu bạn phải tạo tập dữ liệu từ đầu và ko có thời gian làm label. Thường thì làm classify nhiều hơn, vì tập dữ liệu về spam cũng có khá nhiều


#12

Nhưng khi triển khai vào thực tế thì có 1 thực tế là kiểu dữ liệu spam rất khó định nghĩa để đưa vào dữ liệu training. Ví dụ như trên forum này thì ham là các bài về Machine learning, spam có thể là bán bất động sản, bán quần áo, tuyển dụng, giới thiệu khóa học, bảo hiểm, hội thánh của đức chúa trời mẹ tuyển thành viên,… mình đã thử 1 phương pháp unsupervised là one class classification nhưng nghe vẻ cũng không tốt(hoặc do mình làm không tốt). Bạn có cách nào để giải quyết vấn đề này không?


#13

Mình thấy bạn chưa đề cập đến vấn đề balancing data thì phải? Kinh nghiệm của mình là Naives Bayes rất nhạy cảm với data imbalancing. Bạn xem thử có vấn đề này trong tập dữ liệu của mình không.


#14

Mình cũng có vấn đề tương tự với bạn, vấn đề của mình là phân loại tin tức thật/giả. Ngay việc định nghĩa tin tức thật/giả cũng là 1 vấn đề. Định nghĩa và phân loại với label thật/giả dễ bị ảnh hưởng bởi định nghĩa của người phân loại -> kém khách quan.

Có 1 từ khóa mà dựa trên vấn đề của mình đã tìm hiểu là stance detection, hướng đi này cụ thể sẽ kiểm tra nội dung và chủ đề chính cần phân loại có liên quan với nhau không? Mình thấy tương đồng với việc lọc spam dựa vào chủ đề. Ví dụ như trên site Machine learning cơ bản thì các tin về bất động sản, chính trị, bla…bla… là spam


#15

Lý thuyết thì là đúng rồi, lý thuyết thì các phương pháp one class classification cũng phải xịn nhưng mình áp dụng lại không tốt.


#16

Cho mình hỏi thử, tại mình cũng mới học nlp thôi, thì dataset của bạn có bị mất cân bằng không? Với bạn dùng model classify nào thế ạ?


#17

Dữ liệu mất cân bằng là điều chắc chắn nhưng việc xử lý mất cân bằng và việc đặt class weight cho model mình có thể không nhắc tới vì vấn đề nằm ở chỗ mình rất khó để định nghĩa được dữ liệu cho một class. Phương pháp thì hiện giờ mình đang sử dụng random forest do đã thử và thấy nó tốt hơn so với các phương pháp khác.

One class classification thì mình mới thử trong này Novelty and Outlier Detection