贝叶斯分类器是基于贝叶斯公式,之前写过一篇关于贝叶斯公式的文章:
之前的几种模型都是判别式模型,而贝叶斯分类器是一种生成式模型,我自己的一个最简单的理解就是用概率的方式去考虑分类问题–万物皆概率。之前也有过一篇文章:
根据上面两个知识点,我们可以知道,贝叶斯分类器就是想用 p ( y ∣ x ) = p ( x , y ) p ( x ) , y ∈ ( c 1 , c 2 . . . c i ) p(y|x) = \frac{p(x, y)}{p(x)}, y \in (c_1, c_2 ... c_i) p(y∣x)=p(x)p(x,y),y∈(c1,c2...ci)。根据之前的模型的概念,这个贝叶斯分类器模型的训练过程就是想让所有样本计算的 p ( y ∣ x ) p(y|x) p(y∣x)与真实的 y y y之间的差异,或者说损失最小。这里就定义了这个损失的概念: R ( c i ∣ x ) = ∑ j = 1 N λ i j P ( c i ∣ x ) R(c_i|x)=\sum_{j=1}^N\lambda_{ij}P(c_i|x) R(ci∣x)=j=1∑NλijP(ci∣x)
这个公式计算的是真实分类为 c j c_j cj类别的样本被分成的 c i c_i ci类别的损失。对 j j j进行就和就是一个误判的样本对应其他各种类别的总体风险。我们的目标就是让这个目标函数降到最小。如果某种判定准则 h h h可以让每个样本上对其他每类都能损失最小化,那么自然就可以在样本集整体上损失最小化。那么我们就是要找到这样一个准则,或者说映射关系,也可以说模型:叫做最优贝叶斯分类器: h ∗ h^* h∗:h ∗ = a r g min y ( R ( c ∣ x ) ) h^*=arg\min_y(R(c|x)) h∗=argymin(R(c∣x))
然后,把 λ \lambda λ定义成:λ i j = { 0 , i f i = j 1 , i f i ≠ j \lambda_{ij}=\begin{cases}0, if i=j \\ 1, if i\neq j\end{cases} λij={0,ifi=j1,ifi=j
那么 R ( c ∣ x ) = 1 − P ( c ∣ x ) R(c|x)=1-P(c|x) R(c∣x)=1−P(c∣x),其实也就是不等于正确那一类的所有类别的概率总和。
那么, h ∗ h^* h∗就可以转换成: h ∗ = a r g max y P ( c ∣ x ) h^*=arg\max_yP(c|x) h∗=argymaxP(c∣x) 从求最小就变成了求最大,这个分类器必须使得后验概率 P ( c ∣ x ) P(c|x) P(c∣x)在每个样本上最大。
根据贝叶斯公式: P ( c ∣ x ) = P ( x , c ) p ( x ) = P ( c ) P ( c ∣ x ) P ( x ) P(c|x)=\frac{P(x,c)}{p(x)}=\frac{P(c)P(c|x)}{P(x)} P(c∣x)=p(x)P(x,c)=P(x)P(c)P(c∣x)。从这个公式中看, P ( c ) P(c) P(c)是每种类别的概率,这个东西的话,也成为先验概率,样本集固定了,这个东西就是可以通过样本集中的类别概率来统计的(大数定律),可以用 c i 类 别 的 样 本 数 / 样 本 集 个 数 c_i类别的样本数/样本集个数 ci类别的样本数/样本集个数。同样, P ( x ) P(x) P(x)就是样本 x x x出现的概率。
那么,分类器在求解 P ( c ∣ x ) P(c|x) P(c∣x)的上最大,可以转变为分类器模型让 P ( x ∣ c ) P(x|c) P(x∣c)上最大。这里做这个转换,我的理解是这样的:对于新的样本,计算就是计算 P ( c ∣ x ) P(c|x) P(c∣x),也就是预测新样本的分类是 c c c的概率。而这个概率可以通过贝叶斯公式来计算,其中最麻烦的就是 P ( x ∣ c ) P(x|c) P(x∣c),而求解这个东西的概率可以再拆分成按照属性来计算: P ( x ∣ c ) = ∏ i = 1 d p ( x i ∣ c ) P(x|c) = \prod_{i=1}^d{p(x_i|c)} P(x∣c)=∏i=1dp(xi∣c),也就是根据每种属性在样本集中的概率来计算。最终把这些概率连乘。而 P ( c ∣ x ) = P ( x , c ) p ( x ) = P ( c ) P ( x ) ∏ i = 1 d p ( x i ∣ c ) P(c|x)=\frac{P(x,c)}{p(x)}=\frac{P(c)}{P(x)}\prod_{i=1}^d{p(x_i|c)} P(c∣x)=p(x)P(x,c)=P(x)P(c)∏i=1dp(xi∣c)。
当然,第四步中的公式是基于每个属性都是独立这一前提才成立的。后面还会提到不成立的情况。
如果是基于所有样本都是独立采样这一前提的话,那么 P ( x ) P(x) P(x)这个对于所有的样本都是相同的,可以忽略,那么第四步中的公式就可以变成: P ( c ) ∏ i = 1 d p ( x i ∣ c ) P(c)\prod_{i=1}^d{p(x_i|c)} P(c)i=1∏dp(xi∣c) 也就是贝叶斯分类器的基本形式。
贝叶斯分类器作为一种生成模型的分类器,是计算每种类别的概率,哪个最大就确定是那种类别。配合第二点和第四点来理解这句话,借用《机器学习》书中的例子:
上面的是训练集,假设来了一个新的样本:
对于这样的一个样本,我们就是要去求解他的 P ( c ∣ x i ) P(c|x_i) P(c∣xi),那么,对于类别 C ∈ ( 好 瓜 , 不 是 好 瓜 ) C \in (好瓜,不是好瓜) C∈(好瓜,不是好瓜)只有两个类别,是一个二分类问题。通过上面提到的模型,实际上是分别求解新样本为好瓜情况下的 p ( c ) p(c) p(c)、 p ( x ) p(x) p(x)、 p ( x ∣ c ) p(x|c) p(x∣c)这三个值,然后得到是好瓜的概率,然后再计算不是好瓜情况下的 p ( c ) p(c) p(c)、 p ( x ) p(x) p(x)、 p ( x ∣ c ) p(x|c) p(x∣c)这三个值,然后得到是不是好瓜的概率。根据上一章节中,我们的规律是要最大化这个概率的,那么我们就是要选概率大的,所以计算出来的类别中,哪个概率大,这个样本的分类就是哪个。
先看下 p ( c ) p(c) p(c),这个数是样本集定了就定了。就是某个类别占样本集中的比例;那么, p ( c 0 ) = 好 瓜 数 总 数 = 8 17 = 0.471 p(c_0) = \frac{好瓜数}{总数}= \frac{8}{17} = 0.471 p(c0)=总数好瓜数=178=0.471; p ( c 1 ) = 不 是 好 瓜 数 总 数 = 9 17 = 0.529 p(c_1) = \frac{不是好瓜数}{总数}= \frac{9}{17} = 0.529 p(c1)=总数不是好瓜数=179=0.529.
然后就是计算每个属性在样本集中概率了,概率比较好算,就是样本中类别为 c i c_i ci的,每种属性的概率(公式1): P ( x i ∣ c ) = ∣ D c , x i ∣ D c P(x_i|c)=\frac{|D_{c,x_i}|}{D_c} P(xi∣c)=Dc∣Dc,xi∣
举个栗子:
这里还有几个连续属性的没有计算,这些连续属性的话,一般假定服从正太分布:
这里还需要先针对样本集计算连续值的均值 μ c , i \mu_{c,i} μc,i和方差 σ c , i \sigma_{c,i} σc,i。然后再代入 x i x_i xi进行计算:
概率出来之后,然后把好瓜的相关概率进行相乘,计算等于0.038。而不是好瓜的概率计算等于 6.8 × 1 0 − 5 6.8 × 10^{-5} 6.8×10−5。所以这个样本的类别会被判定为好瓜,然后这里把新样本纳入到样本集中,进行持续学习。
上面的概率计算有一个问题,可以看到概率的连乘之后是一个很小的数了,如果再多几个属性,可能都会趋向于0,而在计算机中也会导致精度不够,最后都等于0,所以会在之前的连乘前加上 l o g log log运算: l o g ( p ( x ∣ c ) ) = l o g ( ∏ i = 1 d p ( x i ∣ c ) ) = ∑ i = 1 d l o g ( p ( x i ∣ c ) ) log(p(x|c)) = log(\prod_{i=1}^d{p(x_i|c)})=\sum_{i=1}^d{log({p(x_i|c)})} log(p(x∣c))=log(i=1∏dp(xi∣c))=i=1∑dlog(p(xi∣c))
平滑与修正。
这里还存在一个问题,如果使用第三步中的公式中分子为0,也就是说在样本集中如果某个属性不存在。那么不管如何计算都会等于0。所以需要进行一下修改(公式2): P ^ ( x i ∣ c ) = D c , x i + 1 ∣ D c ∣ + N i \hat{P}{(x_i|c)} = \frac{D_{c,x_i}+1}{|D_c|+N_i} P^(xi∣c)=∣Dc∣+NiDc,xi+1 这里面的 N i N_i Ni就是第 i i i个属性可能的取值数目。
训练代码就是根据上面的公式计算各个属性对应的各个类别的概率,形成向量。
def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = sum(trainCategory)/float(numTrainDocs) p0Num = ones(numWords); p1Num = ones(numWords) #change to ones() p0Denom = 2.0; p1Denom = 2.0 #change to 2.0 for i in range(numTrainDocs): if trainCategory[i] == 1: p1Num += trainMatrix[i] p1Denom += sum(trainMatrix[i]) else: p0Num += trainMatrix[i] p0Denom += sum(trainMatrix[i]) p1Vect = log(p1Num/p1Denom) #change to log() p0Vect = log(p0Num/p0Denom) #change to log() return p0Vect,p1Vect,pAbusive 判别的话就是根据这些向量直接进行概率计算。
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): p1 = sum(vec2Classify * p1Vec) + log(pClass1) #element-wise mult p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1) if p1 > p0: return 1 else: return 0 朴素贝叶斯的朴素之处就在于假设所有的属性都是相互独立的,所以公式 P ( x ∣ c ) = ∏ i = 1 d p ( x i ∣ c ) P(x|c) = \prod_{i=1}^d{p(x_i|c)} P(x∣c)=∏i=1dp(xi∣c)才成立。但显然很多情况下,这个假设是不成立的。那么把样本间的属性分量的相互依赖关系引入贝叶斯公式中,就形成了一些其他半朴素贝叶斯模型。
如果属性之间有依赖关系的话,需要将上面的公式做一个改造: P ( c ) ∏ i = 1 d p ( x i ∣ c , p a i ) P(c)\prod_{i=1}^d{p(x_i|c,pa_i)} P(c)i=1∏dp(xi∣c,pai) 其中的 p a i pa_i pai是指属性 x i x_i xi所依赖的属性。然后根据上面的公式2来解释这个公式就是样本集中样本为 c c c,依赖 p a pa pa属性的属性的个数。
而这些相互依赖关系,最简单也是最常用的一种就是“独依赖估计”策略。所谓的“独依赖”就是假设每个属性在类别之外最多仅依赖于一个其他的属性。根据不同的依赖方法,可以形成不同的独依赖模型。
选择一个属性作为其他属性的依赖属性,这里使用交叉验证来挑其中某个属性来作为其他的依赖属性。需要注意一下的是,图中的边的含义按照箭头方向是指属性 x 1 x_1 x1决定 x 2 x_2 x2,或者说 x 2 x_2 x2依赖于 x 1 x_1 x1:
TAN是基于最小生成树算法来生成:
通过某种策略计算属性与属性之间权重函数 I ( x i , x j ∣ y ) I(x_i,x_j|y) I(xi,xj∣y)。
以属性为节点构建完全图,节点与节点之间的权重就是第一步中的权重函数。
应用最小生成树算法(
),在这个完全图上生成一份最小生成树。
加入类别节点 y y y,增加从 y y y到每个属性节点的有向边。