Skip to content

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

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

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


生活引入

邮箱的垃圾邮件过滤

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

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


直观理解

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

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

Python 动手实践

实例

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}】")
python
RUNOOB 朴素贝叶斯分类结果:

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

AI 中的应用场景

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

AI 思考中...

最大似然估计找到「最像」的分布参数

手算交叉熵损失

基于 VitePress 构建,部署于 GitHub Pages