Naive Bayes
Naive Bayes is a family of classification algorithms based on Bayes' Theorem, with the "naive" assumption that each feature is independent of the others. Although this assumption is not always true, the algorithm often works very well in practice.
Bayes' Theorem
P(A|B) = P(B|A) × P(A) / P(B)
In the context of classification:
P(class|features) = P(features|class) × P(class) / P(features)
The Naive Assumption
Assumption: all features are independent of each other:
P(x1,x2,...,xn|class) = P(x1|class) × P(x2|class) × ... × P(xn|class)
Although this assumption is rarely true in reality, Naive Bayes remains effective in many cases.
Types of Naive Bayes
| Type | Distribution | Use Case |
|---|---|---|
| Gaussian | Normal | Continuous features |
| Multinomial | Multinomial | Count data (TF-IDF) |
| Bernoulli | Bernoulli | Binary features |
from sklearn.naive_bayes import GaussianNB, MultinomialNB, BernoulliNB
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target, test_size=0.2, random_state=42
)
models = {
'GaussianNB': GaussianNB(),
'MultinomialNB': MultinomialNB(),
}
for name, model in models.items():
model.fit(X_train, y_train)
acc = model.score(X_test, y_test)
print(f"{name}: {acc:.4f}")
Example: Spam Detection
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
emails = [
"Congratulations, you have won a prize drawing",
"Meeting tomorrow at 9 AM",
"Click this link to claim your bonus",
"The Q3 financial report is done",
"Big discount promo today",
"Reminder: project presentation tomorrow",
"You have been selected to win a car",
"Please review the document that has been sent"
]
labels = [1, 0, 1, 0, 1, 0, 1, 0] # 1=spam, 0=ham
pipeline = make_pipeline(CountVectorizer(), MultinomialNB())
pipeline.fit(emails, labels)
test_emails = [
"You won the raffle! Claim now",
"Don't forget the meeting at 3 PM"
]
prediction = pipeline.predict(test_emails)
for email, pred in zip(test_emails, prediction):
print(f"'{email[:40]}...' → {'SPAM' if pred == 1 else 'HAM'}")
Comparing the Three Types
from sklearn.datasets import load_wine
from sklearn.model_selection import cross_val_score
from sklearn.naive_bayes import GaussianNB, MultinomialNB, BernoulliNB
from sklearn.preprocessing import MinMaxScaler
wine = load_wine()
X, y = wine.data, wine.target
models = {
'GaussianNB': GaussianNB(),
'MultinomialNB': MultinomialNB(),
'BernoulliNB': BernoulliNB(),
}
for name, model in models.items():
if name == 'MultinomialNB':
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)
scores = cross_val_score(model, X_scaled, y, cv=5)
elif name == 'BernoulliNB':
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)
scores = cross_val_score(model, X_scaled > 0.5, y, cv=5)
else:
scores = cross_val_score(model, X, y, cv=5)
print(f"{name:15s}: {scores.mean():.4f} (+/- {scores.std():.4f})")
Pros and Cons
| Pros | Cons |
|---|---|
| Very fast | Independence assumption |
| Suits high-dimensional data | Less accurate than complex models |
| Great for baselines | Zero frequency problem |
| Does not require much data | Probability output is less accurate |
| Easy to implement | Does not handle correlated features |
Practical Tips
- Use GaussianNB for continuous features
- Use MultinomialNB for text classification (TF-IDF, counts)
- Use BernoulliNB for binary/boolean features
- Handle the zero frequency problem with Laplace smoothing (alpha parameter)
In the next chapter we enter the world of unsupervised learning: K-Means Clustering.