朴素贝叶斯案例实战:从垃圾邮件过滤到文本分类的完整实现

1次阅读
没有评论

共计 2031 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景介绍:朴素贝叶斯的数学原理

朴素贝叶斯是基于贝叶斯定理的分类方法,其核心公式为:

朴素贝叶斯案例实战:从垃圾邮件过滤到文本分类的完整实现

$$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)$)。这种假设虽然 ” 朴素 ”,但在文本分类等高维稀疏场景中表现出色,因为:

  • 计算复杂度仅随特征数量线性增长
  • 对噪声数据不敏感
  • 小样本也能取得不错效果

为什么选择文本分类作为案例

相比其他算法,朴素贝叶斯在文本领域有独特优势:

  1. 维度处理能力:词向量空间通常维度极高(数万维),而朴素贝叶斯天然适合高维数据
  2. 概率解释性:可直接输出分类概率,便于设置置信度阈值
  3. 效率对比
  4. 比 SVM 训练速度快 10-100 倍
  5. 比神经网络更易调试

完整实现流程

数据预处理

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(加一平滑)
  2. 对不平衡数据可尝试 α <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]}

延伸学习

  1. 理论进阶
  2. 《机器学习》周志华 第 7 章
  3. 李航《统计学习方法》第 4 章
  4. 开源项目
  5. scikit-learn 实现源码
  6. NLTK 文本处理工具包
  7. 生产级优化
  8. 特征哈希(Feature hashing)
  9. 在线学习(partial_fit 方法)

通过本案例可以看到,朴素贝叶斯虽然算法简单,但在文本分类任务中仍是 baseline 的优选方案。特别是在需要快速验证 idea 或构建轻量级服务的场景下,它的性价比往往超乎预期。

正文完
 0
评论(没有评论)