朴素贝叶斯-学习笔记

简介: 朴素贝叶斯标签(空格分隔): 机器学习朴素贝叶斯算法适合给文档分类。词向量先对文档分词,所有文档中所有不同的词构成词汇表。每个文档根据词汇表能形成一个词向量,1表示对应维度的词条出现在文档中,0表示词条未出现。

朴素贝叶斯

标签(空格分隔): 机器学习


朴素贝叶斯算法适合给文档分类。

词向量

先对文档分词,所有文档中所有不同的词构成词汇表。每个文档根据词汇表能形成一个词向量,1表示对应维度的词条出现在文档中,0表示词条未出现。

这种想法推广开来,发现向量是新时代的数字
比如一个可能发生的事件集合,可以表示为一个向量,每个维度对应一个事件发生的概率。

问题描述

任给一个文档,怎样确定其分类?
每个文档对应一个词向量$\vec w$,需要确定$p(c_i|\vec w)$的最大值,即:已知这个文档的条件下,把这个文档归为哪个类的概率最大?

朴素贝叶斯

$$
分类(\vec w) = p(c_i|\vec w)_{max}=\frac{p(\vec w|c_i)p(c_i)}{p(\vec w)}
$$
其中$\vec w$表示词向量。对于任意一个分类$c_i$,$p(\vec w)$是相同的,因而只需要确定$p(\vec w|c_i)$和$p(c_i)$。

$p(c_i)$:从训练数据中,用简单除法得到。
$p(\vec w|c_i)$:根据朴素贝叶斯假设,特征向量$\vec w$在$c_i$条件下相互独立,也就是:给定目标值时属性之间相互条件独立
$$
p(\vec w|c_i)=\Pi p(w_j|c_i)
$$
而对于$p(w_j|c_i)$,只需要在扫描训练数据时,依据$c_i$过滤数据项,在这些被过滤出的数据中(都是$c_i$类的),用简单统计的结果相除,就得到在$j$维上的概率权值$e(w_j|c_i)$。为什么不是$p(w_j|c_i)$?因为最终要计算的是一个未知分类的向量$\vec x$的分类,需要将$\vec x$与概率权值向量$\vec e$对应位相乘,这才得到$p(w_j|c_i)$序列。$\vec x$中的元素非1即0,如果元素为1,那么$p(w_j|c_i)$就取$e(w_j|c_i)$,否则取0。

简单优化

条件概率乘积为0

$p(\vec w|c_i)=\Pi p(w_j|c_i)$这个公式中,一旦$p(w_j|c_i)$等于0,整个结果就是0。但是对于$\vec w$,你怎样判断$\Pi p(w_j|c_i)=0$的所有$c_i$,该如何判断哪个$c_i$更好?万一所有的$c_i$对应的$p(\vec w|c_i)=\Pi p(w_j|c_i)$都等于0,该怎样确定最终的分类?因此,要避免某个$p(w_j|c_i)$等于0。一个办法是使用拉普拉斯平滑:将所有词的出现数初始化为1,并将分母初始化为2。对应《机器学习实战》中文版P62的代码:

p0Num = onew(numWords)
p1Num = ones(numWords)
p0Denom = 2.0
p1Denom = 2.0

条件概率乘积下溢

相乘的都是概率,都是小于1的数,乘不了几次就得到非常小的数字,产生下溢,干扰比较。一个方法是用取对数。没错,就是这么老套的办法,但是管用,因为$\forall x \in (0,1)$,x越小,$\log x$的绝对值越大,或者说负的程度越大。对于$p(\vec w|c_i)=\Pi p(w_j|c_i)$取对数,就是一堆负数相加。这种情形下对于任意的$\vec x$是很方便的。

当然,公式中还有一个$p(c_i)$,也需要对数处理后相加。

代码

使用分类器

在训练阶段我们只计算$e(\vec w|c_i)$,这其实就是训练出来的分类器。一旦完成训练,就可以使用分类器:

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    """
    @param vec2Classify: 需要被分类的词向量
    @param p0Vec: 第0类对应的词概率向量
    @param p1Vec: 第1类对应的词概率向量
    @param 
    """
    p1=sum(vec2Classify*p1Vec) + np.log(pClass1)
    p0=sum(vec2Classify*p0Vec) + np.log(1.0-pClass1)
    if p1>p0:
        return 1
    else:
        return 0

训练模型

