第4章 朴素贝叶斯

引言

在众多机器学习分类算法中,本篇我们提到的朴素贝叶斯模型,和其他绝大多数分类算法都不同,也是很重要的模型之一。

在众多机器学习的分类算法中,朴素贝叶斯模型以其独特的方法和重要性,与其他算法显著不同。相对于KNN、逻辑回归、决策树等判别方法,这些算法直接学习输入特征X与输出Y之间的直接关系(决策函数 \(Y=f(x)\) 或者条件分布 \(P(Y \mid X)\)​ ),朴素贝叶斯模型则采用了生成方法。它直接找出特征输出Y和特征 X的联合分布 \(P(X, Y)\) ,进而通过 \[ P(Y \mid X)=\frac{P(X, Y)}{P(X)} \]

计算得出结果判定。

朴素贝叶斯算法原理

贝叶斯定理

贝叶斯理论是以18世纪的一位神学家托马斯.贝叶斯(Thomas Bayes)命名。通常,事件A在事件B (发生) 的条件下的概率,与事件B在事件A (发生) 的条件下的概率是不一样的。然而,这两者是有确定的关系的,贝叶斯定理就是这种关系的陈述。 \[ P(A \mid B)=\frac{P(B \mid A) P(A)}{P(B)} \]

  • 条件概率:就是事件 \(A\) 在另外一个事件 \(B\) 已经发生条件下的发生概率。条件概率表示为 \(P(A \mid B)\) ,即在 \(B\) 发生的条件下 \(A\) 发生的概率。
  • 联合概率:表示两个事件共同发生(数学概念上的交集)的概率。 \(A\)\(B\) 的联合概率表示为联合概率。联合概率表示为 \(P(A B)\) \[ P(A B)=P(A \mid B) P(B)=P(B \mid A) P(A) \text {, 若 } A B \text { 相互独立, 则} P(A B)=P(A) P(B) \]
  • 全概率公式: \(\displaystyle P(X)=\sum_k P\left(X \mid Y=Y_k\right) P\left(Y_k\right)\), 其中 \(\displaystyle \sum_k P\left(Y_k\right)=1\)

朴素贝叶斯

朴素贝叶斯方法是基于贝叶斯定理和特征条件独立假设的分类方法

这是一个较强的假设。由于这一假设,模型包含的条件概率的数量大为减少,朴素贝叶斯法的学习与预测大为简化。因而朴素贝叶斯法高效,且易于实现。其缺点是分类的性能不一定很高。

对于给定的训练数据集:

  1. 首先基于特征条件独立假设学习输入 / 输出的联合概率分布
  2. 然后基于此模型,对给定的输入 \(x\) ,利用贝叶斯定理求出后验概率最大的输出 \(y\) :

\[ \begin{aligned} P\left(X=x \mid Y=c_k\right) & =P\left(X^{(1)}=x^{(1)}, \cdots, X^{(n)}=x^{(n)} \mid Y=c_k\right) \\ & =\prod_{j=1}^n P\left(X^{(j)}=x^{(j)} \mid Y=c_k\right) \end{aligned}\tag{1} \]

原理

朴素贝叶斯方法属于生成模型的范畴。在给定输入 \(x\) 的情况下,这种方法通过已学习的模型计算后验概率分布 \(P(Y=c_k \mid X=x)\) 。它选择后验概率最高的类别 $c_k $ 作为输入 $x $ 的预测分类。其中后验概率的计算基于贝叶斯定理进行
\[ \begin{aligned} P\left(Y=c_k \mid X=x\right) &= \frac{P\left(X=x \mid Y=c_k\right) P\left(Y=c_k\right)}{\displaystyle \sum_k P\left(X=x \mid Y=c_k\right) P\left(Y=c_k\right)} \end{aligned}\tag{2} \] 将式\((1)\)代入式\((2)\),有 \[ P\left(Y=c_k \mid X=x\right)=\frac{\displaystyle P\left(Y=c_k\right) \prod_j P\left(X^{(j)}=x^{(j)} \mid Y=c_k\right)}{\displaystyle \sum_{k} P\left(Y=c_k\right) \prod_{j} P\left(X^{(j)}=x^{(j)} \mid Y=c_k\right)},k=1,2, \cdots, K\tag{3} \] 这是朴素贝叶斯法分类的基本公式。于是, 朴素贝叶斯分类器可表示为 \[ y=f(x)=\arg \max _{c_k} \frac{\displaystyle P\left(Y=c_k\right) \prod_j P\left(X^{(j)}=x^{(j)} \mid Y=c_k\right)}{\displaystyle \sum_k P\left(Y=c_k\right) \prod_j P\left(X^{(j)}=x^{(j)} \mid Y=c_k\right)}\tag{4} \] 注意到, 在式 \((4)\) 中分母对所有 \(c_k\) 都是相同的,所以 \[ y=\arg \max _{c_k} P\left(Y=c_k\right) \prod_j P\left(X^{(j)}=x^{(j)} \mid Y=c_k\right)\tag{5} \]

