机器学习实践第四篇——贝叶斯分类器

一.什么是贝叶斯分类器

  1.1贝叶斯定理

  贝叶斯定理是贝叶斯统计学中的核心定理,它描述了在获得新的观察数据后如何更新概率估计。贝叶斯定理的数学表达如下:

  $$P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)}$$

  其中,$P(A|B)$ 表示在给定观察数据 $B$ 的条件下,事件 $A$ 发生的概率。$P(B|A)$ 表示在事件 $A$ 发生的条件下,观察到数据 $B$ 的概率。$P(A)$ 和 $P(B)$ 分别表示事件 $A$ 和事件 $B$ 发生的先验概率。

  贝叶斯定理的解释如下:根据先验概率 $P(A)$,我们对事件 $A$ 发生的概率有一定的信念。当我们获得新的观察数据 $B$ 后,我们可以使用条件概率 $P(B|A)$ 来更新我们对事件 $A$ 发生的信念。通过将先验概率和条件概率相乘,并除以边缘概率 $P(B)$(用于归一化),我们可以得到后验概率 $P(A|B)$,即在观察到数据 $B$ 后事件 $A$ 发生的概率。

  贝叶斯定理在实际应用中非常有用,特别是在需要根据新的证据来更新概率估计的情况下。它被广泛应用于机器学习、数据分析、模式识别、人工智能等领域,例如在垃圾邮件过滤、文本分类、医学诊断等任务中。通过不断更新概率估计,贝叶斯定理可以帮助我们做出更准确的预测和决策。

  1.2贝叶斯分类器

  贝叶斯分类器是一种基于贝叶斯定理的机器学习算法,常用于文本分类、垃圾邮件过滤等任务中。它的基本原理是利用已知的数据和贝叶斯定理来推断新数据的分类。

  具体来说,贝叶斯分类器假设特征之间相互独立,并且每个特征对于给定的类别是等价的。基于这些假设,它可以通过计算后验概率来进行分类,即对于给定的输入数据,计算每个类别的后验概率,然后选择具有最高后验概率的类别作为预测结果。

  贝叶斯分类器有几种不同的实现方式,其中最常见的是朴素贝叶斯分类器(Naive Bayes Classifier)。朴素贝叶斯分类器假设特征之间相互独立,这样可以简化计算,并且在实践中通常表现良好。

  在文本分类任务中,贝叶斯分类器可以用来确定一段文本属于哪个类别,例如判断一封电子邮件是垃圾邮件还是正常邮件。它通过分析文本中的单词或短语出现的频率来进行分类,利用每个类别中单词的频率信息来计算后验概率,从而实现分类。

  总的来说,贝叶斯分类器是一种简单而有效的分类算法,尤其适用于处理高维度的数据和大规模的文本分类任务。

二.几种贝叶斯分类器
  2.1朴素贝叶斯分类器 

  朴素贝叶斯分类器是贝叶斯分类器的一种常见形式,它进一步假设特征之间是条件独立的。这个假设使得朴素贝叶斯分类器更加简单和高效,但也可能在某些情况下引入一定的偏差。

  朴素贝叶斯分类器的基本原理如下:

  假设我们有一个分类任务,输入数据可以表示为特征向量 $X = (x_1, x_2, \ldots, x_n)$,而对应的类别为 $C_k$,其中 $k$ 表示类别的索引。

  朴素贝叶斯分类器假设特征之间是条件独立的,即给定类别 $C_k$ 的条件下,各个特征 $x_i$ 是相互独立的。这个假设使得我们可以将似然概率 $P(X|C_k)$ 分解为各个特征的概率的乘积:

  $$P(X|C_k) = P(x_1|C_k) \cdot P(x_2|C_k) \cdot \ldots \cdot P(x_n|C_k)$$

  根据贝叶斯定理,后验概率 $P(C_k|X)$ 可以计算为:

  $$P(C_k|X) \propto P(C_k) \cdot P(x_1|C_k) \cdot P(x_2|C_k) \cdot \ldots \cdot P(x_n|C_k)$$

  为了进行分类,我们可以计算每个类别的后验概率,并选择具有最高后验概率的类别作为预测结果:

  $$\hat{C} = \arg\max_{C_k} P(C_k) \cdot P(x_1|C_k) \cdot P(x_2|C_k) \cdot \ldots \cdot P(x_n|C_k)$$

  在朴素贝叶斯分类器中,我们需要估计先验概率 $P(C_k)$ 和各个特征的条件概率 $P(x_i|C_k)$。通常,我们使用训练数据集来估计这些概率。对于离散特征,可以通过计算各个特征值在每个类别下的频率来估计概率。对于连续特征,可以假设特征服从某种概率分布(如高斯分布),然后使用训练数据集来估计分布的参数。

  需要注意的是,朴素贝叶斯分类器的条件独立性假设可能在实际问题中不成立。如果特征之间存在较强的相关性,朴素贝叶斯分类器可能会产生较差的分类结果。然而,尽管这个假设的简化性,朴素贝叶斯分类器在许多实际应用中表现良好,并且具有较低的计算复杂度。

  2.2半朴素贝叶斯分类器

  半朴素贝叶斯分类器是对朴素贝叶斯分类器的一种改进,它在一定程度上放宽了朴素贝叶斯分类器中特征之间条件独立的假设。在半朴素贝叶斯分类器中,仍然假设某些特征之间是条件独立的,但同时允许部分特征之间存在相关性。

  具体来说,半朴素贝叶斯分类器通常会通过一些方法来选择一部分特征作为条件独立的特征集,而其他特征则可以在给定类别的条件下相互依赖。这种方法旨在更好地反映特征之间的真实关系,从而提高分类器的性能。

  常见的半朴素贝叶斯分类器包括:

  1. Tree-Augmented Naive Bayes (TAN):TAN 使用了树结构来建模特征之间的依赖关系,其中每个节点表示一个特征,边表示特征之间的依赖关系。TAN 在朴素贝叶斯的基础上引入了一些依赖关系,但仍然保持了一定的简化。

  2. Averaged One-Dependence Estimators (AODE):AODE 通过对所有可能的一阶依赖关系取平均来估计条件概率,从而考虑了部分特征之间的依赖关系。它是对完全贝叶斯网络的一种近似。

  这些方法在一定程度上缓解了朴素贝叶斯分类器中特征独立性假设的限制,因此在某些情况下可以获得比朴素贝叶斯更好的分类性能。然而,与此同时,它们也可能增加了模型的复杂度和计算成本。选择合适的分类器取决于数据的特点以及应用的需求。

