鋌~(最近压力略大,好久没有更新,xixixi),今天的主题是朴素贝叶斯分类器,NB这个缩写真是绝了,确实值得这个缩写,哈哈哈。今天跟大家聊一聊朴素贝叶斯分类器的基本原理和代码编写。贝叶斯分类器的基本原理是使用贝叶斯公式计算各种概率值,然后根据新样本的属性,计算属于某一类的概率,可能略抽象,等下实例讲解,具体是如何操作的。首先给出一些贝叶斯理论的基本原理介绍。

  • 条件概率

  • 乘法公式

  • 全概率公式

  • 贝叶斯公式

条件概率表示的基本事实是,在给定条件下B下,某件事情A发生的概率。

记作:

如果已知事件B为家中至少有个男孩儿,则再发生A事件的概率则为:

对上面的条件概率分子分母同时除以4, 也就是样本空间的大小,则推导出如下式:

所以可以得到一般性结论,条件概率是两个没有条件的概率商。这里可以通过一张图来理解贝叶斯公式在做什么:

乘法公式简单理解就是将条件概率移项:全概率公式是计算复杂概率的一个很重要的公式,假设B1, B2,B3...Bn是样本空间的一个划分,他们互不相容,且并集为整个的样本空间,则对于任意的一个事件A来说,则有如下公式:这里稍加解释,全概率公式是怎么来的,其实可以通过下式推导出来:

又因为条件B被分割为互补相容的几个部分,所以可以根据:

这里用C和D表示两个新的事件以免混淆, 因为两个事件互不相容,所以同时发生的概率则为0, 又有条件概率公式,则可以得到:

则可以整理该式子变成最简的∑和式。

贝叶斯公式则是在乘法公式和全概率公式上推导出来的著名公式,其实就是对应项的替换而已。假设B1, B1,...Bn是样本空间的一个分割,他们之间互补相容,并集为整个样本空间,则:

因为:

则分别将分子分母替换,就可以得到著名的贝叶斯公式。以垃圾邮件分类为例,有垃圾邮件和正常邮件,我们先根据垃圾邮件出现的数目,计算垃圾邮件出现的概率值,假设垃圾邮件出现为事件B1, 则正常邮件出现的为事件B0,事件A为某篇文章出现的条件,我们可以计算出P(B1), P(B0), P(A|B1), P(A|B0), 也就是垃圾邮件的概率,正常邮件的概率, 在垃圾邮件当中,A邮件出现的概率,在正常邮件当中,A邮件出现的概率,以及P(A),A邮件出现的概率。则当我们获得了一封新的邮件A_new, 则可以计算P(B1|A_new)和P(B0|A_new), 也就是新邮件属于垃圾邮件的概率和属于正常邮件的概率,当属于垃圾邮件的概率大于正常邮件的概率,我们则认为邮件是垃圾邮件,反之为正常邮件。这里要说明的一点是,计算P(A|B1)和P(A|B0)时,我们将考虑每个单词出现的概率,而不是整个邮件文档出现的概率,也就是将一封邮件出现的条件概率表示为:

之所以叫做朴素贝叶斯, 就是因为假设不同单词之间是独立的,相互不影响,因为这样公式比较简单,另外一般也能得到一个好的结果。所有最终用于预测新邮件属于垃圾邮件和正常邮件时,我们只需要计算贝叶斯公式的分子即可,我们只需要比较大小,并不关注具体概率值的大小,这里是数学角度的处理方式,当我们撰写贝叶斯公式的代码时,因为矩阵是稀疏矩阵,某个单词的条件概率很可能为0, 最后计算整个邮件出现的概率时,要使用各个单词的条件概率乘积为0, 这时可以强行将每个单词出现的次数出现为0的,计数为1。另外计算机的储存问题,当数字非常小时,会出现下溢出的问题,感兴趣的读者可以自行查阅这个问题,这里我们的处理方式是将小数取ln值,自然对数为底,或者以其他数字为底都可以。因为ln函数是单调的递增函数,这就是贝叶斯分类器在数学计算上和代码撰写上几个非常有用的技巧。下面介绍一下如何将邮件抽象为稀疏矩阵。

