【机器学习】朴素贝叶斯

3. 朴素贝叶斯

素贝叶斯算法(Naive Bayes)是一种基于贝叶斯定理的简单而有效的分类算法。其“朴素”之处在于假设各特征之间相互独立,即在给定类别的条件下,各个特征是独立的。尽管这一假设在实际中不一定成立,合理的平滑技术和数据预处理仍能使其在许多任务中表现良好。

优点

  • 速度快:由于朴素贝叶斯仅需计算简单的概率,训练和预测的速度非常快。
  • 适用于高维数据:即使在特征数量多的情况下,朴素贝叶斯仍然表现良好,且不会陷入维度灾难。
  • 适合多类分类:朴素贝叶斯可以自然地处理多类分类问题。
  • 鲁棒性:对缺失数据和少量噪声不敏感,能在有限的数据集上表现稳定。

缺点

  • 特征独立假设不成立时效果下降:特征之间若存在高度依赖性,朴素贝叶斯的性能可能会大幅降低。
  • 数据稀疏问题:尤其是多项式和伯努利模型,面对稀疏数据时容易出现概率为零的情况,因此需要平滑技术(如拉普拉斯平滑)来缓解这个问题。
3.1 贝叶斯定理

贝叶斯定理是朴素贝叶斯算法的核心公式,它将后验概率表示为先验概率、似然和证据的关系:

P ( C k ∣ X ) = P ( X ∣ C k ) ⋅ P ( C k ) P ( X ) P(C_k|X) = \frac{P(X|C_k) \cdot P(C_k)}{P(X)} P(CkX)=P(X)P(XCk)P(Ck)

其中:

  • P ( C k ∣ X ) P(C_k|X) P(CkX) 是类别 C k C_k Ck 在给定特征 X X X 下的后验概率;
  • P ( X ∣ C k ) P(X|C_k) P(XCk) 是在类别 C k C_k Ck 下特征 X X X 出现的条件概率(即似然);
  • P ( C k ) P(C_k) P(Ck) 是类别 C k C_k Ck 的先验概率;
  • P ( X ) P(X) P(X) 是边缘概率,可以忽略,因为它对于所有类别 C k C_k Ck 相同。
3.2 极大似然估计

朴素贝叶斯的核心假设是条件独立性,即假设在给定类别的条件下,特征之间相互独立。对于特征向量 X = ( x 1 , x 2 , . . . , x n ) X = (x_1, x_2, ..., x_n) X=(x1,x2,...,xn),我们有:

P ( X ∣ C ) = P ( x 1 ∣ C ) ⋅ P ( x 2 ∣ C ) ⋅ … ⋅ P ( x n ∣ C ) P(X|C) = P(x_1|C) \cdot P(x_2|C) \cdot \ldots \cdot P(x_n|C) P(XC)=P(x1C)P(x2C)P(xnC)

这一假设使得模型简化为每个特征独立对分类结果的贡献。朴素贝叶斯模型的分类过程是通过最大化后验概率来进行的:

C ^ = argmax C   P ( C ∣ X ) \hat{C} = \underset{C}{\text{argmax}} \ P(C|X) C^=Cargmax P(CX)

根据贝叶斯定理,可以转换为:

C ^ = argmax C   P ( X ∣ C ) ⋅ P ( C ) \hat{C} = \underset{C}{\text{argmax}} \ P(X|C) \cdot P(C) C^=Cargmax P(XC)P(C)

其中 P ( X ∣ C ) P(X|C) P(XC) 的计算可以通过假设特征独立性简化为各个特征的条件概率的乘积。在不知道 P ( C k ) P(C_k) P(Ck) P ( X ∣ C k ) P(X|C_k) P(XCk) 的情况下,我们可以使用极大似然估计来估计这些概率。

1. 先验概率的极大似然估计

对于类别 C k C_k Ck 的先验概率 P ( C k ) P(C_k) P(Ck),假设类别 C k C_k Ck 在训练集中以独立同分布的方式出现。基于极大似然估计,先验概率可以通过类别 C k C_k Ck 出现的频率来估计。设 n n n 是总样本数, I ( y i = C k ) I(y_i = C_k) I(yi=Ck) 为指示函数,当第 i i i 个样本属于类别 C k C_k Ck 时取 1,否则取 0。则先验概率 P ( C k ) P(C_k) P(Ck) 估计为:

