朴素贝叶斯分类器_sklearn朴素贝叶斯分类器

朴素贝叶斯分类器_sklearn朴素贝叶斯分类器所谓分类,就是根据事物的特征(Feature)对其归类(Class)特征的数据特点有两种可能:1.离散/标签2.连续/浮点数(大样本/小样本)下面我们分别来看一、离散/标签这是一个病人

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

 

所谓分类,就是根据事物的特征(Feature)对其归类(Class)

 

 特征的数据特点有两种可能:

  1. 离散/标签

  2. 连续/浮点数(大样本/小样本)

 

下面我们分别来看

一、离散/标签

这是一个病人分类的例子

某个医院早上收了六个门诊病人,如下表。

  症状  职业   疾病

  打喷嚏 护士   感冒
  打喷嚏 农夫   过敏
  头痛  建筑工人 脑震荡
  头痛  建筑工人 感冒
  打喷嚏 教师   感冒
  头痛  教师   脑震荡

现在又来了第七个病人,是一个打喷嚏建筑工人。请问他患上感冒的概率有多大?

 

根据贝叶斯定理

 P(A|B) = P(B|A) P(A) / P(B)

可得

   P(感冒|打喷嚏x建筑工人)
    = P(打喷嚏x建筑工人|感冒) x P(感冒)
    / P(打喷嚏x建筑工人)

假定”打喷嚏”和”建筑工人”这两个特征是独立的,因此,上面的等式就变成了

   P(感冒|打喷嚏x建筑工人)
    = P(打喷嚏|感冒) x P(建筑工人|感冒) x P(感冒)
    / P(打喷嚏) x P(建筑工人)

 

如何计算: P(打喷嚏|感冒)?

特征1:病人症状统计表

  打喷嚏 头痛 合计
感冒  2  1 3
过敏  1  0 1
脑震荡  0  2 2
合计 3 3 6

 

 

          P(打喷嚏|感冒) = 2/3 = 0.67

 

 

 

如何计算: P(建筑工人|感冒)?

特征2:病人职业统计表

  护士 农夫 建筑工人 教师 合计
感冒  1  0 1 1 3
过敏  0  1 0 0 1
脑震荡  0  0 1 1 2
合计 1 1 2 2 6

 

 

        P(建筑工人|感冒) = 1/3 = 0.33

 

 

 

因此,这个打喷嚏的建筑工人,得了感冒的概率不难计算得:

   P(感冒|打喷嚏x建筑工人)
    = P(打喷嚏|感冒) x P(建筑工人|感冒) x P(感冒)
    / P(打喷嚏) x P(建筑工人)

           = 0.67 x 0.33 x 0.5 / 0.5 x 0.33
    = 0.67

同理,可以计算这个病人患上过敏或脑震荡的概率。比较这几个概率,就可以知道他最可能得什么病。

这就是贝叶斯分类器的基本方法:在统计资料的基础上,依据某些特征,计算各个类别的概率,从而实现分类。

 

注意,

1. 为了简化计算,朴素贝叶斯算法做了一假设:“朴素的认为各个特征相互独立”。

2. 其次,如果只是得到最大值对应的那个作为其分类,那么,我们可以省略分母计算,从而进一步简化计算过程

3. 贝叶斯公式推导能够成立有个重要前期,就是各个证据(evidence)不能为0。也即对于任意特征Fx,P(Fx)不能为0。而显示某些特征未出现在测试集中的情况是可以发生的。因此实现上通常要做一些小的处理,例如把所有计数进行+1加法平滑(additive smoothing,又叫拉普拉斯平滑(Laplace smothing))。而如果通过增加一个大于0的可调参数alpha进行平滑,就叫Lidstone平滑

例如,在所有6个分为C=1的影评样本中,某个特征F1=1不存在,则P(F1=1|C=1)  = 0/6,P(F1=0|C=1)  = 6/6。

