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

算法选型对比
- SVM:需要精细的特征工程,在文本高维空间计算成本高
- 深度学习:依赖 GPU 和大量数据,模型解释性差
- 朴素贝叶斯:
- 小数据友好:1000 条样本就能达到实用效果
- 数学可解释:每个预测结果都能追溯概率来源
- 训练速度快: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:将连乘转为累加防止数值下溢
生产环境优化
-
特殊字符:
import re email = re.sub(r'[^\w\s]', '', email) # 保留字母数字和空格 -
增量训练:
# 更新词频统计 spam_word_count += new_spam_data.sum(axis=0) # 重新计算概率时保留原始平滑项 -
内存优化:
# 使用稀疏矩阵存储 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. 新类别:使用半监督学习,置信度高的预测自动加入训练集
通过这个实践项目,我们验证了朴素贝叶斯 ” 简单即有效 ” 的哲学。虽然假设特征独立(这就是 ” 朴素 ” 的由来),但在文本分类任务中往往能超越复杂模型。
正文完
发表至: 未分类
近两天内