以垃圾邮件分类器为例,构建这个算法的步骤大致如下:

  1. 将每一封邮件,看做一个特征向量,将每一封邮件当中的出现的词提取出来,如果内容是英文的邮件,可以按照空格来分割文本内容,如果是中文的邮件,则相对复杂一些,需要一些分词的文本库,或者使用一些分词软件,因为中文的习惯就是词与词之间并没有类似英文的空格,这就导致中文的处理略微复杂,另外一个就是类似于语气助词等,并不是关键的词,需要将该类词语去除,一般会提高分类器的预测精度。然后将所有邮件当中出现的词去重,取最大的并集,取并集之后的每个单词则做为最终的特征,或者叫做属性。例如有两封邮件的内容分别是:“my dog has flea probelems help please.”;“maybe not take him to dog park stupid”,则提取两封邮件当中出现的所有单词集合为{my dog has flea probelems help please maybe not take him to park stupid},其中dog这个单词都出现在两封邮件当中了,所以将其去重,则两封邮件则可以按照单词是否出现在单词并集列表中(出现为1,未出现为0),转换为特征向量:

    [1,1,1,1,1,1,1,0,0,0,0,0,0,0]

    [0,1,0,0,0,0,1,1,1,1,1,1,1,1]

    所有邮件当中出现的单词总数为14,所以特征向量长度为14。这就是如何将邮件内容抽象成稀疏矩阵的方法。然后根据邮件的是否为垃圾邮件,将特征向量标记,是垃圾邮件标记为1, 不是则标记为0, 这就是训练集的标签。

  2. 根据训练数据和贝叶斯公式,计算条件概率,得到条件概率之后,也就是相当于得到了决策的根据,也可以理解为训练模型。

  3. 根据得到的条件概率,比较大小,如果新邮件属于垃圾邮件的概率大于属于正常邮件的概率,那么我们就认为该邮件属于垃圾邮件,反之为正常邮件。

  4. 使用测试集验证分类器效果。

下面是编写朴素贝叶斯分类器的源代码,首先说明一下数据的形式。数据共50封邮件,来自于机器学习实战当中配套的数据,其中25封为垃圾邮件,标记为spam, 另外25封为正常邮件,标记为ham,  垃圾邮件和正常邮件分别存放在两个不同的文件夹中的不同的文本文件当中。所有这里需要使用一些批量读取文件和正则表达式处理邮件的一些代码技巧。那么我们开始吧!先预览一封垃圾邮件:

######################## autor : liuxuang    ## date : 20200907     ## 微信 : LXYweixinID  ##########################设置垃圾邮件和正常邮件的文件存储路径HamEmail SpamEmail ##定义处理多个文件,并转换为稀疏矩阵的函数MutiDocuments2matrix ##加载数据处理的dplyr包和字符串处理的stringr包##不规则的邮件和常规的数据格式不同,我们使用read_lines函数逐行处理     library(dplyr)    library(stringr)    library(readr)###设置垃圾邮件和正常邮件的文件路径    HamEmail_path     SpamEmail_path     ##取所有文件的单词并集    VocabListSet         if(Email_type == "ham"){            setwd(HamEmail_path)        }else if(Email_type == "spam"){            setwd(SpamEmail_path)        }        VocabList_set         VocabList_List         Res ##list.files()函数是获取文件路径下所有文件名称        for(email in list.files()){            temp_data ##这里的正则表达式是提取所有有英文字母组成的字符串,也就是英文单词            vocabList             vocabList  2]            VocabList_List[[email]]             VocabList_set         }##将单词列表每封邮件分别存储到Res里面的两个部分##R语言不像python可以返回多个对象,必须将其存入到一个对象中##这里使用list结构存储单词列表等内容        Res[["VocabList_set"]]         Res[["VocabList_List"]]         return(Res)    }    ham_Res     spam_Res     VOCBLIST ###VOCBLIST是所有文件中的单词并集##编写将文件处理成向量的函数,其中只计数1次,初始化计数为0,##防止计算概率乘积时概率为0   doc2Vector         VoccabVector         if(doc_type == "ham"){            for(word in ham_Res$VocabList_List[[filename]]){                if(word %in% ham_Res$VocabList_set){                    VoccabVector[which(word == ham_Res$VocabList_set)] = 1                }            }        }else{            for(word in ham_Res$VocabList_List[[filename]]){                if(word %in% spam_Res$VocabList_set){                    VoccabVector[which(word == spam_Res$VocabList_set)] = 1                }            }        }        return(VoccabVector)    }  ###将正常邮件的稀疏矩阵存储到VocMatrix_ham    VocMatrix_ham     for(file in list.files(HamEmail_path)){        VocMatrix_ham     }    VocMatrix_ham   ###将正常邮件的稀疏矩阵存储到VocMatrix_spam    VocMatrix_spam     for(file in list.files(SpamEmail_path)){        VocMatrix_spam     }    VocMatrix_spam ##将垃圾邮件和正常邮件合并,并添加训练的标签,垃圾邮件为1,正常邮件为0    VocMatrix     names(VocMatrix)     VocMatrix % mutate(Labels = c(rep(1, 25), rep(0, 25)))    return(VocMatrix)}##将训练标签labels添加到矩阵当中,返回该稀疏矩阵,用于计算条件概VocMatrix VocMatrix_add1 % select(-Labels) + 1VocMatrix_add1$Labels $Labelsprint(VocMatrix_add1)

