第4章 基于概率论的分类方法:朴素贝叶斯
概率论是许多机器学习算法的基础,所以深刻理解这一主题就显得十分重要
4.1 基于贝叶斯决策理论的分类方法
贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。朴素贝叶斯是贝叶斯决策理论的一部分。
贝叶斯决策理论
假设有一个由两类数据组成的数据集。
我们用
p1(x,y)
p
1
(
x
,
y
)
表示数据点
(x,y)
(
x
,
y
)
属于类别1的概率,即图中的红色圆点;用
p2(x,y)
p
2
(
x
,
y
)
表示数据点
(x,y)
(
x
,
y
)
属于类别2的概率,即图中的蓝色三角。对于一个新的数据点
(x,y)
(
x
,
y
)
,可以用下面的规则来判断其类别:
- 若
p1(x,y)>p2(x,y)
p
1
(
x
,
y
)
>
p
2
(
x
,
y
)
,则其类别为1
- 若
p1(x,y)<p2(x,y)
p
1
(
x
,
y
)
<
p
2
(
x
,
y
)
,则其类别为2
即我们选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。(回忆一下,在kNN中,我们也是选择了多数表决的方式来确定输入数据的类别)
4.2 条件概率
由于考研结束才几个月,对条件概率还是有一些认识的。
想要计算取到灰色球的概率,假设选择两个桶相互独立、概率相等且只有这两个选择,完整的计算公式如下:
p(gray)=p(gray⋂Ω)=p(gray⋂(bucketA⋃bucketB))=p(gray,bucketA)+p(gray,bucketB)=p(gray|bucketA)p(bucketA)+p(gray|bucketB)p(bucketB)=24∗12+13∗12=512 p ( g r a y ) = p ( g r a y ⋂ Ω ) = p ( g r a y ⋂ ( b u c k e t A ⋃ b u c k e t B ) ) = p ( g r a y , b u c k e t A ) + p ( g r a y , b u c k e t B ) = p ( g r a y | b u c k e t A ) p ( b u c k e t A ) + p ( g r a y | b u c k e t B ) p ( b u c k e t B ) = 2 4 ∗ 1 2 + 1 3 ∗ 1 2 = 5 12
条件概率的计算公式:
贝叶斯准则:
想要深入研究计算科学就离不开良好的数理基础,还是有必要在补一补一些数学课程的。
4.3 使用条件概率来分类
学习了条件概率和贝叶斯决策理论之后,我们很容易就能发现,真正需要计算和比较的其实是 p(c1|x,y) p ( c 1 | x , y ) 和 p(c2|x,y) p ( c 2 | x , y ) , 即给定数据点 (x,y) ( x , y ) ,该数据点来自类别 c1 c 1 的概率是多少。通过已知的概率 p(x,y|ci) p ( x , y | c i ) 我们应用贝叶斯准则可以得到:
- 若 p(c1|x,y)>p(c2|x,y) p ( c 1 | x , y ) > p ( c 2 | x , y ) ,则属于类别 c1 c 1
- 若 p(c1|x,y)<p(c2|x,y) p ( c 1 | x , y ) < p ( c 2 | x , y ) ,则属于类别 c2 c 2
4.4 使用朴素贝叶斯进行文档分类
朴素贝叶斯是前面介绍的贝叶斯分类器的一个扩展,常用于文档分类。
朴素贝叶斯有两个非常重要的假设,每个特征:
- 独立(统计意义上的独立,这里表现为一个特征出现的概率和其他特征没有关系,这个假设也正是朴素的含义)
- 同等重要
尽管这两个假设可能不符合实际,但是朴素贝叶斯的实际效果却很好
朴素贝叶斯分类器通常有两种实现方式: 一种基于伯努利模型实现,一种基于多项式模型实现。本章采用前一种实现方式。该实现方式中并不考虑词在文档中出现的次数,只考虑出不出现,因此在这个意义上相当于假设词是等权重的。后面会用到多项式模型
4.5 使用Python进行文本分类
思路:将文本看成单词向量,即将句子转换成向量,考虑出现在所有文档中的所有词汇,再决定将哪些词纳入词汇表或者说所要的词汇集合,然后必须要将每一篇文章转换为词汇表上的向量。
4.5.1 准备数据:从文本中构建词向量
首先根据所给的数据集提取出词汇表,再将每篇文档转换成对应词汇表的数值型向量
4.5.2 训练算法:从词向量计算概率
针对这个例子,现在我们来重写贝叶斯准则,给定向量 w w ,本例中就是第一步中转换来的数值型向量。
- p(ci),p(w) p ( c i ) , p ( w ) 的计算显而易见
- 对于 p(w|ci) p ( w | c i ) ,我们将 w w 展开,由于每个特征独立,则
朴素贝叶斯分类器训练函数如下:
def trainNB(trainMatrix, trainCategory):
"""
:param trainMatrix: 文件单词矩阵 [[1,0,1,1,1....],[],[]...]
:param trainCategory: 文件对应的类别[0,1,1,0....],列表长度等于单词矩阵数,其中的1代表对应的文件是侮辱性文件,0代表不是侮辱性矩阵
:return:
"""
# 文件数
numTrainDocs = len(trainMatrix)
# 单词数
numWords = len(trainMatrix[0])
# 侮辱性文件的出现概率,即trainCategory中所有的1的个数,
# 代表的就是多少个侮辱性文件,与文件的总数相除就得到了侮辱性文件的出现概率
pAbusive = sum(trainCategory) / float(numTrainDocs)
# 为解决计算多个乘积,其中一个为0时造成的严重后果,将所有词出现数初始化为1,分母初始化为2
# 构造单词出现次数列表
p0Num = ones(numWords) # [1,1,1,.....]
p1Num = ones(numWords) # [1,1,1,.....]
# 整个数据集单词出现总数
p0Denom = 2.0
p1Denom = 2.0
for i in range(numTrainDocs):
# 是否是侮辱性文件
if trainCategory[i] == 1:
# 如果是侮辱性文件,对侮辱性文件的向量进行加和
p1Num += trainMatrix[i] #[0,1,1,....] + [0,1,1,....]->[0,2,2,...]
# 对向量中的所有元素进行求和,也就是计算所有侮辱性文件中出现的单词总数
p1Denom += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
# 为解决下溢出,对乘积取自然对数
# 类别1,即侮辱性文档的[P(w1|c1),P(w2|c1),P(w3|c1),P(w4|c1),P(w5|c1)....]列表
# 即 在1类别下,每个单词出现的概率
p1Vect = log(p1Num / p1Denom) # [1,2,3,5]/90->[1/90,...]
# 类别0,即正常文档的[P(w1|c0),P(w2|c0),P(w3|c0),P(w4|c0),P(w5|c0)....]列表
# 即 在0类别下,每个单词出现的概率
p0Vect = log(p0Num / p0Denom)
return p0Vect, p1Vect, pAbusive
要注意这里其实没有用到条件概率的公式去计算 p(wi|ci)=p(wi,ci)p(ci) p ( w i | c i ) = p ( w i , c i ) p ( c i ) ,而是用了另外的方法,即总频数/总次数。
4.5.3 测试算法:根据现实情况修改分类器
修改过的代码已经在上面了。
4.5.4 准备数据:文档词袋模型
前面用到的是每个词是否出现作为一个特征,这可以被描述为词集模型,分类器基于伯努利模型;若使用某次出现的次数作为特征,则成为词袋模型,分类器基于多项式模型。