后验概率最大化的含义

朴素贝叶斯法将实例分到后验概率最大的类中, 这等价于期望风险最小化。假设选择 0-1 损失函数: \[ L(Y, f(X))=\left\{\begin{array}{rr} 1, & Y \neq f(X) \\ 0, & Y=f(X) \end{array}\right.\tag{6} \]

式中 \(f(X)\) 是分类决策函数。这时,期望风险函数为 \[ R_{\exp }(f)=E[L(Y, f(X))]\tag{7} \] 期望是对联合分布 \(P(X, Y)\) 取的。由此取条件期望 \[ R_{\exp }(f)=E_X \sum_{k=1}^K\left[L\left(c_k, f(X)\right)\right] P\left(c_k \mid X\right)\tag{8} \]

为了使期望风险最小化, 只需对 \(X=x\) 逐个极小化, 由此得到: \[ \begin{aligned} f(x) & =\arg \min _{y \in \mathcal{Y}} \sum_{k=1}^K L\left(c_k, y\right) P\left(c_k \mid X=x\right) \\ & =\arg \min _{y \in \mathcal{Y}} \sum_{k=1}^K P\left(y \neq c_k \mid X=x\right) \\\\ & =\arg \min _{y \in \mathcal{Y}}\left(1-P\left(y=c_k \mid X=x\right)\right) \\\\ & =\arg \max _{y \in \mathcal{Y}} P\left(y=c_k \mid X=x\right) \end{aligned}\tag{9} \]

这样一来, 根据期望风险最小化准则就得到了后验概率最大化准则: \[ f(x)=\arg \max _{c_k} P\left(c_k \mid X=x\right)\tag{10} \]

即朴素贝叶斯法所采用的原理。

极大似然估计

在朴素贝叶斯法中,学习意味着估计 \(P\left(Y=c_k\right)\)\(P\left(X^{(j)}=x^{(j)} \mid Y=c_k\right)\) 。可以应用极大似然估计法估计相应的概率。先验概率 \(P\left(Y=c_k\right)\) 的极大似然估计是 \[ P\left(Y=c_k\right)=\frac{\displaystyle \sum_{i=1}^N I\left(y_i=c_k\right)}{N}, \quad k=1,2, \cdots, K \tag{11} \]

设第 \(j\) 个特征 \(x^{(j)}\) 可能取值的集合为 \(\left\{a_{j 1}, a_{j 2}, \cdots, a_{j S_j}\right\}\),条件概率 \(P\left(X^{(j)}=a_{j l} \mid Y=c_k\right)\)的极大似然估计是 \[ \begin{aligned} & P\left(X^{(j)}=a_{j l} \mid Y=c_k\right)=\frac{\displaystyle \sum_{i=1}^N I\left(x_i^{(j)}=a_{j l}, y_i=c_k\right)}{\displaystyle \sum_{i=1}^N I\left(y_i=c_k\right)}, \\ & j=1,2, \cdots, n, \quad l=1,2, \cdots, S_j, \quad k=1,2, \cdots, K \end{aligned}\tag{12} \]

式中, \(x_i^{(j)}\) 是第 \(i\) 个样本的第 \(j\) 个特征; \(a_{j l}\) 是第 \(j\) 个特征可能取的第 \(l\) 个值; \(I\) 为指示函数。

创建训练集和测试集

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

from collections import Counter
import math
# data
def create_data():
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df.columns = [
'sepal length', 'sepal width', 'petal length', 'petal width', 'label'
]
data = np.array(df.iloc[:100, :])
# print(data)
return data[:, :-1], data[:, -1]
X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
X_test[0], y_test[0]

Output[ ]

(array([6.6, 2.9, 4.6, 1.3]), 1.0)
  • 高斯模型

    GaussianNB 高斯朴素贝叶斯 特征的可能性被假设为高斯概率密度函数: \[ P\left(x_i \mid y_k\right)=\frac{1}{\sqrt{2 \pi \sigma_{y k}^2}} \exp \left(-\frac{\left(x_i-\mu_{y k}\right)^2}{2 \sigma_{y k}^2}\right)\tag{13} \]

    数学期望: \(\mu\) 方差: \(\sigma^2=\frac{\sum(X-\mu)^2}{N}\)

实现一个朴素贝叶斯分类器

class NaiveBayes:
def __init__(self):
self.model = None

# 数学期望
@staticmethod
def mean(X):
return sum(X) / float(len(X))

# 标准差(方差)
def stdev(self, X):
avg = self.mean(X)
return math.sqrt(sum([pow(x - avg, 2) for x in X]) / float(len(X)))

# 概率密度函数
def gaussian_probability(self, x, mean, stdev):
exponent = math.exp(-(math.pow(x - mean, 2) /
(2 * math.pow(stdev, 2))))
return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent

# 处理X_train
def summarize(self, train_data):
summaries = [(self.mean(i), self.stdev(i)) for i in zip(*train_data)]
return summaries

# 分类别求出数学期望和标准差
def fit(self, X, y):
labels = list(set(y))
data = {label: [] for label in labels}
for f, label in zip(X, y):
data[label].append(f)
self.model = {
label: self.summarize(value)
for label, value in data.items()
}
return 'gaussianNB train done!'

# 计算概率
def calculate_probabilities(self, input_data):
# summaries:{0.0: [(5.0, 0.37),(3.42, 0.40)], 1.0: [(5.8, 0.449),(2.7, 0.27)]}
# input_data:[1.1, 2.2]
probabilities = {}
for label, value in self.model.items():
probabilities[label] = 1
for i in range(len(value)):
mean, stdev = value[i]
probabilities[label] *= self.gaussian_probability(
input_data[i], mean, stdev)
return probabilities

# 类别
def predict(self, X_test):
# {0.0: 2.9680340789325763e-27, 1.0: 3.5749783019849535e-26}
label = sorted(
self.calculate_probabilities(X_test).items(),
key=lambda x: x[-1])[-1][0]
return label

def score(self, X_test, y_test):
right = 0
for X, y in zip(X_test, y_test):
label = self.predict(X)
if label == y:
right += 1

return right / float(len(X_test))
model = NaiveBayes()
model.fit(X_train, y_train)

Output[ ]

'gaussianNB train done!'
print(model.predict([4.4,  3.2,  1.3,  0.2]))

Output[ ]

0.0
model.score(X_test, y_test)

Output[ ]

1.0

scikit-learn实例

from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

Output[ ]

1.0
clf.predict([[4.4,  3.2,  1.3,  0.2]])

Output[ ]

array([0.])

而scikit-learn中的伯努利模型和多项式模型

from sklearn.naive_bayes import BernoulliNB, MultinomialNB # 伯努利模型和多项式模型

第4章朴素贝叶斯法-习题

1.用极大似然估计法推出朴素贝叶斯法中的概率估计公式\((11)\)及公式 \((12)\)

解答:
第1步:证明公式\((11)\)\(\displaystyle P(Y=c_k) = \frac{\displaystyle \sum_{i=1}^N I(y_i=c_k)}{N}\)

由于朴素贝叶斯法假设\(Y\)是定义在输出空间\(\mathcal{Y}\)上的随机变量,因此可以定义\(P(Y=c_k)\)概率为\(p\)

\(\displaystyle m=\sum_{i=1}^NI(y_i=c_k)\),得出似然函数: \[ L(p)=f_D(y_1,y_2,\cdots,y_n|\theta)=\binom{N}{m}p^m(1-p)^{(N-m)} \] 使用微分求极值,两边同时对\(p\)求微分: \[ \begin{aligned} 0 &= \binom{N}{m}\left[mp^{(m-1)}(1-p)^{(N-m)}-(N-m)p^m(1-p)^{(N-m-1)}\right] \\ & = \binom{N}{m}\left[p^{(m-1)}(1-p)^{(N-m-1)}(m-Np)\right] \end{aligned} \] 可求解得到: \[ \displaystyle p=0,p=1,p=\frac{m}{N} \] 显然 \[ \begin{aligned} \displaystyle P(Y=c_k)&=p =\frac{m}{N} =\frac{\displaystyle \sum_{i=1}^N I(y_i=c_k)}{N} \end{aligned} \] 公式\((11)\)得证。


第2步:证明公式\((11)\)\[ \displaystyle P(X^{(j)}=a_{jl}|Y=c_k) = \frac{\displaystyle \sum_{i=1}^N I(x_i^{(j)}=a_{jl},y_i=c_k)}{\displaystyle \sum_{i=1}^N I(y_i=c_k)} \]\[ P(X^{(j)}=a_{jl}|Y=c_k)=p \]

\[ \displaystyle m=\sum_{i=1}^N I(y_i=c_k), q=\sum_{i=1}^N I(x_i^{(j)}=a_{jl},y_i=c_k) \]

得出似然函数: \[ L(p)=\binom{m}{q}p^q(i-p)^{m-q} \] 使用微分求极值,两边同时对\(p\)求微分: \[ \begin{aligned} 0 &= \binom{m}{q}\left[qp^{(q-1)}(1-p)^{(m-q)}-(m-q)p^q(1-p)^{(m-q-1)}\right] \\ & = \binom{m}{q}\left[p^{(q-1)}(1-p)^{(m-q-1)}(q-mp)\right] \end{aligned} \] 可求解得到 \[ \displaystyle p=0,p=1,p=\frac{q}{m} \]

显然 \[ \displaystyle P(X^{(j)}=a_{jl}|Y=c_k)=p=\frac{q}{m}=\frac{\displaystyle \sum_{i=1}^N I(x_i^{(j)}=a_{jl},y_i=c_k)}{\displaystyle \sum_{i=1}^N I(y_i=c_k)} \] 公式\((12)\)得证。