朴素贝叶斯分类器

Naive Bayes classifier

Posted by 朱晓旭 on March 13, 2020

朴素贝叶斯假设

朴素贝叶斯是最简单的有向概率图模型,它的核心思想是条件独立性假设。
朴素贝叶斯假设:在给定类别的情况下,属性(特征)之间是相互独立的。

$${x_{i}}\bot{x_{j}}| y (x!=j)$$

x是p维特征,y是类别,概率模型如下所示:

$$y\in\{0,1\},x\in{\mathbb{R}}^{p}$$

假设动机

朴素贝叶斯假设的动机是简化$P(x|y)$。
低维下似然可以直接计算,但是随着特征的维度增加,链式法则下似然的计算复杂度高,计算困难。

$$P(x|y)=P(x_{1})\prod_{i = 2}^{p}P({x_{i}}|y,x_{1:i-1}))$$

基于朴素贝叶斯假设:

$$P(X|y)=\prod_{j = 1}^{p}P({x_{j}}|y)$$

从上式可以看出,贝叶斯假设解决了计算时的依赖链过长的问题,简化了特征的联合概率计算的复杂度。 同时我们也能够理解,基于同样目的的马尔可夫假设,比如HMM里的一阶齐次马尔可夫假设:${x_{j}}\bot{x_{i+1}}|x_{i},\forall{j<i}$,在给定当前状态的情况下,将来与过去相互独立,是更为宽松的假设。

朴素贝叶斯分类器

数据是data:

$$\{(x_{i},y_{i})\}_{i=1}^{N}$$
$$y_{i}\in\{0,1\},x_{i}\in{\mathbb{R}}^{p}$$

分类器的预测目标是:给定x情况下,预测y属于哪类。

$$\hat{y} = \mathop{\arg\max}_{y}P(y|x) $$
$$=\mathop{\arg\max}_{y}{\frac{P(x,y)}{P(x)}}$$

由于:

$$P(y|x)={\frac{P(x,y)}{P(x)}}={\frac{P(y)P(x|y)}{P(x)}}\propto{P(y)P(x|y)}$$

因此:

$$\hat{y} = \mathop{\arg\max}_{y}P(y)P(x|y)$$
$$= \mathop{\arg\max}_{y}P(y)\prod_{j = 1}^{p}P({x_{j}}|y)$$

朴素贝叶斯就是计算各类的先验概率,和各个类别下特征取值的条件概率,最后将各个类别下的特征取值条件概率相乘,并乘上该类别的先验概率,取乘积最大的对应的类别作为预测类别。 基于不同特征分布,我们可以采用不同的模型(多项式模型,高斯模型,伯努利模型)。 高斯模型:

$$P(x_{i}|y) = \frac{1}{ \sqrt{2\pi\sigma_{y}^{2}}} exp( -\frac{(x_{i}-\mu_{y})^2}{2{\sigma_{y}}^{2}} )$$

技术处理

  1. 平滑处理 为了防止某个特征的似然为0的情况,会导致联合概率也为0,因此进行平滑处理。
$$P(x_{i}|y)={\frac{P(x_{i}|y)+\alpha}{P(y)+M\alpha}}$$

其中, $\alpha$=1称为Laplace平滑,$\alpha\in{(0,1)}$时为Lidstone平滑,M为所有特征的总数。

  1. 对数运算 面对连乘的计算,引入对数是自然而然的操作。
$$\hat{y} = \mathop{\arg\max}_{y}(log(P(y))+\sum_{j=1}^{p}log(P(x_{i}|y)))$$

例子

使用贝叶斯估计判断是否新型冠状病毒感染者。
数据集中有六人,其中感染者三人,未感染者三人。

序号 发烧 咳嗽 无精神 感染
1
2
3
4
5
6

给定一人:发烧,不咳嗽,有精神,判断是否为新型冠状病毒感染者。
分析:x是三维的特征,分别是{发烧,咳嗽,无精神},y是类别,{感染者,未感染者}。注意观测未感染者时发烧的概率为0。
计算先验:

$$P(感染者)=\frac{3}{6}=\frac{1}{2}$$
$$P(未感染者)=\frac{3}{6}=\frac{1}{2}$$

计算似然:

$$P(发烧|感染者)=\frac{2/3+1}{1/2+2}=\frac{2}{3}$$
$$P(不咳嗽|感染者)=\frac{1/3+1}{1/2+2}=\frac{8}{15}$$
$$P(有精神|感染者)=\frac{2/3+1}{1/2+2}=\frac{1}{3}$$
$$P(发烧|未感染者)=\frac{0+1}{1/2+2}=\frac{2}{5}$$
$$P(不咳嗽|未感染者)=\frac{1/3+1}{1/2+2}=\frac{8}{15}$$
$$P(有精神|未感染者)=\frac{1/3+1}{1/2+2}=\frac{8}{15}$$

推断(例子简单不需要对数运算更清晰):

$$P(感染者|发烧,不咳嗽,有精神)=P(感染者)P(发烧|感染者)P(不咳嗽|感染者)P(有精神|感染者)={\frac{1}{2}}*{\frac{2}{3}}*{\frac{8}{15}}*{\frac{1}{3}}={\frac{8}{135}}$$
$$P(未感染者|发烧,不咳嗽,有精神)=P(未感染者)P(发烧|未感染者)P(不咳嗽|未感染者)P(有精神|未感染者)={\frac{1}{2}}*{\frac{2}{5}}*{\frac{8}{15}}*{\frac{8}{15}}={\frac{64}{1125}}$$

因此推断结果时给定一人:发烧,不咳嗽,有精神,则该人为感染者的几率大。

代码

上述例子给出了特征离散模型,下面给出连续型。连续型特征我们一般采用高斯模型。python代码摘自GitHub

class NaiveBayes():
	def fit(self, X, y):
		self.X = X
		self.y = y
		self.classes = np.unique(y)
		self.parameters = {}
		for i, c in enumerate(self.classes):
			X_Index_c = X[np.where(y == c)]
			X_index_c_mean = np.mean(X_Index_c, axis=0, keepdims=True)
			X_index_c_var = np.var(X_Index_c, axis=0, keepdims=True)
			parameters = {"mean": X_index_c_mean, "var": X_index_c_var, "prior": X_Index_c.shape[0] / X.shape[0]}
			self.parameters["class" + str(c)] = parameters
	
	def _pdf(self, X, classes):
		eps = 1e-4
		mean = self.parameters["class" + str(classes)]["mean"]
		var = self.parameters["class" + str(classes)]["var"]
		numerator = np.exp(-(X - mean) ** 2 / (2 * var + eps))
		denominator = np.sqrt(2 * np.pi * var + eps)
		result = np.sum(np.log(numerator / denominator), axis=1, keepdims=True)
		return result.T
	
	def _predict(self, X):
		output = []
		for y in range(self.classes.shape[0]):
			prior = np.log(self.parameters["class" + str(y)]["prior"])
			posterior = self._pdf(X, y)
			prediction = prior + posterior
			output.append(prediction)
		return output
	
	def predict(self, X):
		output = self._predict(X)
		output = np.reshape(output, (self.classes.shape[0], X.shape[0]))
		prediction = np.argmax(output, axis=0)
		return prediction

总结

  1. 贝叶斯条件独立性假设下,极大的简化了联合概率的计算,提高了效率。
  2. 现实世界中特征间的关系不是独立的,一般情况下很难满足朴素贝叶斯假设,贝叶斯假设太过理想化。

参考