经过加法平滑后,P(F1=1|C=1)  = (0+1)/(6+2)=1/8,P(F1=0|C=1)  = (6+1)/(6+2)=7/8。

注意分母的+2,这种特殊处理使得2个互斥事件的概率和恒为1。

4. 当特征很多的时候,大量小数值的小数乘法会有溢出风险。因此,通常的实现都是将其转换为log

log[P(C)*P(F1|C)*P(F2|C)…P(Fn|C)] = log[P(C)]+log[P(F1|C)] + … +log[P(Fn|C)]

将乘法转换为加法,就彻底避免了乘法溢出风险。

 

二、连续/浮点数(大样本,分区间

  第二个是账号分类的例子

  这个问题是这样的,对于SNS社区来说,不真实账号(使用虚假身份或用户的小号)是一个普遍存在的问题,作为SNS社区的运营商,希望可以检测出这些不真实账号,从而在一些运营分析报告中避免这些账号的干扰,亦可以加强对SNS社区的了解与监管。

      如果通过纯人工检测,需要耗费大量的人力,效率也十分低下,如能引入自动检测机制,必将大大提升工作效率。这个问题说白了,就是要将社区中所有账号在真实账号和不真实账号两个类别上进行分类。

  运营商决定考察账号的三个特征:日志数量/注册天数、好友数量/注册天数、是否使用真实头像。

 

  运维人员曾经人工检测过的1万个账号,得到这三个特征的先验统计概率

 

特征1(F1):日志数量/注册天数 统计表

  [0, 0.05)
[0.05, 0.2)  [0.2, +∞) 合计
真实  0.12  0.30  0.28 0.60
虚假  0.25  0.10  0.05 0.40
合计  0.37  0.40  0.33 1

 

 

   P(F1_2|真实) = 0.30/0.60 = 0.5

 

 

特征2(F2):好友数量/注册天数 统计表

  [0, 0.1 ) [0.1, 0.5) [0.5, +∞) 合计
真实  0.10  0.20 0.30 0.60
虚假  0.15  0.15 0.10 0.40
合计  0.25  0.35 0.40 1

 

 

     P(F2_2|真实) = 0.20/0.60 = 0.33

 

 

特征3(F3):是否使用真实头像(1/0) 统计表

  1 0 合计
真实  0.48 0.12 0.60
虚假  0.01 0.39 0.40
合计 0.49 0.51 1

 

 

    P(F3_2|真实) = 0.12/0.60 = 0.20

 

 

因此,下面这个账号(0.1, 0.2, 0)为真实账号的概率,分析如下:

  日志数量/注册天数:0.1 ~ F1_2

  好友数量/注册天数:0.2 ~ F2_2

  是否使用真实头像:0     ~ F3_2

   P(真实|F1_2 x F2_2 x F3_2)
    = P(F1_2|真实) x P(F1_2|真实)x P(F3_2|真实) x P(真实)
    / P(F1_2) x P(F2_2) x P(F3_2)

           = 0.5 x 0.33 x 0.2 x 0.6 / 0.4 x 0.35 x 0.51
    = 0.28

同理,可以计算

  P(虚假|F1_2 x F2_2 x F3_2) = 0.51

 

三、连续/浮点数(小样本,设正态

这是一个性别分类的例子

 

下面是一组人类身体特征的统计资料。

  性别  身高(英尺) 体重(磅)  脚掌(英寸)

  男    6       180     12
  男    5.92     190     11
  男    5.58     170     12
  男    5.92     165     10
  女    5       100     6
  女    5.5      150     8
  女    5.42     130     7
  女    5.75     150     9

已知某人身高6英尺、体重130磅,脚掌8英寸,请问该人是男是女?

 

根据朴素贝叶斯分类器,计算下面这个式子的值。

P(身高|性别) x P(体重|性别) x P(脚掌|性别) x P(性别)

这里的困难在于,由于身高、体重、脚掌都是连续变量,不能采用离散变量的方法计算概率。而且由于样本太少,所以也无法分成区间计算。怎么办?

 

这时,

首先假设男性和女性的身高、体重、脚掌都是正态分布

然后,通过样本计算出均值和方差;

接着,由正态分布的密度函数,计算出各自条件概率密度。

 

比如,男性的身高是均值5.855、方差0.035的正态分布。

所以,男性的身高为6英尺的条件概率密度为:

朴素贝叶斯分类器_sklearn朴素贝叶斯分类器

 

 

有了这些数据以后,就可以计算(身高,体重,脚掌)=(6、130、8)的性别分类了。

  P(身高=6|男) x P(体重=130|男) x P(脚掌=8|男) x P(男)
    = 6.1984 x e-9

  P(身高=6|女) x P(体重=130|女) x P(脚掌=8|女) x P(女)
    = 5.3778 x e-4

可以看到,女性的概率比男性要高出将近10000倍,所以判断该人为女性。

 

 

 四、python实现的代码

 

import numpy as np


def loadDataSet():
    docs = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
            ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
            ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
            ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
            ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
            ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
    classes = [0,1,0,1,0,1]    # 1为辱骂, 0为否
    return docs, classes

#创建一个带有所有单词的列表
def create_all_words(docs):
    all_words = set([])
    for doc in docs:
        all_words = all_words | set(doc)
    return list(all_words)

# 将句子根据其中的单词转成向量
def create_all_words_counter(all_words, doc):
    all_words_counter = [0] * len(all_words)
    for word in doc:
        if word in all_words:
            all_words_counter[all_words.index(word)] = 1   # 置1,伯努利模型
            #all_words_counter[all_words.index(word)] += 1 # 加1,多项式模型
        else:
            print('word ',word ,'not in dict')
    return all_words_counter


# 计算P(i)和P(w[i]|C[1])和P(w[i]|C[0]),这里有两个技巧
# 一个是开始的分子分母没有全部初始化为0是为了防止其中一个的概率为0导致整体为0,
# 另一个是后面乘用对数防止因为精度问题结果为0
def trainNB0(all_words_counters, classes):
    num_docs = len(all_words_counters)
    num_all_words = len(all_words_counters[0])
    pAbusive = np.sum(classes) / num_docs # 辱骂的先验概率

    pNum = np.ones((2, num_all_words))  # 置1,没有置0,这是一个技巧
    pDenom = np.array([2.0, 2.0])

    for i in range(num_docs):
        pNum[classes[i]] += all_words_counters[i]
        pDenom[classes[i]] += np.sum(all_words_counters[i])

    p0Vec = np.log(pNum[0]) - np.log(pDenom[0])  # 处于精度的考虑,这里使用对数减法!!
    p1Vec = np.log(pNum[1]) - np.log(pDenom[1])
    return p0Vec, p1Vec, pAbusive
   
def classifyNB(all_words_counter, p0Vec, p1Vec, pAbusive):
    p1 = np.sum(all_words_counter * p1Vec) + np.log(pAbusive)    # 乘以辱骂先验概率。与前对应,这里用了对数加!!
    p0 = np.sum(all_words_counter * p0Vec) + np.log(1.0 - pAbusive)
    if p1 > p0:
        return 1 # 分类1:辱骂
    else:
        return 0 # 分类2:否
       

   
if __name__ == '__main__':
    docs, classes = loadDataSet()
    all_words = create_all_words(docs)
    all_words_counters = []
    for doc in docs:
        all_words_counters.append(create_all_words_counter(all_words, doc))
    p0Vec, p1Vec, pAb = trainNB0(np.array(all_words_counters), np.array(classes))
    
    testDoc = ['love', 'my', 'dalmation']
    all_words_counter = np.array(create_all_words_counter(all_words, testDoc))
    print(testDoc, 'classified as: ', classifyNB(all_words_counter, p0Vec, p1Vec, pAb))
    
    testDoc = ['stupid', 'garbage']
    all_words_counter = np.array(create_all_words_counter(all_words, testDoc))
    print(testDoc, 'classified as: ', classifyNB(all_words_counter, p0Vec, p1Vec, pAb))
    
    

 

 

参考:

http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html

http://blog.csdn.net/lsldd/article/details/41542107

http://www.jb51.net/article/57540.htm

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/168147.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 微信不能登录网页版(微信手机网页登录)

     因为出于工作和学习的目的,我的个人电脑操作系统使用的是Ubuntu18.04LTS,就目前而言,许多优秀的软件都有Linux版本,虽然Linux的用户相对群体较小,但是其软件生态也在逐渐成长,而且日常使用浏览器就可以解决许多的应用需求。现在微信和QQ在生活和工作领域均是举足轻重,emm…  BUT!!!腾讯到目前为止并没有推出Linux版的微信和TI…

    2022年4月12日
    58
  • 安装drupal

    安装drupal1.把汉化文件拷贝到profiles/standard/translations/可以中文安装2.改变一个文件夹属性,cp一个文件。3.建立数据库4.开始安装,导入翻译中进度条卡死,硬盘不响了,刷新一下继续。5.设置网站名称信箱,管理员帐号信箱。6.安装开始,完毕,注意参阅install.txt文件。7.安装必须模块:Administrationmenu;a…

    2022年7月20日
    11
  • linux 重命名文件名_centos7重命名文件

    linux 重命名文件名_centos7重命名文件在这个简短的教程中,我们将向您展示如何在Linux中重命名文件。通常,这些命令在云服务器上使用,并且在大多数基于Unix的系统(包括CentOS和Ubuntu)上运行。这是我们一系列简短的Linux教程中的第一篇教程。使用mv命令重命名文件在Linux中重命名命令的最基本(相对最简单)的方法是使用mv命令。语法如下:mv[选项]oldfilenamenewfilename这是一个真实的示例…

    2022年9月11日
    0
  • 大数据教程,大数据学习线路图

    大数据教程,大数据学习线路图前言先引用一下马云大大的话:很多人还没搞清楚什么是PC互联网,移动互联网来了,我们还没搞清楚移动互联的时候,大数据时代又来了。马云深度解析大数据“大数据”是近年来IT行业的热词,并广泛的应用在各行各业。特别是近年来随着社交网络、物联网、云计算以及多种传感器的广泛应用,以数量庞大,种类众多,时效性强为特征的非结构化的数据不断涌现,数据的重要性愈发凸显,传统的数据存储、分析技术难以实时处…

    2022年5月22日
    32
  • linux卸载命令_centos卸载jdk

    linux卸载命令_centos卸载jdk#1.查看目前通过rpm安装的jdk版本rpm-qa|grepjdkrpm-qa|grepgcj#2.得到的结果如下:jdk-1.7.0_80-fcs.x86_64libgcj-4.4.7-3.el6.x86_64#3.执行如下命令卸载jdkrpm-e–nodepslibgcj-4.4.7-3.el6.x86_64或rpm-e–nodepsjdk-1.7.0_80-fcs.x86_64…

    2022年10月1日
    0
  • 异步传输模式atm采用_什么是云主机

    异步传输模式atm采用_什么是云主机异步传输模式(ATM)也称为信元中继(在固定大小的信元中传输数据),它通过光纤或双绞线电缆(高速交换)在OSI模型的数据链路层(第2层)运行一种基于ITU-T宽带综合业务数字网(B-ISDN)标准的网络技术,该标准是由电信业开发的,用于实现下一代网络。ATM专为在WAN(如公用电话系统和公司数据网络)中使用而设计,尽管它也已被用于创建超高速LAN。ATM可以同时传输各种流量:语音,视频和数据,速度高达每秒155兆比特。它将语音,视频数据转换为数据包,并通过相同的介质传递大数据包数据。ATM与TCP/.

    2022年9月21日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号