从零实现朴素贝叶斯算法:11行Python代码构建垃圾邮件分类器

1次阅读
没有评论

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

image.webp

为什么需要垃圾邮件分类

垃圾邮件过滤是邮箱系统的刚需功能,每年能帮助企业节省数百小时无效沟通时间。传统规则过滤容易被绕过,而深度学习需要大量标注数据。朴素贝叶斯在准确率 (92% F1) 和实现成本 (11 行代码) 间取得了完美平衡。

从零实现朴素贝叶斯算法:11 行 Python 代码构建垃圾邮件分类器

算法选型对比

  1. SVM:需要精细的特征工程,在文本高维空间计算成本高
  2. 深度学习:依赖 GPU 和大量数据,模型解释性差
  3. 朴素贝叶斯
  4. 小数据友好:1000 条样本就能达到实用效果
  5. 数学可解释:每个预测结果都能追溯概率来源
  6. 训练速度快:O(n)时间复杂度,适合增量更新

核心实现步骤

文本预处理

from sklearn.feature_extraction.text import CountVectorizer

# 中文需替换为 jieba 分词
vectorizer = CountVectorizer(stop_words='english', max_features=5000)
X = vectorizer.fit_transform(emails)  # emails 为邮件文本列表
  • stop_words:自动过滤 ”the”,”and” 等无意义词
  • max_features:限制词袋维度避免内存溢出

概率计算与平滑

import numpy as np

# 计算先验概率 P(spam)
spam_prior = (y_train == 1).mean()  # y_train 为标签

# 统计词频
spam_word_count = X[y_train == 1].sum(axis=0) + 1  # 拉普拉斯平滑
ham_word_count = X[y_train == 0].sum(axis=0) + 1

# 计算条件概率 P(word|spam)
spam_probs = (spam_word_count) / (spam_word_count.sum() + vocab_size)
ham_probs = (ham_word_count) / (ham_word_count.sum() + vocab_size)
  • +1+vocab_size:拉普拉斯平滑避免零概率
  • 公式:$P(spam|words) \propto P(spam)\prod_{i}P(word_i|spam)$

完整分类器

class NaiveBayesClassifier:
    def predict(self, email):
        word_vec = vectorizer.transform([email])
        spam_score = np.log(self.spam_prior) + word_vec @ np.log(self.spam_probs.T)
        ham_score = np.log(1-self.spam_prior) + word_vec @ np.log(self.ham_probs.T)
        return 1 if spam_score > ham_score else 0
  • @:矩阵乘法计算联合概率
  • np.log:将连乘转为累加防止数值下溢

生产环境优化

  1. 特殊字符

    import re
    email = re.sub(r'[^\w\s]', '', email)  # 保留字母数字和空格

  2. 增量训练

    # 更新词频统计
    spam_word_count += new_spam_data.sum(axis=0)
    # 重新计算概率时保留原始平滑项

  3. 内存优化

    # 使用稀疏矩阵存储
    from scipy import sparse
    spam_word_count = sparse.csr_matrix(spam_word_count)

评估与思考

from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

思考题答案提示
1. 变体邮件:引入字符级 n -gram 特征
2. 新类别:使用半监督学习,置信度高的预测自动加入训练集

通过这个实践项目,我们验证了朴素贝叶斯 ” 简单即有效 ” 的哲学。虽然假设特征独立(这就是 ” 朴素 ” 的由来),但在文本分类任务中往往能超越复杂模型。

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