现在位置: 首页 > AI 数学基础 > 正文

朴素贝叶斯垃圾邮件分类器

用最基础的条件概率公式实现一个简单的中文垃圾邮件分类器,不调 sklearn。

学完本案例你将理解:贝叶斯定理 + 「各词独立」假设 = 一个能用的文本分类器。


生活引入

邮箱的垃圾邮件过滤

你的邮箱每天收到 100 封邮件。怎么让程序自动判断一封新邮件是不是垃圾邮件?程序的做法:统计历史邮件中,垃圾邮件里出现「免费」「中奖」这些词的概率,以及正常邮件里出现「会议」「项目」的概率。

新邮件来了,算一下:在垃圾邮件的假设下这些词同时出现的概率 vs 在正常邮件的假设下。谁大就判给谁。


直观理解

朴素贝叶斯的关键简化——「朴素假设」:假设各个词出现与否是相互独立的。虽然这个假设在现实中不成立(「免费」和「奖品」经常一起出现),但实用效果却出奇地好。

技巧做法解决的问题
对数概率用 log 将连乘转为连加很多小数连乘会变成 0(数值下溢)
拉普拉斯平滑每个词计数 +1 而不是 +0训练集里没见过的词导致概率为 0

Python 动手实践

实例

from collections import defaultdict
import math

# 训练数据(8 条标注好的中文短信)
train_data = [
    ("赢取 免费 奖品 立即 点击", "spam"),
    ("恭喜 中奖 领取 现金 优惠", "spam"),
    ("限时 优惠 点击 链接 免费", "spam"),
    ("贷款 低息 立即 申请 现金", "spam"),
    ("会议 安排 明天 上午 讨论", "ham"),
    ("项目 进度 汇报 会议 记录", "ham"),
    ("周末 聚餐 安排 大家 参加", "ham"),
    ("报告 数据 分析 项目 完成", "ham"),
]

# 统计每个类别的词频
class_word_counts = defaultdict(lambda: defaultdict(int))
class_doc_counts = defaultdict(int)
vocab = set()

for text, label in train_data:
    class_doc_counts[label] += 1
    for word in text.split():
        class_word_counts[label][word] += 1
        vocab.add(word)

vocab_size = len(vocab)
total_docs = len(train_data)

# 朴素贝叶斯分类(对数概率 + 拉普拉斯平滑)
def predict(text, alpha=1.0):
    words = text.split()
    scores = {}
    for label in class_doc_counts:
        log_prob = math.log(class_doc_counts[label] / total_docs)
        total_words = sum(class_word_counts[label].values())
        for word in words:
            word_count = class_word_counts[label][word]
            word_prob = (word_count + alpha) / (total_words + alpha * vocab_size)
            log_prob += math.log(word_prob)
        scores[label] = log_prob
    return max(scores, key=scores.get), scores

# 测试
test_emails = [
    "免费 领取 现金 奖品",
    "明天 会议 项目 汇报",
    "限时 点击 优惠 链接",
    "周末 大家 一起 讨论 报告",
]

print("RUNOOB 朴素贝叶斯分类结果:\n")
for email in test_emails:
    label, scores = predict(email)
    print(f"  {email!r:28s} -> 【{label}】")
RUNOOB 朴素贝叶斯分类结果:

  '免费 领取 现金 奖品'          -> 【spam】
  '明天 会议 项目 汇报'           -> 【ham】
  '限时 点击 优惠 链接'           -> 【spam】
  '周末 大家 一起 讨论 报告'       -> 【ham】

AI 中的应用场景

场景说明
文本分类垃圾邮件过滤、新闻分类、情感分析——朴素贝叶斯是经典 baseline
文档主题建模LDA(Latent Dirichlet Allocation)的数学基础
异常检测计算新样本属于「正常分布」的概率,太低则判为异常