Naive Bayes và các biến thể

Naive Bayes và Các Biến Thể: Thuật Toán Phân Loại Xác Suất Đơn Giản nhưng Hiệu Quả

Giới thiệu

Naive Bayes là một trong những thuật toán học máy đơn giản nhất nhưng lại rất hiệu quả, đặc biệt trong các bài toán phân loại văn bản, phát hiện spam, và phân tích cảm xúc. Dựa trên định lý Bayes trong lý thuyết xác suất, thuật toán này được gọi là "naive" (ngây thơ/đơn giản) vì nó giả định rằng các đặc trưng (features) trong dữ liệu là độc lập với nhau, một giả định mà trong thực tế hiếm khi đúng. Tuy nhiên, bất chấp sự đơn giản hóa này, Naive Bayes vẫn hoạt động rất hiệu quả trong nhiều tình huống thực tế.

Bài viết này sẽ giới thiệu chi tiết về thuật toán Naive Bayes, từ nguyên lý cơ bản đến các biến thể phổ biến, ưu nhược điểm, và các ứng dụng thực tế của nó.

Định lý Bayes - Nền tảng toán học

Trước khi đi vào thuật toán Naive Bayes, chúng ta cần hiểu về định lý Bayes - nền tảng toán học của thuật toán này.

Định lý Bayes cho biết cách tính xác suất có điều kiện của một sự kiện A khi biết rằng sự kiện B đã xảy ra:

$$P(A|B) = \frac{P(B|A) \times P(A)}{P(B)}$$

Trong đó:

  • $P(A|B)$ là xác suất hậu nghiệm (posterior probability): xác suất của A xảy ra khi biết B đã xảy ra

  • $P(B|A)$ là xác suất hợp lý (likelihood): xác suất của B xảy ra khi biết A đã xảy ra

  • $P(A)$ là xác suất tiên nghiệm (prior probability): xác suất của A xảy ra trước khi biết bất kỳ thông tin nào về B

  • $P(B)$ là xác suất chứng cứ (evidence): xác suất của B xảy ra

Trong bối cảnh phân loại, định lý Bayes có thể được viết lại như sau:

$$P(\text{class}|\text{features}) = \frac{P(\text{features}|\text{class}) \times P(\text{class})}{P(\text{features})}$$

Trong đó:

  • $P(\text{class}|\text{features})$ là xác suất một mẫu thuộc về một lớp nhất định, khi biết các đặc trưng của nó

  • $P(\text{features}|\text{class})$ là xác suất quan sát được các đặc trưng này trong một mẫu thuộc lớp đó

  • $P(\text{class})$ là xác suất tiên nghiệm của lớp đó

  • $P(\text{features})$ là xác suất quan sát được các đặc trưng này trong bất kỳ mẫu nào

Thuật toán Naive Bayes

Nguyên lý cơ bản

Thuật toán Naive Bayes áp dụng định lý Bayes với giả định "ngây thơ" rằng các đặc trưng là độc lập với nhau khi biết lớp. Điều này cho phép chúng ta viết:

$$P(\text{features}|\text{class}) = P(x_1, x_2, ..., x_n|\text{class}) = P(x_1|\text{class}) \times P(x_2|\text{class}) \times ... \times P(x_n|\text{class})$$

Với giả định này, công thức Bayes trở thành:

$$P(\text{class}|\text{features}) = \frac{P(\text{class}) \times \prod_{i=1}^{n} P(x_i|\text{class})}{P(\text{features})}$$

Khi so sánh các lớp để quyết định phân loại, chúng ta chỉ quan tâm đến tử số vì mẫu số $P(\text{features})$ là hằng số đối với tất cả các lớp. Do đó, quy tắc phân loại trở thành:

$$\hat{y} = \arg\max_{c} P(c) \times \prod_{i=1}^{n} P(x_i|c)$$

Trong đó $\hat{y}$ là lớp được dự đoán cho mẫu đó.

