vlambda博客
学习文章列表

机器学习算法(2)--朴素贝叶斯

算法概述

朴素贝叶斯(Naive Bayes)是一个非常简单,但是实用性很强的分类模型。朴素贝叶斯分类器的构造基础是贝叶斯理论。常用于文本的分类,比如垃圾邮件的识别、文章类别的分类等等。


概率基础

概率定义为某件事情发生的可能性,比如说扔出一个硬币,结果头像朝上的概率。我们将事件的概率记作P(X),那么假设这一事件为 X 属于样本空间中的一个类别,那么0 ≤ P(X) ≤1。

联合概率和条件概率

1.联合概率
序号 职业 体型 女神是否喜欢
1 程序员 超重 不喜欢
2 产品 匀称 喜欢
3 程序员 匀称 喜欢
4 程序员 超重 喜欢
5 美工 匀称 不喜欢
6 美工 超重 不喜欢
7 产品 匀称 喜欢


包含多个条件,且多个条件同时成立的概率。如上表中,职业为程序员,并且体型匀称的概率,用P(X,Y)表示,可以看出上述7种情况下只有序号3一种情况满足要求。因此,P(X,Y)=1/7。

2.条件概率

条件概率指的是在事件Y发生的前提下,事件X发生的概率。如上表中,在女神喜欢的前提下,职业是程序员的概率,用P(X|Y)表示。女神喜欢的序号数量为4,从这4个序号中找到职业是程序员的序号数量为2。因此,P(X|Y)=2/4=1/2。同样,用条件概率的公式也可以计算出来:

假设每个事件之间是相互独立的,则有:

如上表中,在女神喜欢的前提下,职业是程序员并且体型匀称的概率,用P(X,Y|Z)表示:

贝叶斯公式

所谓贝叶斯公式即是改变条件概率中的条件和结果,从而计算出某件事情的发生是由某个因素引起的概率,用下列公式来表示:

上式中:

P(A)名为先验概率,指事情还没有发生,要求这件事情发生的可能性的大小,可以根据以往经验和分析得到,它往往作为"由因求果"问题中的"因"。

P(A|B)名为后验概率,指事情已经发生,要求这件事情发生的原因是由某个因素引起的可能性的大小是“执果寻因”问题中的"果"。

P(B|A)名为条件概率,在另外一个事件A已经发生条件下,事件B的发生概率,一般是通过历史数据统计得到的,如前面的一个例子。

朴素贝叶斯分类器

朴素贝叶斯分类器常用于文本的分类,即给定训练文档的词频统计,预测待定文档的类别。对于贝叶斯公式来说,P(A)就指代的是文档的类别;P(B)就指代的是预测文档中的特征值在所有类型文章中出现的频率之和;P(B|A)就指代的是在指定的文档类别中,特征值同时出现的概率;P(A|B)就指的是对于给定的文档特征值,i计算属于某一文档类别的概率。因为上式中分母都是一样的,因此朴素贝叶斯分类器可以简化为仅计算先验概率和后验概率。具体见下面的计算实例。

计算实例

下表统计了在科技和娱乐两种类型的文档中,“商场”、“影院”、“支付宝”和“云计算”这些特征值出现的文档数量。

特征词\类别 科技 娱乐 汇总(求和)
“商场” 9 51 60
“影院” 8 56 64
“支付宝” 20 15 35
“云计算” 63 0 63
汇总(求和) 100 121 221

现有一篇被预测文档,出现了影院、支付宝和云计算这些文档关键词,分别计算属于科技、娱乐的类别概率。根据计算方法的不同可以分为极大似然估计和贝叶斯估计。

极大似然估计

1、先验概率P(A):

2、后验概率P(A|B):

3、计算属于科技和娱乐的概率:

属于科技的概率:

属于娱乐的概率:

可以看出最后的计算结果中属于娱乐的概率为0,原因是出现“云计算”的娱乐类文档的数量为0,会导致后验概率为0,进而导致最后的结果为0。不管是由于统计过程出现了失误还是娱乐类型的文档没有出现过“云计算”,这样由一个特征决定结果而忽略其他特征对结果的影响的方式是不允许出现的,这与K-近邻算法中对特征值进行标准化是一样的道理。比方说好人会做的事情,你有一项没做,我们就把你定义为坏人,这样做合理吗。

贝叶斯估计

用极大似然估计会出现某个类别的概率为0的情况,贝叶斯估计在极大似然估计的基础上添加了平滑系数。具体的方法就是对后验概率的计算方法进行改进:

