机器学习(三):贝叶斯分类器基本原理及代码实现

贝叶斯分类算法是统计学的一种分类方法,它是一类利用概率统计知识进行分类的算法。该算法的优点在于简单易懂、学习效率高、在某些领域的分类问题中能够与决策树、神经网络相媲美。接下来我们介绍一下这个算法:

一、基础知识

在我们讲贝叶斯分类器之前,我们先补充一下相关的数学知识:

1、条件概率

条件概率是指事件A在另一个事件B已经发生条件下发生的概率。条件概率表示为P(A/B),读作“在B条件下A的概率”。
若只有两个事件A,B,那么:P(AB) = P(A\B)P(B) = P(B\A)P(A)
即:p(A|B)=\frac{P(AB)}{P(B)}

2、全概率公式

表示若事件A1,A2,…,An构成一个完备事件组且都有正概率,则对任意一个事件B都有公式成立:
P(B)=P(AB+\bar{A}B) =P(AB)+P(\bar{A}B)=P(A)P(B|A)+P(\bar{A})P(B|\bar{A})同时P(B)也可以表示为:
P(B)=P(A_{1}B)+P(A_{2}B)+...+P(A_{n}B)
=\sum P(A_{i}B)
=\sum P(B|A_{i})*P(A_{i})

3、贝叶斯公式

由条件概率公式可以得到贝叶斯表达式
p(A|B)=\frac{P(AB)}{P(B)}=\frac{P(B|A)*P(A)}{P(B)}

将全概率公式代入到条件概率公式当中,对于事件A_{k}和事件B有:
P(A_{k}|B)=\frac{P(B|A_{k})*P(A_{k})}{\sum P(B|A_{i})*P(A_{i})}
a、P(A)是 A 的先验概率,之所以称为“先验”是因为它不考虑任何 B 方面的因素。

b、P(A|B)是已知 B 发生后 A 的条件概率,也由于得自 B 的取值而被称作 A 的后验概率。

c、P(B|A)是已知 A 发生后 B 的条件概率,也由于得自 A 的取值而被称作 B 的后验概率。

d、P(B)是 B 的先验概率,也作标淮化常量(normalizing constant)。

二、贝叶斯定理

设X是类标号未知的数据样本。设H为某种假定,如,数据样本X属于某特定的类C。对于分类问题,我们希望确定P(H\X)-给定观测数据样本,假定H成立的概率。P(H\X)是后验概率,或条件X下,H的后验概率。例如,假定数据样本世界是由水果组成,用它们的颜色和形状描述,假定X表示红色和圆的,H表示假定X是苹果,则P(H\X)反映当我们看到X是红色并是圆时,我们对X是苹果的确信程度。P(H)是先验概率,或H的先验概率,对于我们的例子,它是任意给定的数据样本为苹果的概率,而不管数据样本看上去如何。后验概率P(H\X)比先验概率P(H)基于更多的信息(如,背景知识)。P(H)是独立于X的。
类似的,P(X\H)是条件H下,X的后验概率。即,它是已知X是苹果,X是红色并且是圆的的概率。P(X)是X的先验概率。
“如何计算这些概率?”,给定数据集,P(X)、P(H)、P(X|H)我们是可以求出来的,这时候贝叶斯就发挥了作用,它提供了一种由P(X)、P(H)、P(X|H)计算后验概率P(H|X)的方法:
P(H|X)=\frac{P(X|H)(H)}{P(X)}

三、朴素贝叶斯分类器的公式

假设某个体有n项特征(Feature),分别为F1,F2,...,Fn。现在有m个类别(Category),分别为C1,C2,C3,...,Cm。贝叶斯分类器就是计算出概率最大的那个分类,也就是求下面这个算式的最大值:
P(C|F_{1}F_{2}...F_{n}) = \frac{P(F_{1}F_{2}...F_{n}|C)P(C)}{P(F_{1}F_{2}...F_{n})}
由于P(F1F2...Fn)对于所有的分类都是相同的,可以省略,问题就变成了求P(F_{1}F_{2}...F_{n}|C)P(C)
的最大值。
朴素贝叶斯分类器则是更进一步,假设所有特征都彼此独立,因此:
P(F_{1}F_{2}...F_{n}|C)P(C) = P(F_{1}|C)P(F_{2}|C)...P(F_{n}|C)P(C)
上式等号右边的每一项,都可以从统计资料中得到,由此就可以计算出每个类别对应的概率,从而找出最大概率的那个类。虽然"所有特征彼此独立"这个假设,在现实中不太可能成立,但是它可以大大简化计算。

四、拉普拉斯平滑(Laplace smoothing)

也就是参数为1时的贝叶斯估计,当某个分量在总样本某个分类中(观察样本库/训练集)从没出现过,会导致整个实例的计算结果为0。为了解决这个问题,使用拉普拉斯平滑进行处理。它的思想非常简单,就是对先验概率的分子(划分的计数)加1,分母加上类别数;对条件概率分子加1,分母加上对应特征的可能取值数量。这样在解决零概率问题的同时,也保证了概率和依然为1.

这里举个例子,假设在文本分类中,有3个类,C1,C2,C3,在指定的训练样本中,某个词语F1,在各个类中观测计数分别为0,990,10,则概率为P(F1|C1)=0,P(F1|C2)=0.99,P(F1|C3)=0.01,对这三个量使用拉普拉斯平滑的计算方法如下:1/1003=0.001,991/1003=0.988,11/1003=0.011

五、朴素贝叶斯定理的应用