Các bước của thuật toán

Thuật toán Naive Bayes hoạt động theo các bước sau:

  1. Tính xác suất tiên nghiệm của mỗi lớp: $P(c)$ = (số mẫu thuộc lớp c) / (tổng số mẫu)

  2. Tính xác suất có điều kiện của mỗi đặc trưng khi biết lớp: $P(x_i|c)$ = (số mẫu có đặc trưng $x_i$ và thuộc lớp c) / (số mẫu thuộc lớp c)

  3. Áp dụng công thức Naive Bayes để tính xác suất hậu nghiệm của mỗi lớp: $P(c|\text{features}) \propto P(c) \times \prod_{i=1}^{n} P(x_i|c)$

  4. Chọn lớp có xác suất hậu nghiệm cao nhất: $\hat{y} = \arg\max_{c} P(c|\text{features})$

Xử lý vấn đề xác suất bằng 0

Một vấn đề thường gặp trong Naive Bayes là khi một đặc trưng không xuất hiện trong một lớp nào đó trong tập huấn luyện, xác suất $P(x_i|c)$ sẽ bằng 0, dẫn đến xác suất hậu nghiệm cũng bằng 0. Để giải quyết vấn đề này, người ta thường sử dụng kỹ thuật làm mịn (smoothing), phổ biến nhất là Laplace (hay Additive) smoothing:

$$P(x_i|c) = \frac{\text{count}(x_i, c) + \alpha}{\text{count}(c) + \alpha \times |\text{domain}(x_i)|}$$

Trong đó $\alpha$ là tham số làm mịn (thường là 1, được gọi là Laplace smoothing), và $|\text{domain}(x_i)|$ là số giá trị có thể có của đặc trưng $x_i$.

Các biến thể của Naive Bayes

Thuật toán Naive Bayes có nhiều biến thể khác nhau, phù hợp với các loại dữ liệu và bài toán khác nhau. Ba biến thể phổ biến nhất là:

1. Multinomial Naive Bayes

Multinomial Naive Bayes phù hợp với dữ liệu rời rạc, thường được dùng cho phân loại văn bản nơi các đặc trưng là tần suất xuất hiện của các từ.

Công thức: $$P(x_i|c) = \frac{\text{count}(x_i, c) + \alpha}{\sum_{j=1}^{|V|} (\text{count}(x_j, c) + \alpha)}$$

Trong đó:

  • $\text{count}(x_i, c)$ là số lần đặc trưng $x_i$ xuất hiện trong các mẫu thuộc lớp c

  • $|V|$ là kích thước của từ điển

  • $\alpha$ là tham số làm mịn (thường là 1)

Ứng dụng:

  • Phân loại văn bản

  • Phân tích cảm xúc

  • Phát hiện spam email

Ví dụ Python:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

# Tải dữ liệu
categories = ['alt.atheism', 'soc.religion.christian', 'comp.graphics', 'sci.med']
twenty_train = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42)
twenty_test = fetch_20newsgroups(subset='test', categories=categories, shuffle=True, random_state=42)

# Tạo pipeline
text_clf = Pipeline([
    ('vect', CountVectorizer()),
    ('clf', MultinomialNB(alpha=1.0)),
])

# Huấn luyện mô hình
text_clf.fit(twenty_train.data, twenty_train.target)

# Dự đoán và đánh giá
predictions = text_clf.predict(twenty_test.data)
print(classification_report(twenty_test.target, predictions, target_names=twenty_train.target_names))

2. Gaussian Naive Bayes

Gaussian Naive Bayes giả định rằng các đặc trưng liên tục tuân theo phân phối chuẩn (Gaussian) trong mỗi lớp. Phù hợp với dữ liệu liên tục như chiều cao, cân nặng, đo lường, v.v.

Công thức: $$P(x_i|c) = \frac{1}{\sqrt{2\pi\sigma^2_c}} \exp\left(-\frac{(x_i - \mu_c)^2}{2\sigma^2_c}\right)$$

