共计 2031 个字符,预计需要花费 6 分钟才能阅读完成。
背景介绍:朴素贝叶斯的数学原理
朴素贝叶斯是基于贝叶斯定理的分类方法,其核心公式为:

$$P(y|x_1,…,x_n) = \frac{P(y)\prod_{i=1}^n P(x_i|y)}{P(x_1,…,x_n)}$$
其中关键假设是特征条件独立性(即 $P(x_i|y,x_j)=P(x_i|y)$)。这种假设虽然 ” 朴素 ”,但在文本分类等高维稀疏场景中表现出色,因为:
- 计算复杂度仅随特征数量线性增长
- 对噪声数据不敏感
- 小样本也能取得不错效果
为什么选择文本分类作为案例
相比其他算法,朴素贝叶斯在文本领域有独特优势:
- 维度处理能力:词向量空间通常维度极高(数万维),而朴素贝叶斯天然适合高维数据
- 概率解释性:可直接输出分类概率,便于设置置信度阈值
- 效率对比:
- 比 SVM 训练速度快 10-100 倍
- 比神经网络更易调试
完整实现流程
数据预处理
import re
from sklearn.feature_extraction.text import CountVectorizer
def clean_text(text):
text = re.sub(r'<[^>]+>', '', text) # 去除 HTML 标签
text = re.sub(r'\d+', 'NUM', text) # 数字替换
return text.lower()
# 示例:中文分词需配合 jieba 等工具
import jieba
def chinese_cut(text):
return ' '.join(jieba.cut(text))
特征工程对比
| 方法 | 优点 | 缺点 |
|---|---|---|
| 词频统计 | 计算简单 | 忽略词语重要性差异 |
| TF-IDF | 降低高频词权重 | 需存储整个词表 |
from sklearn.feature_extraction.text import TfidfTransformer
tfidf = TfidfTransformer()
X_tfidf = tfidf.fit_transform(word_counts)
模型训练与评估
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report
# 多项式朴素贝叶斯(适合词频特征)model = MultinomialNB(alpha=1.0) # alpha 为平滑系数
model.fit(X_train, y_train)
# 评估
print(classification_report(y_test, model.predict(X_test)))
输出示例:
precision recall f1-score support
spam 0.98 0.96 0.97 742
legit 0.96 0.98 0.97 702
关键性能优化
稀疏矩阵处理
- 使用
scipy.sparse格式存储特征矩阵 - 设置
max_features限制词表大小 - 采用哈希技巧(
HashingVectorizer)
拉普拉斯平滑
数学形式:
$$\hat{P}(x_i|y) = \frac{count(x_i,y) + \alpha}{count(y) + \alpha n}$$
实际设置建议:
- 通常取 α =1(加一平滑)
- 对不平衡数据可尝试 α <1
常见问题解决方案
特征相关性问题
- 症状:当强相关特征存在时(如 ” 免费 ” 和 ” 领取 ”),朴素假设被破坏
- 解决方案:
- 使用互信息筛选特征
- 改用半朴素贝叶斯(如 TAN)
类别不平衡处理
# 方法 1:类别权重
model = MultinomialNB(class_prior=[0.3, 0.7])
# 方法 2:过采样
from imblearn.over_sampling import RandomOverSampler
ros = RandomOverSampler()
X_res, y_res = ros.fit_resample(X, y)
部署为 API 服务
使用 Flask 构建预测接口:
from flask import Flask, request
import pickle
app = Flask(__name__)
model = pickle.load(open('model.pkl','rb'))
@app.route('/predict', methods=['POST'])
def predict():
text = request.json['text']
vec = vectorizer.transform([clean_text(text)])
proba = model.predict_proba(vec)
return {'spam_prob': proba[0][1]}
延伸学习
- 理论进阶:
- 《机器学习》周志华 第 7 章
- 李航《统计学习方法》第 4 章
- 开源项目:
- scikit-learn 实现源码
- NLTK 文本处理工具包
- 生产级优化:
- 特征哈希(Feature hashing)
- 在线学习(partial_fit 方法)
通过本案例可以看到,朴素贝叶斯虽然算法简单,但在文本分类任务中仍是 baseline 的优选方案。特别是在需要快速验证 idea 或构建轻量级服务的场景下,它的性价比往往超乎预期。
正文完
