共计 2699 个字符,预计需要花费 7 分钟才能阅读完成。
为什么选择朴素贝叶斯?
在文本分类领域,我们常常遇到两个典型场景:

- 垃圾邮件过滤:需要快速判断新邮件是否属于垃圾邮件,处理大量用户请求时要求低延迟
- 新闻分类:将新闻自动归类到财经、体育等板块,特征维度常高达数万维
朴素贝叶斯算法在这些场景表现出独特优势:
- 训练速度快,适合高维特征
- 内存占用低,便于线上部署
- 对缺失数据有一定鲁棒性
核心原理拆解
贝叶斯定理基础
分类问题本质是求最大后验概率:
$$P(y|x_1,x_2,…,x_n) = \frac{P(y)P(x_1,x_2,…,x_n|y)}{P(x_1,x_2,…,x_n)}$$
其中:
– $P(y)$ 是先验概率
– $P(x|y)$ 是似然概率
– 分母 $P(x)$ 对所有类别相同,实践中可忽略
朴素假设的利与弊
关键假设:特征条件独立
$$P(x_1,x_2,…,x_n|y) = \prod_{i=1}^n P(x_i|y)$$
工程价值:
– 将联合概率分解为乘积,避免维度灾难
– 只需存储各特征的边缘分布
现实局限:
– 实际文本中词语间存在关联(如 ” 机器学习 ” 常整体出现)
– 可通过特征组合部分缓解
概率估计方法对比
- 最大似然估计
$$P(w_i|c) = \frac{count(w_i,c)}{\sum_w count(w,c)}$$ -
问题:未登录词概率为 0 会导致连乘归零
-
拉普拉斯平滑
$$P(w_i|c) = \frac{count(w_i,c)+1}{\sum_w (count(w,c)+1)}$$ - 保证所有词都有非零概率
- 超参数 α 可调整(如 α =0.1)
Python 实现详解
特征工程:TF-IDF 转换
from sklearn.feature_extraction.text import TfidfVectorizer
# 示例语料
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names_out())
分类器核心逻辑
import numpy as np
from scipy.sparse import csr_matrix
class NaiveBayesClassifier:
def __init__(self, alpha=1.0):
self.alpha = alpha # Laplace smoothing factor
self.class_prob = None
self.feature_prob = None
def fit(self, X: csr_matrix, y):
n_samples, n_features = X.shape
self.classes = np.unique(y)
n_classes = len(self.classes)
# Calculate class priors
self.class_prob = np.zeros(n_classes)
for i, c in enumerate(self.classes):
self.class_prob[i] = np.sum(y == c) / n_samples
# Compute feature likelihood with smoothing
self.feature_prob = np.zeros((n_classes, n_features))
for i, c in enumerate(self.classes):
class_mask = (y == c)
N_c = X[class_mask].sum(axis=0) # Word counts per class
total_c = N_c.sum() # Total words in class
# Laplace smoothing
self.feature_prob[i] = (N_c + self.alpha) / (total_c + self.alpha * n_features)
def predict(self, X):
# Logarithm to avoid underflow
log_probs = np.log(self.feature_prob) @ X.T + np.log(self.class_prob[:, np.newaxis])
return self.classes[np.argmax(log_probs, axis=0)]
关键实现细节:
– 使用稀疏矩阵存储(csr_matrix)节约内存
– 对数运算防止概率连乘下溢
– 支持自定义平滑系数 α
生产环境优化策略
稀疏矩阵处理
- 使用
scipy.sparse格式存储特征矩阵 - 零值不占存储空间
- 矩阵运算时自动跳过零值计算
增量训练实现
def partial_fit(self, X_batch, y_batch):
if self.class_prob is None: # First batch
self.fit(X_batch, y_batch)
else:
# Update class counts
new_class_counts = np.array([np.sum(y_batch == c) for c in self.classes])
total_samples = len(y_batch) + np.sum(self.class_prob * self.n_samples)
# Update feature counts (requires storing original counts)
for i, c in enumerate(self.classes):
class_mask = (y_batch == c)
self.feature_counts[i] += X_batch[class_mask].sum(axis=0)
# Recompute probabilities
self._update_probs(total_samples)
生产环境注意事项
类别不平衡处理
- 重采样技术
- 对少数类过采样(如 SMOTE)
-
对多数类欠采样
-
代价敏感学习
- 调整决策阈值
- 修改损失函数权重
模型监控指标
- 实时记录预测置信度分布
- 设置精度 / 召回率报警阈值
- 定期检测特征分布漂移
思考与延伸
- 特征组合优化:如何自动发现强关联的特征对(如 bigram)来缓解朴素假设限制?
- 混合建模:能否结合 BERT 等深度学习模型处理长文本,同时保留朴素贝叶斯的效率优势?
在实践中,朴素贝叶斯往往能提供令人惊讶的 baseline 效果。虽然理论假设过于理想化,但正是这种简单性使其成为文本分类任务中的瑞士军刀——不一定是最强大的工具,但绝对值得首先尝试。
正文完