可以得到一个50乘671的稀疏矩阵,每一行表示一封邮件,671列表示每个单词和邮件的标签Labels。然后根据该稀疏矩阵计算我们想要的概率,编写预测函数:

##条件概率##fliter函数用以区分垃圾邮件和正常邮件,也就是控制条件,利用sum计数##mean函数是一个编程技巧,如果原向量只有0和1,那么求均值就是1的比率##其中p1和p0表示每个单词在特定条件下的条件概率 ##pSam表示垃圾邮件的概率,分母就不用求了,因为分母相同,比分子大小就可以##这里是将上面的条件概率公式转换成代码语言,需要理解,多看几遍。 p1_sum % filter(Labels == 1))p0_sum % filter(Labels == 0))p1 %                     filter(Labels == 1) %>%                     select(-Labels), 2, sum) / p1_sum)p0 %                     filter(Labels == 0) %>%                     select(-Labels), 2, sum) / p0_sum)pSpam 

这里可以展示一下做过处理之后的垃圾邮件每个单词的条件概率(部分结果):

然后编写新邮件预测的函数:

NB_Predict function(documnes_path, VOCBLIST, p1_mum, p0_mum, pSpam){##读取数据,转换为向量    temp_data     vocabList "[A-Za-z]+", simplify = T)    vocabList  2]##初始化为0,可以作为条件进行选择,当没出现该词后,数值为0,和p1或者p0相乘后##起到筛选的作用    VocabVector     for(word in vocabList){        if(word %in% VOCBLIST){            VocabVector[which(word == VOCBLIST)] = 1        }    }##因为之前的函数已经取了log,所以log(AB) = log(A) + log(B)##输出概率值最大标签就是预测值    p1_predict log(pSpam)    p0_predict log(1 - pSpam)    if(p1_predict > p0_predict){        print("Spam")    }else{        print("ham")    }}test1_file "G:/email/test1.txt"tees2_file "G:/email/test2.txt"NB_Predict(test1_file, VOCBLIST, p1, p0, pSpam)#[1] : "Spam"NB_Predict(test2_file, VOCBLIST, p1, p0, pSpam)#[1] : "ham"

这是两封邮件的具体内容,结果还不错,有兴趣的同学可以自己撰写一下交叉验证的代码。这里就不写了,好困,要睡觉了~

sklearn朴素贝叶斯分类器_手撕朴素贝叶斯分类器源码(Naive Bayesian)相关推荐

  1. 手撕JDBC笔记(含源码),进阶框架必备

    文章目录 一.JDBC概述 二.获取数据库连接 2.1 Driver接口及实现类 2.1.1 Driver接口介绍 2.1.2 加载JDBC驱动(Driver实现类) 2.2 数据库五种连接方式(迭代 ...

  2. 【有点狂的手撕STL】STL源码剖析精读 000

    STL源码剖析精读 前言 通过刷题感受到了C++中STL的妙用,十分的想要提高自己对于STL的理解以及运用能力,因此开设此专栏,并希望能够带领大家一起感受C++中STL的魅力. 一.STL简介 STL ...

  3. vb毕业设计——基于vb+VB.NET的媒体播放器设计与实现(毕业论文+程序源码)——媒体播放器

    基于vb+VB.NET的媒体播放器设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于vb+VB.NET的媒体播放器设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦. 文章目录: 基于 ...

  4. 仿小皮手游网帝国CMS模板源码 大型手游门户网站系统源码+手机版+火车头采集

    csdn下载地址: https://download.csdn.net/download/dujiangdu123/13919533 好久没分享92game的资源了,92game一般都是采用帝国CMS ...

  5. nodejs源码_格物致知记一次nodejs源码分析的经历

    昨天分析http模块相关的代码时,遇到了一个晦涩的逻辑,看了想,想了看还是没看懂.百度.谷歌了很多帖子也没看到合适的答案.突然看到一个题目有点相识的搜索结果,点进去是Stack Overflow上的帖 ...

  6. 天天有毒_鸡汤文案类小程序源码

    简介: 天天有毒_鸡汤文案类小程序源码 网盘下载地址: http://kekewl.net/oi8WRaw46rq0 图片:

  7. 基于Laravel开发的Diy手机壳在线定制系统源码

    本资源可免费获取,请至尾部读阅! Diy手机壳在线定制系统源码,基于Laravel开发.可以在后台编辑手机壳型号以及图片,和自定义图片,前台可以直接选择,超方便的diy手机壳定制软件: 可以二次开发, ...

  8. html圣诞树代码_支持手机选择背景音乐圣诞树源码

    html圣诞树代码_支持手机选择背景音乐圣诞树源码小子在本地测试了下,圣诞树会根据音乐变化起来,挺好看的手机打开显示黑屏的问题,已经修复适配,上传服务器即可,如果加载慢就把远程js和css本地化或者更 ...

  9. 课表网页完整的php代码,练手Lab课程表小程序源码v1.0.0 Thinkphp 前后端分离

    练手Lab课程表小程序源码是一个基于Thinkphp系统进行开发的前后端分离系统. 源码功能介绍 1.情侣功能 2.情侣间留言 3.情侣间互相设置课程表背景 4.自己日.周课程表背景设置 5.教务系统 ...

最新文章

  1. 工业大数据系统与应用北京市重点实验室给大家拜年啦!
  2. python项目归纳总结-python总结七
  3. Anaconda简介及其下载 安装 配置 使用 卸载
  4. 启明云端分享|SSD201_自动升级固件与烧录MAC地址
  5. CSS3中的2D和3D转换知识介绍
  6. 钉钉扫码登录第三方_e签宝联合钉钉升级产品功能,共建企业服务生态闭环
  7. Python selenium 滚动页面以及滚动至元素可见(转载)
  8. 别再白瞎去花钱购买高精度卫星地图,一文教你解决精度与下载问题
  9. docker---dockerfile 编写优化
  10. 深圳计师需要全国计算机证吗,深圳入户需要什么技师证
  11. 高线测径仪精密测量已实现全面的检测
  12. java中isolate时间_Flutter 92: 图解 Dart 单线程实现异步处理之 Isolate (一)
  13. 令牌桶算法的python实现,人人都可以玩算法
  14. 虾皮面试真题:虾皮后端15连问!
  15. etcher刻录以后U盘容量只有12M,如何恢复容量?
  16. Eclipse+tomcat开发j2ee经典入门例子
  17. 如何将英文的PDF文档翻译成中文简体?
  18. Spring Boot 升级所遇到的坑们s 1.5.x升级到2.1.x
  19. Linux 笔试面试常见题目(整理)
  20. 520浪漫代码流星雨

热门文章

  1. 计算机专业综合改革举措,计算机专业教学改革
  2. PHP小程序码扫码登录网站,WeAuth微信小程序实现PC网站扫码授权登录
  3. python爬虫过程中遇到的问题_python爬虫过程中出现的问题汇总-Go语言中文社区
  4. centos7源码安装ntp_如何安装和配置 Chrony 作为 NTP 客户端?
  5. 向服务器上传文件的命令,上传文件到远程服务器的命令
  6. php undefined empty,怎样处理php undefined index毛病问题_后端开发
  7. python基于dict、defaultdict、Counter的累加器
  8. 解决Hbase报错java.lang.IllegalStateException: The procedure WAL relies on the ability to hsync for....
  9. Mac 配置jupyter notebook 扩展 Nbextensions
  10. 唐山师范学院计算机宿舍,唐山师范学院宿舍条件怎么样宿舍图片内景