P ( C k ) = ∑ i = 1 n I ( y i = C k ) n P(C_k) = \frac{\sum_{i=1}^n I(y_i = C_k)}{n} P(Ck)=ni=1nI(yi=Ck)

这里, I ( ⋅ ) I(\cdot) I() 是指示函数,即当条件成立时值为 1,否则为 0。

2. 条件概率的极大似然估计

条件概率 P ( X ∣ C k ) P(X|C_k) P(XCk) 表示在类别 C k C_k Ck 给定的条件下,特征向量 X X X 出现的概率。假设特征之间条件独立,特征向量 X = ( x 1 , x 2 , … , x m ) X = (x_1, x_2, \ldots, x_m) X=(x1,x2,,xm),则:

P ( X ∣ C k ) = ∏ j = 1 m P ( x j ∣ C k ) P(X|C_k) = \prod_{j=1}^{m} P(x_j|C_k) P(XCk)=j=1mP(xjCk)

我们使用极大似然估计来估计每个特征 x j x_j xj 在类别 C k C_k Ck 下的条件概率。假设第 j j j 个特征是离散的(如词频或二元特征),则:

P ( x j ∣ C k ) = ∑ i = 1 n I ( x i j = 1  and  y i = C k ) ∑ i = 1 n I ( y i = C k ) P(x_j|C_k) = \frac{\sum_{i=1}^n I(x_{ij} = 1 \ \text{and} \ y_i = C_k)}{\sum_{i=1}^n I(y_i = C_k)} P(xjCk)=i=1nI(yi=Ck)i=1nI(xij=1 and yi=Ck)

其中 x i j x_{ij} xij 表示第 i i i 个样本的第 j j j 个特征的取值。这个估计表示第 j j j 个特征在类别 C k C_k Ck 下出现的频率。

3.3 后验概率最大化

我们的目标是最大化后验概率 P ( C k ∣ X ) P(C_k|X) P(CkX),根据贝叶斯定理,可以写为:

P ( C k ∣ X ) = P ( X ∣ C k ) ⋅ P ( C k ) P ( X ) P(C_k|X) = \frac{P(X|C_k) \cdot P(C_k)}{P(X)} P(CkX)=P(X)P(XCk)P(Ck)

由于边缘概率 P ( X ) P(X) P(X) 对所有类别 C k C_k Ck 都相同,在分类问题中我们可以忽略它。因此,最大化后验概率 P ( C k ∣ X ) P(C_k|X) P(CkX) 等价于最大化 P ( X ∣ C k ) ⋅ P ( C k ) P(X|C_k) \cdot P(C_k) P(XCk)P(Ck)

C ^ = argmax C k   P ( X ∣ C k ) ⋅ P ( C k ) \hat{C} = \underset{C_k}{\text{argmax}} \ P(X|C_k) \cdot P(C_k) C^=Ckargmax P(XCk)P(Ck)

结合极大似然估计的结果,我们有:

C ^ = argmax C k   ( ∏ j = 1 m P ( x j ∣ C k ) ⋅ P ( C k ) ) \hat{C} = \underset{C_k}{\text{argmax}} \ \left( \prod_{j=1}^m P(x_j|C_k) \cdot P(C_k) \right) C^=Ckargmax (j=1mP(xjCk)P(Ck))

由于对数函数是单调递增的,我们可以取对数,将乘法转换为加法,得到更便于计算的公式:

C ^ = argmax C k   ( ∑ j = 1 m log ⁡ P ( x j ∣ C k ) + log ⁡ P ( C k ) ) \hat{C} = \underset{C_k}{\text{argmax}} \ \left( \sum_{j=1}^m \log P(x_j|C_k) + \log P(C_k) \right) C^=Ckargmax (j=1mlogP(xjCk)+logP(Ck))

3.4 拉普拉斯平滑

在实际应用中,如果某个特征在类别 C k C_k Ck 中未出现,即 ∑ I ( x i j = 1  and  y i = C k ) = 0 \sum I(x_{ij} = 1 \ \text{and} \ y_i = C_k) = 0 I(xij=1 and yi=Ck)=0,则 P ( x j ∣ C k ) = 0 P(x_j|C_k) = 0 P(xjCk)=0,这会导致整个后验概率 P ( C k ∣ X ) = 0 P(C_k|X) = 0 P(CkX)=0。为了避免这种情况,我们使用拉普拉斯平滑。