Trong đó:

  • $\mu_c$ là giá trị trung bình của đặc trưng $x_i$ trong các mẫu thuộc lớp c

  • $\sigma^2_c$ là phương sai của đặc trưng $x_i$ trong các mẫu thuộc lớp c

Ứng dụng:

  • Phân loại dữ liệu y tế

  • Nhận dạng đối tượng

  • Dự đoán thời tiết

Ví dụ Python:

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score

# Tải dữ liệu
iris = load_iris()
X, y = iris.data, iris.target

# Chia dữ liệu
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Khởi tạo và huấn luyện mô hình
gnb = GaussianNB()
gnb.fit(X_train, y_train)

# Dự đoán và đánh giá
y_pred = gnb.predict(X_test)
print(f"Độ chính xác: {accuracy_score(y_test, y_pred):.4f}")

3. Bernoulli Naive Bayes

Bernoulli Naive Bayes phù hợp với dữ liệu nhị phân, nơi mỗi đặc trưng chỉ có thể nhận một trong hai giá trị (thường là 0 hoặc 1, hiện diện hoặc vắng mặt).

Công thức: $$P(x_i|c) = P(i|c)^{x_i} \times (1 - P(i|c))^{(1-x_i)}$$

Trong đó:

  • $P(i|c)$ là xác suất đặc trưng $i$ xuất hiện trong các mẫu thuộc lớp c

  • $x_i$ là giá trị của đặc trưng (0 hoặc 1)

Ứng dụng:

  • Phân loại văn bản với biểu diễn nhị phân

  • Phát hiện spam với các đặc trưng hiện diện/vắng mặt

  • Phân tích cảm xúc dựa trên sự hiện diện của các từ cụ thể

Ví dụ Python:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import BernoulliNB
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

# Tải dữ liệu
categories = ['alt.atheism', 'soc.religion.christian', 'comp.graphics', 'sci.med']
twenty_train = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42)
twenty_test = fetch_20newsgroups(subset='test', categories=categories, shuffle=True, random_state=42)

# Tạo pipeline với biểu diễn nhị phân (binary=True)
text_clf = Pipeline([
    ('vect', CountVectorizer(binary=True)),
    ('clf', BernoulliNB(alpha=1.0)),
])

# Huấn luyện mô hình
text_clf.fit(twenty_train.data, twenty_train.target)

# Dự đoán và đánh giá
predictions = text_clf.predict(twenty_test.data)
print(classification_report(twenty_test.target, predictions, target_names=twenty_train.target_names))

4. Complement Naive Bayes

Complement Naive Bayes là một biến thể được thiết kế để xử lý tốt hơn với dữ liệu không cân bằng. Thay vì tính xác suất của một đặc trưng xuất hiện trong một lớp, nó tính xác suất của đặc trưng đó xuất hiện trong tất cả các lớp khác.

Công thức: $$P(x_i|\bar{c}) = \frac{\sum_{j \neq c} \text{count}(x_i, j) + \alpha}{\sum_{j \neq c} \sum_{k=1}^{|V|} (\text{count}(x_k, j) + \alpha)}$$

Ứng dụng:

  • Phân loại văn bản với dữ liệu không cân bằng

  • Phát hiện sự kiện hiếm

Ví dụ Python:

from sklearn.naive_bayes import ComplementNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_20newsgroups
from sklearn.metrics import classification_report

# Tải dữ liệu
categories = ['alt.atheism', 'soc.religion.christian', 'comp.graphics', 'sci.med']
twenty_train = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42)
twenty_test = fetch_20newsgroups(subset='test', categories=categories, shuffle=True, random_state=42)

# Tạo pipeline
text_clf = Pipeline([
    ('vect', CountVectorizer()),
    ('clf', ComplementNB(alpha=1.0)),
])

# Huấn luyện mô hình
text_clf.fit(twenty_train.data, twenty_train.target)