使用训练数据,训练出分类器,也就是获取$e(\vec w|c_i)$和$e(c_i)$。同时修正了《机器学习实战》P61的一个bug,即对于$p1Vect和p0Vect的计算,分母应当是训练数据对应类的向量总数,而不是元素总和$:

def trainNB0(trainMatrix, trainCategory):
    """
    朴素贝叶斯分类器训练函数:计算P(\vec w|c_1)和P(\vec w|c_2)
    @param trainMatrix:训练矩阵
    @param trainCategory: 和trainMatrix配套使用的向量,表示每个trainMatrix[i]所属类别
    
    """
    numTrainDocs = len(trainMatrix)  #文档总数
    numWords=len(trainMatrix[0])  #向量维数:不重复的单词数量
    pAbusive=sum(trainCategory)/float(numTrainDocs)
    p0Num=np.ones(numWords)
    p1Num=np.ones(numWords)
    p0Denom=2.0
    p1Denom=2.0
    for i in range(numTrainDocs):
        if trainCategory[i]==1:
            p1Num += trainMatrix[i]
            #p1Denom += sum(trainMatrix[i])  ##去掉这句
        else:
            p0Num += trainMatrix[i]
            #p0Denom += sum(trainMatrix[i])  ##去掉这句
    #p1Vect = p1Num/p1Denom  ##书上这句是错的
    #p0Vect = p0Num/p0Denom  ##这句也是错的
    
    num_c1 = sum(trainCategory)
    num_c0 = len(trainCategory) - num_c1
    p1Vect = log(p1Num / num_c1)   #这才正确的是p(\vec w|c_1)
    p0Vect = log(p0Num / num_c0)   #这才正确的是p(\vec w|c_0)
    
    return p0Vect, p1Vect, pAbusive #pAbusive就是p(c_1)

理论上到这里就算出了基本的表达式,可以用来比较了。

总结

感觉《机器学习实战》第四章朴素贝叶斯对于取对数的说明不够清楚,使用分类器时的向量相乘更是没有任何说明,让人一头雾水。不过章节后面的垃圾邮件分类和词语倾向性的例子还不错~

目录
相关文章
|
1天前
|
云安全 人工智能 自然语言处理
|
6天前
|
搜索推荐 编译器 Linux
一个可用于企业开发及通用跨平台的Makefile文件
一款适用于企业级开发的通用跨平台Makefile,支持C/C++混合编译、多目标输出(可执行文件、静态/动态库)、Release/Debug版本管理。配置简洁,仅需修改带`MF_CONFIGURE_`前缀的变量,支持脚本化配置与子Makefile管理,具备完善日志、错误提示和跨平台兼容性,附详细文档与示例,便于学习与集成。
314 116
|
8天前
|
数据采集 人工智能 自然语言处理
Meta SAM3开源:让图像分割,听懂你的话
Meta发布并开源SAM 3,首个支持文本或视觉提示的统一图像视频分割模型,可精准分割“红色条纹伞”等开放词汇概念,覆盖400万独特概念,性能达人类水平75%–80%,推动视觉分割新突破。
610 53
Meta SAM3开源:让图像分割,听懂你的话
|
21天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
5天前
|
人工智能 Java API
Java 正式进入 Agentic AI 时代:Spring AI Alibaba 1.1 发布背后的技术演进
Spring AI Alibaba 1.1 正式发布,提供极简方式构建企业级AI智能体。基于ReactAgent核心,支持多智能体协作、上下文工程与生产级管控,助力开发者快速打造可靠、可扩展的智能应用。
|
4天前
|
弹性计算 人工智能 Cloud Native
阿里云无门槛和有门槛优惠券解析:学生券,满减券,补贴券等优惠券领取与使用介绍
为了回馈用户与助力更多用户节省上云成本,阿里云会经常推出各种优惠券相关的活动,包括无门槛优惠券和有门槛优惠券。本文将详细介绍阿里云无门槛优惠券的领取与使用方式,同时也会概述几种常见的有门槛优惠券,帮助用户更好地利用这些优惠,降低云服务的成本。
270 132
|
8天前
|
机器学习/深度学习 人工智能 自然语言处理
AgentEvolver:让智能体系统学会「自我进化」
AgentEvolver 是一个自进化智能体系统,通过自我任务生成、经验导航与反思归因三大机制,推动AI从“被动执行”迈向“主动学习”。它显著提升强化学习效率,在更少参数下实现更强性能,助力智能体持续自我迭代。开源地址:https://github.com/modelscope/AgentEvolver
423 29
|
15天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
728 224