三.朴素贝叶斯的实现

  3.1高斯朴素贝叶斯分类器的 Python 实现

点击查看代码

class GaussianNaiveBayes:
    def fit(self, X, y):
        n_samples, n_features = X.shape
        self.classes = np.unique(y)
        n_classes = len(self.classes)
        
        self.mean = np.zeros((n_classes, n_features))
        self.var = np.zeros((n_classes, n_features))
        self.priors = np.zeros(n_classes)
        
        for idx, c in enumerate(self.classes):
            X_c = X[y == c]
            self.mean[idx, :] = X_c.mean(axis=0)
            self.var[idx, :] = X_c.var(axis=0)
            self.priors[idx] = len(X_c) / n_samples
            
    def predict(self, X):
        y_pred = [self._predict(x) for x in X]
        return np.array(y_pred)
    
    def _predict(self, x):
        posteriors = []
        for idx, c in enumerate(self.classes):
            prior = np.log(self.priors[idx])
            class_conditional = np.sum(np.log(self._pdf(idx, x)))
            posterior = prior + class_conditional
            posteriors.append(posterior)
        return self.classes[np.argmax(posteriors)]
    
    def _pdf(self, class_idx, x):
        mean = self.mean[class_idx]
        var = self.var[class_idx]
        numerator = np.exp(-(x - mean) ** 2 / (2 * var))
        denominator = np.sqrt(2 * np.pi * var)
        return numerator / denominator

 

  3.2对鸢尾花数据集进行分类

点击查看代码
import numpy as np
from sklearn import datasets
from sklearn import metrics
from sklearn.model_selection import train_test_split
class GaussianNaiveBayes:
    def fit(self, X, y):
        n_samples, n_features = X.shape
        self.classes = np.unique(y)
        n_classes = len(self.classes)
        
        self.mean = np.zeros((n_classes, n_features))
        self.var = np.zeros((n_classes, n_features))
        self.priors = np.zeros(n_classes)
        
        for idx, c in enumerate(self.classes):
            X_c = X[y == c]
            self.mean[idx, :] = X_c.mean(axis=0)
            self.var[idx, :] = X_c.var(axis=0)
            self.priors[idx] = len(X_c) / n_samples
            
    def predict(self, X):
        y_pred = [self._predict(x) for x in X]
        return np.array(y_pred)
    
    def _predict(self, x):
        posteriors = []
        for idx, c in enumerate(self.classes):
            prior = np.log(self.priors[idx])
            class_conditional = np.sum(np.log(self._pdf(idx, x)))
            posterior = prior + class_conditional
            posteriors.append(posterior)
        return self.classes[np.argmax(posteriors)]
    
    def _pdf(self, class_idx, x):
        mean = self.mean[class_idx]
        var = self.var[class_idx]
        numerator = np.exp(-(x - mean) ** 2 / (2 * var))
        denominator = np.sqrt(2 * np.pi * var)
        return numerator / denominator

# 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 将数据集分成训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 创建一个高斯朴素贝叶斯分类器对象
gnb = GaussianNaiveBayes()

# 在训练数据上拟合模型
gnb.fit(X_train, y_train)

# 在测试数据上进行预测
y_pred = gnb.predict(X_test)

# 打印模型准确率
print("准确率:", metrics.accuracy_score(y_test, y_pred))

 

  3.3运行结果

四.总结

  贝叶斯分类器作为“生成式模型”可处理多分类问题,在数据较少的情况下依然有效,但其有几个特别需要注意的点,后续学习研究可往这方面探索。

posted @ 2024-05-14 13:35  Linglo  阅读(826)  评论(0)    收藏  举报