# Dự đoán và đánh giá
predictions = text_clf.predict(twenty_test.data)
print(classification_report(twenty_test.target, predictions, target_names=twenty_train.target_names))

5. Categorical Naive Bayes

Categorical Naive Bayes là một biến thể ít phổ biến hơn, được thiết kế để xử lý các đặc trưng phân loại (categorical) không phải nhị phân. Mỗi đặc trưng có thể nhận một trong nhiều giá trị rời rạc.

Ứng dụng:

  • Phân loại dữ liệu với đặc trưng phân loại

  • Dự đoán dựa trên các đặc trưng như màu sắc, loại sản phẩm, v.v.

Ưu và nhược điểm của Naive Bayes

Ưu điểm:

  1. Đơn giản và dễ triển khai: Thuật toán dễ hiểu và triển khai, không đòi hỏi các kỹ thuật tối ưu hóa phức tạp.

  2. Huấn luyện nhanh: Chỉ cần một lần duyệt qua dữ liệu để tính các xác suất.

  3. Hiệu quả với dữ liệu cao chiều: Hoạt động tốt với dữ liệu có nhiều đặc trưng, như trong phân loại văn bản.

  4. Ít dữ liệu huấn luyện: Có thể hoạt động hiệu quả với ít dữ liệu huấn luyện.

  5. Xử lý tốt giá trị thiếu: Các giá trị thiếu có thể được bỏ qua trong quá trình tính toán.

  6. Xử lý đa lớp tự nhiên: Dễ dàng mở rộng cho bài toán phân loại nhiều lớp.

  7. Dự đoán xác suất: Cung cấp xác suất cho mỗi lớp, không chỉ là nhãn dự đoán.

Nhược điểm:

  1. Giả định độc lập: Giả định các đặc trưng độc lập thường không đúng trong thực tế, có thể dẫn đến kết quả không tối ưu.

  2. Vấn đề "zero frequency": Khi một giá trị đặc trưng không xuất hiện trong tập huấn luyện, cần áp dụng kỹ thuật làm mịn để tránh xác suất bằng 0.

  3. Ít tham số học: Mặc dù đây có thể là ưu điểm trong một số trường hợp, nhưng cũng có nghĩa là mô hình có thể quá đơn giản cho các bài toán phức tạp.

  4. Hiệu suất kém hơn các mô hình phức tạp: Trong nhiều bài toán, các mô hình phức tạp hơn như Random Forest hoặc Deep Learning có thể đạt hiệu suất cao hơn.

Các trường hợp sử dụng Naive Bayes trong thực tế

1. Phát hiện spam email

Naive Bayes, đặc biệt là Multinomial Naive Bayes, đã được sử dụng rộng rãi trong phát hiện spam email. Các email được biểu diễn dưới dạng túi từ (bag of words), và thuật toán học từ các email đã được phân loại trước đó để dự đoán email mới là spam hay không.

2. Phân loại tài liệu

Naive Bayes được sử dụng để phân loại tài liệu vào các chủ đề khác nhau, như tin tức, thể thao, giải trí, v.v. Multinomial Naive Bayes thường được sử dụng cho nhiệm vụ này.

3. Phân tích cảm xúc

Thuật toán này hiệu quả trong việc xác định cảm xúc (tích cực, tiêu cực, trung tính) của một đoạn văn bản, như đánh giá sản phẩm, tweet, bình luận trên mạng xã hội.

4. Phân loại trong y tế

Gaussian Naive Bayes thường được sử dụng trong y tế để phân loại bệnh nhân dựa trên các đặc điểm sinh học như huyết áp, nhịp tim, mức đường huyết, v.v.

5. Hệ thống gợi ý

Naive Bayes có thể được sử dụng trong các hệ thống gợi ý đơn giản, nơi các sản phẩm được gợi ý dựa trên sở thích trước đó của người dùng.

6. Dự đoán thời tiết

Gaussian Naive Bayes có thể được sử dụng để dự đoán thời tiết dựa trên các điều kiện khí tượng khác nhau.

