贝叶斯算法

公式:

通俗解释: 当 B 发生后,A 的概率如何变化

四个关键概念

  1. 先验概率:没做实验前的初始猜测 P(A)
  2. 似然度:假设成立时看到数据的可能性 P(B|A)
  3. 证据:数据本身出现的总概率 P(B)
  4. 后验概率:看到数据后的修正猜测 P(A|B)

朴素贝叶斯

简单假设:特征之间是独立的,互相不影响的。

  • 高斯朴素贝叶斯:连续数据(如身高、温度),鸢尾花分类 GaussianNB()
  • 多项式朴素贝叶斯:离散计数(如文本词频),新闻分类/垃圾邮件过滤 MultinomialNB()
  • 伯努利朴素贝叶斯:二值特征(0/1),用户行为分析 BernoulliNB()

模型比较理论

最大似然: 最符合观测数据的最有优势 P(B|A)

奥卡姆剃刀: P(A) 先验概率比较大的模型具有较大的优势(什么越常见什么就越好:如无必要,勿增实体)——如果一个问题有多个解决方案,选择最简单、假设最少的那一个

拉普拉斯平滑

背景:朴素贝叶斯分类中,若某个特征在训练集的某类别中从未出现,直接计算其条件概率时会得到零值,导致后续的联合概率乘积失效

目标:通过对特征计数进行微小调整,避免因训练数据不足导致的条件概率为零的情况,从而提高模型的鲁棒性。

原始条件概率公式:

加入拉普拉斯平滑(狄利克雷先验分布的特殊情况)后:

(a为平滑系数:一般=1,N为特征x_i 的可能取值数量)

垃圾邮箱过滤

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# === 1. 全局配置 ===
# 解决中文显示和Matplotlib警告
plt.rcParams['font.sans-serif'] = ['SimHei']  # 中文字体
plt.rcParams['axes.unicode_minus'] = False    # 修复负号显示
import matplotlib
matplotlib.use('TkAgg')  # 非交互式后端,避免警告


# 朴素贝叶斯算法 做垃圾邮箱过滤


# 1. 准备数据(示例数据)
emails = [
    # 垃圾邮件 (50条)
    "恭喜您中奖了 点击链接领取万元大奖", "限时免费领取苹果手机", "双十一全场五折 立即抢购",
    "无需抵押快速贷款 电话13800001111", "澳门赌场开业 注册送8888元", "高薪兼职 日结300元",
    "您的账户异常 点击验证身份", "百万红包雨 点击领取", "特价机票99元起 马上预订",
    "微信转账888元即可获赠礼品", "您的信用卡可提额至10万", "网红面膜买一送一 限时抢购",
    "投资虚拟货币 月收益30%", "恭喜获得最新iPhone 点击领取", "内部员工价 名牌包2折",
    "您的ETC认证已过期 点击更新", "明星同款服饰三折起", "免费参加理财讲座 月入十万",
    "您的快递已丢失 点击索赔", "扫码加入会员领100元红包", "酒店特价房99元 限时抢订",
    "学历提升 免考拿本科文凭", "您的微信红包尚未领取", "春节红包大派送 点击领取",
    "股票内幕消息 稳赚不赔", "0首付购车 立即申请", "信用卡逾期处理 联系王经理",
    "您的会员资格即将过期 点击续费", "网红零食全场买二送一", "医疗美容特惠 打针5折",
    "您的手机号码中奖了 兑奖", "别墅清盘价 每平仅2万", "扫码测姻缘 免费看手相",
    "高仿名表 支持专柜验货", "您的社保账户需要更新", "电竞酒店特价 学生半价",
    "代办各种证件 当天可取", "您的微信账户存在风险", "茅台酒厂内部价 直降千元",
    "免费领取智能手表 邮费到付", "您的快递已到达 点击查收", "考公务员保过班 协议退费",
    "银行系统升级 点击验证", "黄金价格暴跌 立即抄底", "您的航班取消 点击改签",
    "别墅装修设计 免费报价", "微信红包未领取 即将过期", "您的微博账号异常登录",
    "海外代购正品保证 假一赔十", "扫码领养宠物 免费送狗粮",

    # 正常邮件 (50条)
    "项目进度会议本周五下午三点", "请查收附件中的季度财务报表", "团建活动安排征求意见",
    "新员工入职培训日程安排", "服务器维护通知:今晚10点至12点", "关于调整食堂用餐时间的通知",
    "2023年度体检预约开始", "研发部周报已上传至共享平台", "办公楼空调系统检修通知",
    "客户需求变更后的方案讨论", "年度优秀员工评选标准公示", "财务报销新系统操作指南",
    "部门预算调整需要重新审批", "新版本测试环境部署完成", "合作伙伴来访接待流程",
    "公司邮箱系统升级注意事项", "端午节放假安排及值班表", "网络安全知识培训通知",
    "办公楼消防演习时间调整", "研发代码提交规范更新说明", "客户投诉处理流程优化方案",
    "新员工导师分配名单确认", "年度旅游目的地投票统计", "会议室预定系统使用指南",
    "公司班车路线调整征求意见", "办公用品采购清单请审批", "季度绩效考核表填写提醒",
    "技术分享会主题征集通知", "新劳动合同版本签署安排", "公司年会节目报名开始",
    "数据中心迁移风险评估报告", "员工子女入学政策咨询", "专利申请流程培训通知",
    "新考勤系统试运行问题反馈", "部门团建经费使用公示", "公司战略调整说明会通知",
    "客户满意度调查结果分析", "新员工转正答辩安排表", "办公楼节能改造方案讨论",
    "研发设备采购需求收集", "年度调薪方案征求意见稿", "新客户签约流程优化建议",
    "产品发布会的媒体邀请名单", "公司文化墙设计方案投票", "技术职称评定材料提交",
    "疫情期间居家办公指南", "新仓库管理系统培训通知", "员工商业保险方案选择",
    "季度销售冠军表彰会流程", "公司官网改版需求讨论会"
]

labels = [1]*50 + [0]*50  # 前50条为垃圾邮件(1),后50条为正常邮件(0)

# 2. 文本转数字特征(核心步骤!)     把一堆文本变成数字矩阵,每个数字代表某个词在文本中出现的次数
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(emails)
print("特征词汇表:", vectorizer.get_feature_names_out())
# 输出:['优惠券', '免费', '发送', '恭喜您', '明天', '季度', '领取', '点击', '报告', '开会', '讨论', '中奖了']

# 3. 划分训练集/测试集
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.25)

# 4. 训练模型(注意alpha=1是拉普拉斯平滑)
model = MultinomialNB(alpha=1)
model.fit(X_train, y_train)

# 5. 预测与评估
y_pred = model.predict(X_test)
# zero_division=0: 允许未预测类别的指标为0
print(classification_report(y_test, y_pred,zero_division=0))

# 6. 新邮件预测
new_email = ["免费开会讨论中奖"]
new_X = vectorizer.transform(new_email)
print("预测概率:", model.predict_proba(new_X))  # 输出:[[0.3, 0.7]] → 70%概率是垃圾邮件