贝叶斯算法在文本领域有重要的应用:
文本挖掘典型场景
1、网页自动分类
2、垃圾邮件判断
3、评论自动分析
4、通过用户访问内容判别用户喜好
这里我们进行两个实例的讲解:

  • 文本分类
    数据集我们使用sklearn自带的新闻数据集20news-bydate_py3.pkz,将它划分训练集与测试集进行预测
#导包
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics.classification import classification_report

1、获取数据集

def naivebayes():
    """
    朴素贝叶斯进行分本分类
    :return:
    """
    #获取数据集
    news = fetch_20newsgroups(subset='all')
    print(news)
if __name__ == "__main__":
    naivebayes()

结果我就不展示了,有兴趣的同学加载一下看看。
2、进行数据集的分割和特征提取

def naivebayes():
    """
    朴素贝叶斯进行分本分类
    :return:
    """
    #获取数据集
    news = fetch_20newsgroups(subset='all')
    print(news)
    #对数据集进行分割
    x_train,x_test,y_train,y_test = train_test_split(news.data,news.target,test_size=0.25)
    #进行特征抽取
    tf = TfidfVectorizer()
    x_train = tf.fit_transform(x_train)
    print(tf.get_feature_names())#输出特征名
    x_test = tf.transform(x_test)
if __name__ == "__main__":
    naivebayes()

3、进行贝叶斯算法预测并输出准确率、精确率和召回率

def naivebayes():
    """
    朴素贝叶斯进行分本分类
    :return:
    """
    #获取数据集
    news = fetch_20newsgroups(subset='all')
    print(news)
    #对数据集进行分割
    x_train,x_test,y_train,y_test = train_test_split(news.data,news.target,test_size=0.25)
    #进行特征抽取
    tf = TfidfVectorizer()
    x_train = tf.fit_transform(x_train)
    print(tf.get_feature_names())#输出特征名
    x_test = tf.transform(x_test)
    #进行贝叶斯算法预测
    mlt = MultinomialNB(alpha=1.0)
    print(x_train.toarray())

    mlt.fit(x_train,y_train)
    y_predict = mlt.predict(x_test)
    print("预测的文章类型为:",y_predict)

    #得出准确率
    print("准确率为:",mlt.score(x_test,y_test))

    #得出精确率召回率
    print("每个类别的精确率和召回率:",classification_report(y_test,y_predict,target_names=news.target_names))#target_names表示每个类别的名称(比如文章分科技、娱乐等)

    return None


if __name__ == "__main__":
    naivebayes()
  • 贝叶斯拼写检查器
#正则匹配、字典
import re,collections
#把语料中的单词全部抽取出来,转成小写,并且去除单词中间的特殊符号
def words(text):#正则匹配
    return re.findall('[a-z]+',text.lower())#大写变小写
#如果遇到一个新词,拼写完全正确,但是语料库中没有包含这个词,那么这个词也永远不会出现在训练集中
#这时我们返回这个词的概率是0,但是这样不符合实际,因为概率为0就代表了这个事件绝对不会发生
#而在我们的概率模型中,我们期望用一个很小的概率来代表这种情况,词频设为1
def train(features):
    model=collections.defaultdict(lambda:1)#返回一个类似字典的对象
    for f in features:
        model[f]+=1#词频+1
    return model
NWORDS=train(words(open('E:\\学习文件\\机器学习\\数据集\\贝叶斯算法\\test.txt').read()))#返回字典类型
alphabet='abcdefghijklmnopqrstuvwxyz'
#编辑距离:两个词之间的编辑距离定义为使用了几次插入(在词中插入一个单字母),删除(删除一个单字母)
#交换(交换相邻两个字母),替换(一个字母换成另一个)的操作从一个词变成另外一个词
#返回所有与单词w编辑距离为1的姐
def edits(word):
    n=len(word)
    return set([word[0:i]+word[i+1:] for i in range(n)]+
              [word[0:i]+word[i+1:]+word[i]+word[i+2:] for i in range(n-1)]+
              [word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet]+
              [word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet])
#编辑距离为2的单词也会存在,但是单词数会非常多这里把编辑距离小于2的词中,只把那些正确的词作为候选词
def edits2(word):
    return set(e2 for e1 in edits(word) for e2 in edits(e1))
#正常来说把一个元音拼成另一个的概率要大于辅音(因为人常常把hello打成hallo这样)把单词的第一个字母拼错的概率会相对小,等等。
#但是为了简单起见,选择了一个简单的方法:编辑距离为1的正确单词比编辑距离为2的优先级高,而编辑距离为0的正确单词优先级比编辑距离为1的高
def known_edits(word):
    return set(e2 for e1 in edits(word) for e2 in edits(e1) if e2 in NWORDS)
def known(words):
    return set(w for w in words if w in NWORDS)
#如果known(set)非空,candidate就会选取这个集合,而不继续计算后面的
def correct(word):
    candidates=known([word]) or known(edits(word)) or known_edits(word) or [word]
    return max(candidates,key=lambda w:NWORDS[w])
correct('tha')
实验结果

代码相对来说比较简单,相关说明都已经在代码中注释了,大家可以看一下~

六、算法总结

1、优点

  • 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率
  • 对缺失数据不太敏感,算法也比较简单,常用于文本分类
  • 分类准确度高,速度快

2、缺点

  • 由于使用了样本属性独立性的假设,所以如果样本属性有关联时,其效果不好
    朴素贝叶斯定理就讲到这里,有兴趣的同学可以将上面的代码执行一下。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容