Cải thiện hiệu suất của Naive Bayes

1. Kỹ thuật làm mịn (Smoothing)

Như đã đề cập, kỹ thuật làm mịn như Laplace smoothing giúp giải quyết vấn đề "zero frequency".

2. Biến đổi đặc trưng

Chuyển đổi các đặc trưng để chúng phù hợp hơn với giả định của thuật toán, như chuẩn hóa đặc trưng liên tục cho Gaussian Naive Bayes.

3. Lựa chọn đặc trưng

Loại bỏ các đặc trưng không liên quan hoặc có độ tương quan cao để giảm bớt tác động của giả định độc lập.

4. Kết hợp mô hình

Kết hợp Naive Bayes với các thuật toán khác để tận dụng điểm mạnh của từng thuật toán.

5. Hiệu chỉnh xác suất

Áp dụng các kỹ thuật hiệu chỉnh xác suất sau khi dự đoán, như hiệu chỉnh hậu nghiệm (posterior calibration).

6. Cross-validation

Sử dụng k-fold cross-validation để tìm giá trị tối ưu cho các tham số như tham số làm mịn $\alpha$.

Triển khai Naive Bayes trên dữ liệu thực tế

Ví dụ: Phân loại tin nhắn SMS là spam hay không

import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB, BernoulliNB
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import classification_report, confusion_matrix

# Tải dữ liệu SMS Spam Collection
url = "https://raw.githubusercontent.com/mohitgupta-omg/Kaggle-SMS-Spam-Collection-Dataset-/master/spam.csv"
df = pd.read_csv(url, encoding='latin-1')
df = df.rename(columns={'v1': 'label', 'v2': 'message'})
df = df[['label', 'message']]

# Chuyển đổi nhãn thành số
df['label_num'] = df.label.map({'ham': 0, 'spam': 1})

# Chia dữ liệu
X_train, X_test, y_train, y_test = train_test_split(
    df.message, df.label_num, test_size=0.3, random_state=42
)

# Tạo và đánh giá Pipeline với MultinomialNB
mnb_pipeline = Pipeline([
    ('vect', CountVectorizer()),
    ('clf', MultinomialNB()),
])

mnb_pipeline.fit(X_train, y_train)
mnb_pred = mnb_pipeline.predict(X_test)
print("MultinomialNB:")
print(classification_report(y_test, mnb_pred))
print(confusion_matrix(y_test, mnb_pred))

# Tạo và đánh giá Pipeline với BernoulliNB
bnb_pipeline = Pipeline([
    ('vect', CountVectorizer(binary=True)),
    ('clf', BernoulliNB()),
])

bnb_pipeline.fit(X_train, y_train)
bnb_pred = bnb_pipeline.predict(X_test)
print("\nBernoulliNB:")
print(classification_report(y_test, bnb_pred))
print(confusion_matrix(y_test, bnb_pred))

# So sánh hiệu suất bằng cross validation
print("\nCross Validation Results:")
mnb_scores = cross_val_score(mnb_pipeline, df.message, df.label_num, cv=5)
bnb_scores = cross_val_score(bnb_pipeline, df.message, df.label_num, cv=5)
print(f"MultinomialNB: {np.mean(mnb_scores):.4f} (+/- {np.std(mnb_scores):.4f})")
print(f"BernoulliNB: {np.mean(bnb_scores):.4f} (+/- {np.std(bnb_scores):.4f})")

# Phân loại tin nhắn mới
new_messages = [
    "Congratulations! You've won a $1000 gift card. Call now to claim.",
    "I'll be home by 6pm. Let's have dinner together.",
    "URGENT: Your bank account has been compromised. Click here to secure it."
]

print("\nPhân loại tin nhắn mới:")
mnb_result = mnb_pipeline.predict(new_messages)
for message, prediction in zip(new_messages, mnb_result):
    print(f"'{message[:50]}{'...' if len(message) > 50 else ''}': {'Spam' if prediction == 1 else 'Ham'}")