其中m为训练文档中统计出的特征词的个数,α为平滑系数,通常α=1,称之为拉普拉斯平滑。

朴素贝叶斯算法的优缺点

1、优点

(1)朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。

(2)对缺失数据不太敏感,算法也比较简单,常用于文本分类。

(3)分类准确度高,速度快

2、缺点

(1)假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。

(2)需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。

(3)由于我们是通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率。

(4)对输入数据的表达形式很敏感。

使用sklearn API实现对新闻的类别预测

1、主要API的介绍

1、文本特征提取类
class sklearn.feature_extraction.text.CountVectorizer()
"""
将文本中的词语转换为词频矩阵(只限于英文)
"""
方法
fit_transform(X) # 学习词汇词典X,并返回词汇文档矩阵
2、朴素贝叶斯分类器
class sklearn.naive_bayes.MultinomialNB(alpha)
"""
alphafloat,平滑系数
"""
方法
fit(X, y) # 根据X, y拟合朴素贝叶斯分类器

2、数据集的介绍

该数据集由18846篇新闻组成20个新闻类别,包括两个子集:一个用于训练(train),另一个用于测试(test),测试集和训练集是按照一个特定日期进行划分的。

我们借用sklearn API来进行进一步介绍:

(1)新闻类别

from sklearn.datasets import fetch_20newsgroups # 导入新闻数据集
from pprint import pprint # 美化输出
news = fetch_20newsgroups(subset="all") # 获取所有数据集,包括训练数据集和测试数据集
pprint(news.target_names) # 输出新闻的类别

20个类别如下所示:

['alt.atheism',
'comp.graphics',
'comp.os.ms-windows.misc',
'comp.sys.ibm.pc.hardware',
'comp.sys.mac.hardware',
'comp.windows.x',
'misc.forsale',
'rec.autos',
'rec.motorcycles',
'rec.sport.baseball',
'rec.sport.hockey',
'sci.crypt',
'sci.electronics',
'sci.med',
'sci.space',
'soc.religion.christian',
'talk.politics.guns',
'talk.politics.mideast',
'talk.politics.misc',
'talk.religion.misc']

(2)数据的展现形式

print(news.data)
print(news.target)

数据是直接以新闻的文字内容进行储存,用数字来表示文章的类别

["From: Mamatha Devineni Ratnam <[email protected]>\nSubject: Pens fans reactions\nOrganization: Post Office, Carnegie Mellon, Pittsburgh, PA\nLines: 12\nNNTP-Posting-Host: po4.andrew.cmu.edu\n\n\n\nI am sure some bashers of Pens fans are pretty confused about the lack\nof any kind of posts about the recent Pens massacre of the Devils. Actually,\nI am bit puzzled too and a bit relieved. However, I am going to put an end\nto non-PIttsburghers' relief with a bit of praise for the Pens. Man, they\nare killing those Devils worse than I thought. Jagr just showed you why\nhe is much better than his regular season stats. He is also a lot\nfo fun to watch in the playoffs. Bowman should let JAgr have a lot of\nfun in the next couple of games since the Pens are going to beat the pulp out of Jersey anyway. I was very disappointed not to see the Islanders lose the final\nregular season game. PENS RULE!!!\n\n"]
[10]

3、基于朴素贝叶斯实现对新闻的类别预测

完整代码如下:

from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer # 对文章特征值进行提取并计数
from sklearn.naive_bayes import MultinomialNB # 朴素贝叶斯分类器

news = fetch_20newsgroups(subset="all")

x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25) # 自行将数据分为训练数据集和测试数据集

vec = CountVectorizer() # 实例化特征提取器
x_train = vec.fit_transform(x_train) # 提取训练数据集的特征
x_test = vec.transform(x_test) # 按训练数据集的特征提取方法对测试数据集的特征进行提取

mnb = MultinomialNB(alpha=1.0) # 实例化朴素贝叶斯分类器,平滑系数取1
mnb.fit(x_train, y_train) # 训练
y_predict = mnb.predict(x_test) # 预测

print("预测准确率为:", mnb.score(x_test, y_test)) # 输出预测准确率
预测准确率为:0.8529286926994907

4、说明

代码执行多次,每次的准确率是不一样的,这跟训练数据和测试数据的分割有关。代码其实只是其次,主要是要理解算法的原理,API的使用如果不熟悉的话,可以查看API文档,或者查看源代码来了解使用方法。