拉普拉斯平滑的基本思想是对每个计数增加一个常数 α > 0 \alpha > 0 α>0,通常取 α = 1 \alpha = 1 α=1。经过平滑处理后,条件概率 P ( x j ∣ C k ) P(x_j|C_k) P(xjCk) 的估计变为:

P ( x j ∣ C k ) = ∑ i = 1 n I ( x i j = 1  and  y i = C k ) + α ∑ i = 1 n I ( y i = C k ) + α ⋅ 2 P(x_j|C_k) = \frac{\sum_{i=1}^n I(x_{ij} = 1 \ \text{and} \ y_i = C_k) + \alpha}{\sum_{i=1}^n I(y_i = C_k) + \alpha \cdot 2} P(xjCk)=i=1nI(yi=Ck)+α2i=1nI(xij=1 and yi=Ck)+α

这里的 2 2 2 是因为 x j x_j xj 是二元特征(取值为 0 或 1),如果特征有更多的取值(如多项分布),则分母的平滑项应该为 α ⋅ 取值数 \alpha \cdot \text{取值数} α取值数

3.5 贝叶斯估计

贝叶斯估计是一种将先验知识与数据相结合的概率估计方法。拉普拉斯平滑可以看作是贝叶斯估计的一种特殊形式。通过贝叶斯估计,我们为 P ( x j ∣ C k ) P(x_j|C_k) P(xjCk) 设定一个先验分布,将其与数据观察结合,得到修正后的估计值:

P ( x j ∣ C k ) = ∑ i = 1 n I ( x i j = 1  and  y i = C k ) + α ∑ i = 1 n I ( y i = C k ) + α ⋅ 特征取值数 P(x_j|C_k) = \frac{\sum_{i=1}^n I(x_{ij} = 1 \ \text{and} \ y_i = C_k) + \alpha}{\sum_{i=1}^n I(y_i = C_k) + \alpha \cdot \text{特征取值数}} P(xjCk)=i=1nI(yi=Ck)+α特征取值数i=1nI(xij=1 and yi=Ck)+α

其中 α \alpha α 是平滑参数,通常设置为 1(即拉普拉斯平滑)。当 α > 1 \alpha > 1 α>1 时,平滑效果更强,适合处理极端数据稀疏的情况。

3.7 代码实现

以下是一个简单的朴素贝叶斯分类器实现(以多项式朴素贝叶斯为例):

import numpy as np

class NaiveBayes:
    def fit(self, X, y):
        n_samples, n_features = X.shape
        self._classes = np.unique(y)
        n_classes = len(self._classes)
        
        # 初始化先验概率和条件概率
        self._priors = np.zeros(n_classes, dtype=np.float64)
        self._likelihoods = np.zeros((n_classes, n_features), dtype=np.float64)
        
        for idx, c in enumerate(self._classes):
            X_c = X[y == c]
            self._priors[idx] = X_c.shape[0] / float(n_samples)
            self._likelihoods[idx, :] = (X_c.sum(axis=0) + 1) / (X_c.shape[0] + n_features)
    
    def predict(self, X):
        return [self._predict(x) for x in X]
    
    def _predict(self, x):
        posteriors = []
        
        for idx, c in enumerate(self._classes):
            prior = np.log(self._priors[idx])
            likelihood = np.sum(np.log(self._likelihoods[idx, :]) * x)
            posteriors.append(prior + likelihood)
        
        return self._classes[np.argmax(posteriors)]

# 使用实例
X_train = np.array([[1, 0, 1], [1, 1, 0], [0, 1, 1], [0, 0, 1]])
y_train = np.array([0, 0, 1, 1])

nb = NaiveBayes()
nb.fit(X_train, y_train)
X_test = np.array([[1, 0, 0], [0, 1, 0]])
predictions = nb.predict(X_test)
print(predictions)

在实际应用中,使用Scikit-learn的GaussianNBMultinomialNBBernoulliNB类可以更高效地实现朴素贝叶斯模型。

你可能感兴趣的:(机器学习,机器学习,概率论)