Naive Bayes trong kỷ nguyên Big Data và Deep Learning

Mặc dù Deep Learning đã trở nên phổ biến trong những năm gần đây, Naive Bayes vẫn có vị trí quan trọng trong hệ sinh thái học máy vì những lý do sau:

  1. Tốc độ và hiệu quả: Naive Bayes huấn luyện và dự đoán nhanh, phù hợp cho các ứng dụng thời gian thực và dữ liệu lớn.

  2. Ít dữ liệu huấn luyện: Trong khi Deep Learning thường đòi hỏi lượng dữ liệu lớn, Naive Bayes có thể hoạt động tốt với ít dữ liệu hơn.

  3. Dễ diễn giải: Kết quả của Naive Bayes dễ diễn giải hơn so với các mô hình "hộp đen" như Deep Learning.

  4. Hiệu quả trong một số miền cụ thể: Trong các bài toán phân loại văn bản, Naive Bayes vẫn có hiệu suất cạnh tranh.

  5. Baseline hữu ích: Naive Bayes thường được sử dụng làm baseline để so sánh với các mô hình phức tạp hơn.

So sánh Naive Bayes với các thuật toán phân loại khác

Thuật toán
Ưu điểm so với Naive Bayes
Nhược điểm so với Naive Bayes

Logistic Regression

Không giả định độc lập giữa các đặc trưng

Chậm hơn, đòi hỏi tối ưu hóa

Decision Trees

Nắm bắt được tương tác giữa các đặc trưng

Dễ bị overfitting, huấn luyện chậm hơn

SVM

Hiệu suất tốt hơn với không gian đặc trưng phức tạp

Chậm hơn, khó diễn giải

Random Forest

Hiệu suất cao hơn, ít bị overfitting

Chậm hơn, sử dụng nhiều bộ nhớ

Deep Learning

Hiệu suất tốt hơn với dữ liệu phức tạp

Đòi hỏi nhiều dữ liệu và tài nguyên tính toán

Kết luận

Naive Bayes, mặc dù đơn giản và dựa trên một giả định đơn giản hóa về độc lập giữa các đặc trưng, vẫn là một thuật toán học máy mạnh mẽ và hữu ích trong nhiều ứng dụng thực tế. Các biến thể của nó - Multinomial, Gaussian, Bernoulli, Complement và Categorical Naive Bayes - cung cấp sự linh hoạt để xử lý các loại dữ liệu khác nhau và giải quyết các bài toán đa dạng.

Thuật toán này đặc biệt phù hợp với các bài toán có nhiều đặc trưng, ít dữ liệu huấn luyện, và yêu cầu tốc độ xử lý nhanh. Trong kỷ nguyên của Big Data và Deep Learning, Naive Bayes vẫn giữ vai trò quan trọng như một baseline đáng tin cậy và một công cụ hiệu quả cho các bài toán phân loại đơn giản.

Hiểu rõ về cơ sở toán học, các biến thể, và cách áp dụng Naive Bayes sẽ giúp các nhà khoa học dữ liệu và kỹ sư máy học tận dụng tối đa sức mạnh của thuật toán đơn giản nhưng hiệu quả này.

Tài liệu tham khảo

  1. Murphy, K. P. (2012). Machine Learning: A Probabilistic Perspective. MIT Press.

  2. Manning, C. D., Raghavan, P., & Schütze, H. (2008). Introduction to Information Retrieval. Cambridge University Press.

  3. Zhang, H. (2004). The Optimality of Naive Bayes. AAAI.

  4. Rennie, J. D., Shih, L., Teevan, J., & Karger, D. R. (2003). Tackling the Poor Assumptions of Naive Bayes Text Classifiers. ICML.

  5. Scikit-learn: Machine Learning in Python, Pedregosa et al., JMLR 12, pp. 2825-2830, 2011.

Last updated