人工智能与机器学习原理精解【17】
文章目录
- 贝叶斯
- 贝叶斯定理的公式推导
- 一、条件概率的定义
- 二、联合概率的分解
- 三、贝叶斯定理的推导
- 四、全概率公式的应用
- 五、总结
- 全概率公式推导
- 一、全概率公式的定义
- 二、全概率公式的推导
- 三、全概率公式的应用
- 贝叶斯定理的原理
- 一、基本原理
- 二、核心概念
- 三、数学表达式
- 四、原理应用
- 五、原理特点
- 朴素贝叶斯定理
- 一、贝叶斯定理基础
- 二、朴素贝叶斯的原理
- 三、朴素贝叶斯的特点
- 朴素贝叶斯公式
- 一、贝叶斯定理
- 二、特征独立性假设
- 三、朴素贝叶斯公式推导
- 四、朴素贝叶斯分类器对数形式
- 五、应用朴素贝叶斯公式
- 六、总结
- 朴素贝叶斯的julia实现
- Symbol
- 拉普拉斯平滑(Laplace Smoothing)
- 实现1
- 依赖库
- 数据准备
- 实现步骤
- 代码实现
- 解释
- 实现2
- 参考文献
贝叶斯
贝叶斯定理的公式推导
一、条件概率的定义
首先,我们回顾条件概率的定义。对于两个事件A和B,条件概率P(A|B)表示在事件B发生的条件下,事件A发生的概率。根据定义,我们有:
P ( A ∣ B ) = P ( A ∩ B ) P ( B ) P(A|B) = \frac{P(A \cap B)}{P(B)} P(A∣B)=P(B)P(A∩B)
其中, P ( A ∩ B ) P(A \cap B) P(A∩B)表示事件A和B同时发生的概率, P ( B ) P(B) P(B)表示事件B发生的概率。
二、联合概率的分解
接下来,我们考虑事件A和B的联合概率 P ( A ∩ B ) P(A \cap B) P(A∩B)。根据概率的乘法法则,我们可以将联合概率分解为:
P ( A ∩ B ) = P ( A ∣ B ) ⋅ P ( B ) P(A \cap B) = P(A|B) \cdot P(B) P(A∩B)=P(A∣B)⋅P(B)
但是,我们也可以从另一个角度分解这个联合概率,即考虑在事件A发生的条件下,事件B发生的概率:
P ( A ∩ B ) = P ( B ∣ A ) ⋅ P ( A ) P(A \cap B) = P(B|A) \cdot P(A) P(A∩B)=P(B∣A)⋅P(A)
三、贝叶斯定理的推导
现在,我们将上面两个等式联立起来:
P ( A ∣ B ) ⋅ P ( B ) = P ( B ∣ A ) ⋅ P ( A ) P(A|B) \cdot P(B) = P(B|A) \cdot P(A) P(A∣B)⋅P(B)=P(B∣A)⋅P(A)
为了得到贝叶斯定理的公式,我们需要解出 P ( A ∣ B ) P(A|B) P(A∣B):
P ( A ∣ B ) = P ( B ∣ A ) ⋅ P ( A ) P ( B ) P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)} P(A∣B)=P(B)P(B∣A)⋅P(A)
这就是贝叶斯定理的公式。它告诉我们,在已知事件B发生的条件下,事件A发生的概率 P ( A ∣ B ) P(A|B) P(A∣B)可以通过事件A发生的先验概率 P ( A ) P(A) P(A)、在事件A发生的条件下事件B发生的概率 P ( B ∣ A ) P(B|A) P(B∣A)以及事件B发生的概率 P ( B ) P(B) P(B)来计算。
四、全概率公式的应用
在某些情况下,我们可能需要计算事件B发生的概率 P ( B ) P(B) P(B),而这个概率可能不是直接给出的。这时,我们可以使用全概率公式来计算 P ( B ) P(B) P(B)。全概率公式是:
P ( B ) = ∑ i P ( B ∣ A i ) ⋅ P ( A i ) P(B) = \sum_{i} P(B|A_i) \cdot P(A_i) P(B)=i∑P(B∣Ai)⋅P(Ai)
其中, { A i } \{A_i\} {Ai}是一个完备事件组,即这些事件两两互斥且并集为全集。将全概率公式代入贝叶斯定理中,我们可以得到更一般的表达式。
五、总结
贝叶斯定理的公式推导是从条件概率的定义出发,通过联合概率的两种分解方式得到的。
全概率公式推导
是概率论中的一个重要公式,它用于计算某个事件发生的总概率,当该事件可以通过多种不同途径(或称为“原因”)发生时。以下是全概率公式的详细推导:
一、全概率公式的定义
设事件 B B B可以由互不相容(即两两之间不能同时发生)的事件 A 1 , A 2 , … , A n A_1, A_2, \ldots, A_n A1,A2,…,An以不同的方式导致,且这些事件构成一个完备事件组(即它们的并集等于全集,或者说,这些事件涵盖了所有可能导致 B B B发生的情况)。那么,事件 B B B发生的总概率 P ( B ) P(B) P(B)可以通过以下公式计算:
P ( B ) = ∑ i = 1 n P ( B ∣ A i ) ⋅ P ( A i ) P(B) = \sum_{i=1}^{n} P(B|A_i) \cdot P(A_i) P(B)=i=1∑nP(B∣Ai)⋅P(Ai)
其中, P ( B ∣ A i ) P(B|A_i) P(B∣Ai)是在事件 A i A_i Ai发生的条件下,事件 B B B发生的概率; P ( A i ) P(A_i) P(Ai)是事件 A i A_i Ai发生的概率。
二、全概率公式的推导
全概率公式的推导基于条件概率和概率的加法法则。
- 条件概率的定义:首先,我们回顾条件概率的定义。对于两个事件 A A A和 B B B,条件概率 P ( B ∣ A ) P(B|A) P(B∣A)表示在事件 A A A发生的条件下,事件 B B B发生的概率。根据定义,我们有:
P ( B ∣ A ) = P ( A ∩ B ) P ( A ) P(B|A) = \frac{P(A \cap B)}{P(A)} P(B∣A)=P(A)P(A∩B)
其中, P ( A ∩ B ) P(A \cap B) P(A∩B)是事件 A A A和 B B B同时发生的概率。
- 概率的加法法则:概率的加法法则告诉我们,如果两个事件是互不相容的(即它们不能同时发生),那么这两个事件之一发生的概率等于它们各自发生的概率之和。对于多个互不相容的事件,这一法则可以推广为:
P ( A 1 ∪ A 2 ∪ … ∪ A n ) = ∑ i = 1 n P ( A i ) P(A_1 \cup A_2 \cup \ldots \cup A_n) = \sum_{i=1}^{n} P(A_i) P(A1∪A2∪…∪An)=i=1∑nP(Ai)
- 结合条件概率和加法法则:现在,我们考虑事件 B B B和由互不相容事件 A 1 , A 2 , … , A n A_1, A_2, \ldots, A_n A1,A2,…,An构成的完备事件组。事件 B B B可以通过这些事件中的任何一个导致,因此我们可以将 B B B表示为这些事件与 B B B的交集的并集:
B = ( A 1 ∩ B ) ∪ ( A 2 ∩ B ) ∪ … ∪ ( A n ∩ B ) B = (A_1 \cap B) \cup (A_2 \cap B) \cup \ldots \cup (A_n \cap B) B=(A1∩B)∪(A2∩B)∪…∪(An∩B)
由于这些交集是互不相容的(因为 A i A_i Ai是互不相容的),我们可以应用概率的加法法则来计算 P ( B ) P(B) P(B):
P ( B ) = ∑ i = 1 n P ( A i ∩ B ) P(B) = \sum_{i=1}^{n} P(A_i \cap B) P(B)=i=1∑nP(Ai∩B)
- 使用条件概率的定义:最后,我们使用条件概率的定义将每个 P ( A i ∩ B ) P(A_i \cap B) P(Ai∩B)替换为 P ( B ∣ A i ) ⋅ P ( A i ) P(B|A_i) \cdot P(A_i) P(B∣Ai)⋅P(Ai):
P ( B ) = ∑ i = 1 n P ( B ∣ A i ) ⋅ P ( A i ) P(B) = \sum_{i=1}^{n} P(B|A_i) \cdot P(A_i) P(B)=i=1∑nP(B∣Ai)⋅P(Ai)
这样,我们就得到了全概率公式。
三、全概率公式的应用
全概率公式在多个领域有广泛应用,特别是在需要考虑多种可能原因或途径导致某个结果发生时。例如,在医学诊断中,医生可能需要考虑多种疾病或病因导致患者出现某种症状的概率;在机器学习中,全概率公式可以用于计算分类问题的总误差率等。
贝叶斯定理的原理
主要涉及概率论中的条件概率和先验概率与后验概率之间的关系。
一、基本原理
- 贝叶斯定理由英国数学家托马斯·贝叶斯(Thomas Bayes)发展而来,它描述了在已知某些条件下,某事件发生的概率如何根据这些条件进行更新。
- 具体来说,贝叶斯定理提供了一种结合先验概率和新的证据(即条件概率)来计算后验概率的方法。
二、核心概念
-
先验概率:在没有任何其他条件或信息的情况下,某个事件发生的概率。这通常基于历史数据、经验或其他信息得出。
-
条件概率:在某个特定条件已经发生的情况下,另一个事件发生的概率。例如,P(A|B)表示在事件B发生的条件下,事件A发生的概率。
-
后验概率:在获得新的证据或信息后,对某个事件发生的概率的更新。后验概率是贝叶斯推断的输出,它反映了在考虑新信息后对某个事件或类别的信念或认知的变化。
三、数学表达式
贝叶斯定理的数学表达式为:
P ( A ∣ B ) = P ( B ∣ A ) ⋅ P ( A ) P ( B ) P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)} P(A∣B)=P(B)P(B∣A)⋅P(A)
其中:
- P ( A ∣ B ) P(A|B) P(A∣B) 表示在事件B发生的条件下,事件A发生的概率(后验概率)。
- P ( B ∣ A ) P(B|A) P(B∣A)表示在事件A发生的条件下,事件B发生的概率(条件概率)。
- P ( A ) P(A) P(A)表示事件A发生的概率(先验概率)。
- P ( B ) P(B) P(B)表示事件B发生的概率,它可以通过全概率公式计算得出,但在某些情况下可以视为已知。
四、原理应用
贝叶斯定理的原理在多个领域有广泛应用,包括但不限于:
-
机器学习:在机器学习中,贝叶斯算法利用先验知识和观察到的数据来更新事件的概率分布,从而做出更加准确的预测和决策。
-
医学诊断:医生可以根据患者的症状、体征和实验室检查结果(新的证据),结合疾病的先验概率,来更新患者患有某种疾病的概率(后验概率)。
-
信息检索:在搜索引擎中,贝叶斯定理可以用来计算查询与文档之间的相关性,从而检索出最相关的信息。
-
信用评分和风险分析:金融机构可以利用贝叶斯定理来评估借款人的信用风险和违约概率,从而做出贷款决策。
五、原理特点
-
动态更新:贝叶斯定理允许我们在获得新信息后动态更新对事件发生的概率的估计,这使得我们的预测和决策更加准确和可靠。
-
结合先验知识:贝叶斯定理充分利用了先验知识(即历史数据或经验),这使得我们在面对新问题时能够更快地找到解决方案。
-
广泛应用:由于贝叶斯定理的灵活性和实用性,它在多个领域都有广泛的应用前景。
朴素贝叶斯定理
是一种基于贝叶斯定理的简单概率分类方法,广泛应用于文本分类、垃圾邮件过滤、医学诊断、情感分析等领域。
一、贝叶斯定理基础
贝叶斯定理是概率论中的一个重要定理,用于计算在已知某些条件下,某个事件发生的概率。其公式为:
P ( A ∣ B ) = P ( B ∣ A ) P ( A ) P ( B ) P(A|B) = \frac{P(B|A)P(A)}{P(B)} P(A∣B)=P(B)P(B∣A)P(A)
- (P(A|B)) 表示在已知事件B发生的情况下,事件A发生的概率,也叫做后验概率。
- (P(B|A)) 表示在已知事件A发生的情况下,事件B发生的概率,也叫做似然概率。
- (P(A)) 表示事件A发生的概率,也叫做先验概率。
- (P(B)) 表示事件B发生的概率,也叫做证据概率。
二、朴素贝叶斯的原理
朴素贝叶斯是一种基于贝叶斯定理的简化模型,其核心假设是特征之间相互独立,即在给定类别的情况下,每个特征对于其他特征没有影响。这样,我们就可以将条件概率分解为单个特征的概率相乘,从而大大简化了计算过程。
朴素贝叶斯的公式为:
P ( C ∣ F 1 , F 2 , . . . , F n ) = P ( C ) P ( F 1 ∣ C ) P ( F 2 ∣ C ) . . . P ( F n ∣ C ) P ( F 1 , F 2 , . . . , F n ) P(C|F_1,F_2,...,F_n) = \frac{P(C)P(F_1|C)P(F_2|C)...P(F_n|C)}{P(F_1,F_2,...,F_n)} P(C∣F1,F2,...,Fn)=P(F1,F2,...,Fn)P(C)P(F1∣C)P(F2∣C)...P(Fn∣C)
由于对于所有的类别C,分母(P(F_1,F_2,…,F_n))都是相同的,因此在比较不同类别的后验概率时,可以忽略分母部分,公式简化为:
P ( C ∣ F 1 , F 2 , . . . , F n ) ∝ P ( C ) P ( F 1 ∣ C ) P ( F 2 ∣ C ) . . . P ( F n ∣ C ) P(C|F_1,F_2,...,F_n) \propto P(C)P(F_1|C)P(F_2|C)...P(F_n|C) P(C∣F1,F2,...,Fn)∝P(C)P(F1∣C)P(F2∣C)...P(Fn∣C)
其中, P ( C ∣ F 1 , F 2 , . . . , F n ) P(C|F_1,F_2,...,F_n) P(C∣F1,F2,...,Fn) 表示在已知所有特征 F 1 , F 2 , . . . , F n F_1,F_2,...,F_n F1,F2,...,Fn的情况下,类别C发生的概率; P ( C ) P(C) P(C)表示类别C发生的先验概率; P ( F i ∣ C ) P(F_i|C) P(Fi∣C)表示在已知类别C的情况下,特征 F i F_i Fi发生的条件概率。
三、朴素贝叶斯的特点
- 朴素贝叶斯模型在实际应用中,首先需要从训练数据集中提取特征和标签,然后计算每个特征的条件概率分布,最后根据贝叶斯定理来预测新样本的类别。
以文本分类为例,我们可以将文本中的单词作为特征,将文本所属的类别作为标签。首先,从训练数据集中统计每个单词在每个类别中出现的频率,进而计算出每个单词在每个类别下的条件概率。然后,对于新的文本样本,统计其中包含的单词,并根据朴素贝叶斯公式计算出该文本属于各个类别的概率,最后选择概率最大的类别作为预测结果。
- 优点:
- 算法简单:朴素贝叶斯模型假设特征之间相互独立,大大简化了计算过程。
- 分类效率高:对于大规模数据集,朴素贝叶斯分类器通常能够快速收敛到较高的分类准确率。
- 对缺失数据不敏感:由于朴素贝叶斯主要依赖于类别的先验概率和特征的条件概率,因此对缺失数据不太敏感。
- 缺点:
- 特征独立性假设:在实际应用中,特征之间往往不是完全独立的,这会影响朴素贝叶斯模型的分类效果。
- 需要大量训练数据:为了准确估计每个特征的条件概率分布,朴素贝叶斯模型需要大量的训练数据。
- 对输入数据敏感:朴素贝叶斯模型对输入数据的表达形式很敏感,不同的特征类型(如离散型、连续型)可能需要不同的处理方法。
朴素贝叶斯公式
是基于贝叶斯定理和特征独立性假设推导出来的。下面,我们将详细推导朴素贝叶斯公式。
一、贝叶斯定理
首先,回顾贝叶斯定理的公式:
P ( C ∣ X ) = P ( X ∣ C ) P ( C ) P ( X ) P(C|X) = \frac{P(X|C)P(C)}{P(X)} P(C∣X)=P(X)P(X∣C)P(C)
其中,
- P ( C ∣ X ) P(C|X) P(C∣X) 是后验概率,表示在观察到特征 (X) 的情况下,类别 (C) 发生的概率。
- P ( X ∣ C ) P(X|C) P(X∣C) 是似然概率,表示在类别 (C) 发生的情况下,观察到特征 (X) 的概率。
- P ( C ) P(C) P(C) 是先验概率,表示类别 © 发生的概率。
- P ( X ) P(X) P(X)是证据概率,表示观察到特征 (X) 的概率。
二、特征独立性假设
朴素贝叶斯假设特征之间相互独立,即给定类别 (C) 的情况下,特征 X 1 , X 2 , … , X n X_1, X_2, \ldots, X_n X1,X2,…,Xn 之间是独立的。因此,似然概率 (P(X|C)) 可以分解为各个特征的条件概率的乘积:
P ( X ∣ C ) = P ( X 1 , X 2 , … , X n ∣ C ) = ∏ i = 1 n P ( X i ∣ C ) P(X|C) = P(X_1, X_2, \ldots, X_n|C) = \prod_{i=1}^{n} P(X_i|C) P(X∣C)=P(X1,X2,…,Xn∣C)=∏i=1nP(Xi∣C)
三、朴素贝叶斯公式推导
- 将特征独立性假设代入贝叶斯定理中,得到朴素贝叶斯公式:
P ( C ∣ X ) = P ( X ∣ C ) P ( C ) P ( X ) = ∏ i = 1 n P ( X i ∣ C ) ⋅ P ( C ) P ( X ) P(C|X) = \frac{P(X|C)P(C)}{P(X)} = \frac{\prod_{i=1}^{n} P(X_i|C) \cdot P(C)}{P(X)} P(C∣X)=P(X)P(X∣C)P(C)=P(X)∏i=1nP(Xi∣C)⋅P(C)
由于对于所有的类别 (C),分母 (P(X)) 都是相同的,因此在比较不同类别的后验概率时,可以忽略分母部分。所以,朴素贝叶斯公式可以简化为:
P
(
C
∣
X
)
∝
∏
i
=
1
n
P
(
X
i
∣
C
)
⋅
P
(
C
)
P(C|X) \propto \prod_{i=1}^{n} P(X_i|C) \cdot P(C)
P(C∣X)∝∏i=1nP(Xi∣C)⋅P(C)
或者,更常见地表示为对数形式(为了避免数值下溢和提高计算稳定性):
log P ( C ∣ X ) ∝ ∑ i = 1 n log P ( X i ∣ C ) + log P ( C ) \log P(C|X) \propto \sum_{i=1}^{n} \log P(X_i|C) + \log P(C) logP(C∣X)∝∑i=1nlogP(Xi∣C)+logP(C)
四、朴素贝叶斯分类器对数形式
这是一种基于贝叶斯定理与特征之间条件独立假设的分类算法。在分类任务中,我们通常需要计算后验概率 P ( C ∣ X ) P(C|X) P(C∣X),即在给定观察到的特征 X X X 的情况下,属于某个类别 C C C 的概率。然而,直接计算这个概率往往是不现实的,因此我们通常使用贝叶斯定理将其转换为更易于计算的形式。
贝叶斯定理可以表示为:
P ( C ∣ X ) = P ( X ∣ C ) ⋅ P ( C ) P ( X ) P(C|X) = \frac{P(X|C) \cdot P(C)}{P(X)} P(C∣X)=P(X)P(X∣C)⋅P(C)
在朴素贝叶斯的上下文中,我们假设特征 X = ( x 1 , x 2 , … , x n ) X = (x_1, x_2, \ldots, x_n) X=(x1,x2,…,xn) 是条件独立的,即每个特征 x i x_i xi 在给定类别 C C C 的情况下是独立的。因此,条件概率 P ( X ∣ C ) P(X|C) P(X∣C) 可以分解为:
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(X∣C)=P(x1∣C)⋅P(x2∣C)⋅…⋅P(xn∣C)
将上述两个公式结合,我们得到朴素贝叶斯分类器的基本公式:
P ( C ∣ X ) = P ( C ) ⋅ P ( x 1 ∣ C ) ⋅ P ( x 2 ∣ C ) ⋅ … ⋅ P ( x n ∣ C ) P ( X ) P(C|X) = \frac{P(C) \cdot P(x_1|C) \cdot P(x_2|C) \cdot \ldots \cdot P(x_n|C)}{P(X)} P(C∣X)=P(X)P(C)⋅P(x1∣C)⋅P(x2∣C)⋅…⋅P(xn∣C)
在实际应用中,我们通常不需要计算 P ( X ) P(X) P(X),因为它对于所有类别都是相同的,因此不会改变不同类别之间的相对概率。所以,我们更关心的是:
P ( C ∣ X ) ∝ P ( C ) ⋅ P ( x 1 ∣ C ) ⋅ P ( x 2 ∣ C ) ⋅ … ⋅ P ( x n ∣ C ) P(C|X) \propto P(C) \cdot P(x_1|C) \cdot P(x_2|C) \cdot \ldots \cdot P(x_n|C) P(C∣X)∝P(C)⋅P(x1∣C)⋅P(x2∣C)⋅…⋅P(xn∣C)
为了避免数值下溢和提高计算稳定性,我们通常将上述公式转换为对数形式:
log P ( C ∣ X ) = log P ( C ) + ∑ i = 1 n log P ( x i ∣ C ) \log P(C|X) = \log P(C) + \sum_{i=1}^{n} \log P(x_i|C) logP(C∣X)=logP(C)+i=1∑nlogP(xi∣C)
这样,我们就可以通过计算每个类别的对数后验概率,并选择具有最高对数概率的类别作为预测结果。
总结来说,朴素贝叶斯分类器的对数形式公式为:
预测类别 = arg max C ( log P ( C ) + ∑ i = 1 n log P ( x i ∣ C ) ) \text{预测类别} = \arg\max_C \left( \log P(C) + \sum_{i=1}^{n} \log P(x_i|C) \right) 预测类别=argCmax(logP(C)+i=1∑nlogP(xi∣C))
其中, arg max C \arg\max_C argmaxC 表示选择使括号内表达式最大的类别 C C C。
五、应用朴素贝叶斯公式
在实际应用中,我们通常使用训练数据集来估计先验概率 P ( C ) P(C) P(C)和条件概率 P ( X i ∣ C ) P(X_i|C) P(Xi∣C)。然后,对于新的样本,我们可以计算其属于每个类别的后验概率(或对数后验概率),并选择概率最大的类别作为预测结果。
六、总结
朴素贝叶斯公式是基于贝叶斯定理和特征独立性假设推导出来的。它通过将似然概率分解为各个特征的条件概率的乘积,大大简化了计算过程。尽管特征独立性假设在实际应用中可能不完全成立,但朴素贝叶斯分类器仍然在许多领域取得了良好的分类效果。
朴素贝叶斯的julia实现
Symbol
在解析的julia代码(AST)中用于表示标识符的对象类型。也经常用作标识实体的名称或标签(例如作为字典关键字)。可以使用:quote运算符输入符号:
通过调用构造函数Symbol(x…),也可以从字符串或其他值构造符号。
符号是不可变的,它们的实现对所有同名符号重复使用相同的对象。
与字符串不同,Symbols是不支持字符迭代的“原子”或“标量”实体。
julia> :name
:name
julia> typeof(:name)
Symbol
julia> x = 42
42
julia> eval(:x)
42
拉普拉斯平滑(Laplace Smoothing)
-
也被称为加一平滑(Add-One Smoothing),是一种在概率估计中常用的技术,特别是当样本数量有限且存在零概率问题时。它通过向每个计数中添加一个小的非零数值(通常是1)来避免零概率的出现,从而确保概率估计的稳健性。
-
在朴素贝叶斯分类器的上下文中,拉普拉斯平滑主要用于处理条件概率的估计。当某个特征值在给定类别的训练样本中没有出现时,如果不进行平滑处理,该特征值对应的条件概率将为0。这可能导致分类器在遇到该特征值时做出错误的分类决策。
-
通过拉普拉斯平滑,我们可以确保即使某个特征值在训练样本中没有出现,它的条件概率也不会为0。具体来说,对于每个类别和每个特征值,我们将其对应的计数加1,然后除以总的计数(加上特征值的可能数量)。
-
以下是拉普拉斯平滑在朴素贝叶斯分类器中的应用示例:
假设我们有一个简单的朴素贝叶斯分类器,它基于两个特征(Feature1
和 Feature2
)来分类数据到两个类别(Class1
和 Class2
)。我们的训练数据如下:
C l a s s 1 : F e a t u r e 1 = A , F e a t u r e 2 = X C l a s s 1 : F e a t u r e 1 = B , F e a t u r e 2 = Y C l a s s 2 : F e a t u r e 1 = A , F e a t u r e 2 = Z Class1: Feature1=A, Feature2=X \\Class1: Feature1=B, Feature2=Y \\Class2: Feature1=A, Feature2=Z Class1:Feature1=A,Feature2=XClass1:Feature1=B,Feature2=YClass2:Feature1=A,Feature2=Z
现在,我们要计算 P(Feature1=B|Class1)
的条件概率。在不做平滑处理的情况下,由于 Feature1=B
只在 Class1
中出现了一次,而 Feature1
在 Class1
中总共有2个不同的值(A和B),所以 P(Feature1=B|Class1) = 1/2
。
但是,如果我们要考虑 Feature1
可能还有其他未出现的值(比如C、D等),并且我们想要对这些未出现的值给出一个非零的概率,我们就可以使用拉普拉斯平滑。假设我们知道 Feature1
总共有3个可能的值(A、B、C),那么平滑后的概率计算如下:
P ( F e a t u r e 1 = B ∣ C l a s s 1 ) = ( 计数 ( F e a t u r e 1 = B , C l a s s 1 ) + 1 ) / ( 计数 ( C l a s s 1 ) + 3 ) = ( 1 + 1 ) / ( 2 + 3 ) = 2 / 5 P(Feature1=B|Class1) \\= (计数(Feature1=B, Class1) + 1) / (计数(Class1) + 3) \\= (1 + 1) / (2 + 3) = 2/5 P(Feature1=B∣Class1)=(计数(Feature1=B,Class1)+1)/(计数(Class1)+3)=(1+1)/(2+3)=2/5
这里,我们向 Feature1=B
在 Class1
中的计数添加了1,同时也向 Class1
中所有可能的 Feature1
值的总数添加了3(因为 Feature1
有3个可能的值)。这样,即使 Feature1=C
在训练数据中从未出现,我们也能给它一个非零的概率。
拉普拉斯平滑是一种简单而有效的技术,它可以帮助朴素贝叶斯分类器更好地处理稀疏数据和未见过的特征值。
下面程序正在调试和修改中
实现1
以一个简单的文本分类问题为例,假设有两种类别:正面评论和负面评论。
依赖库
Julia 有一个强大的生态系统,可以使用多个库来简化实现。这里我们将使用 TextAnalysis.jl
进行一些基本的文本处理(如果没有安装,可以通过 Pkg.add("TextAnalysis")
来安装)。
数据准备
假设我们有以下简单的训练数据和测试数据:
training_data = [
("this is great", "pos"),
("i love it", "pos"),
("hate it", "neg"),
("this is terrible", "neg")
]
test_data = [
"i really like this",
"this is awful"
]
实现步骤
- 数据预处理:将文本数据转换为词频表示。
- 训练模型:计算每个类别的词频和概率。
- 应用模型:对新数据进行分类。
代码实现
using TextAnalysis
# Helper function to count words in a text
function word_counts(text)
counts = Dict{String, Int}()
for (word, freq) in TextAnalysis.word_frequencies(text)
counts[word] = get(counts, word, 0) + freq
end
return counts
end
# Training function
function train_naive_bayes(training_data)
class_counts = Dict{String, Int}()
word_class_counts = Dict{String, Dict{String, Int}}()
for (text, class) in training_data
class_counts[class] = get(class_counts, class, 0) + 1
if !haskey(word_class_counts, class)
word_class_counts[class] = Dict{String, Int}()
end
word_counts_text = word_counts(text)
for (word, count) in word_counts_text
word_class_counts[class][word] = get(word_class_counts[class], word, 0) + count
end
end
# Calculate word probabilities
word_class_probs = Dict{String, Dict{String, Float64}}()
for (class, words) in word_class_counts
total_words = sum(values(words))
word_class_probs[class] = Dict(word => count / total_words for (word, count) in words)
end
class_probs = Dict(class => count / length(training_data) for (class, count) in class_counts)
return class_probs, word_class_probs
end
# Classification function
function classify(text, class_probs, word_class_probs)
scores = Dict{String, Float64}()
word_counts_text = word_counts(text)
for class in keys(class_probs)
score = log(class_probs[class])
for (word, count) in word_counts_text
word_prob = get(word_class_probs[class], word, 1e-6) # Handle unknown words with a small probability
score += count * log(word_prob)
end
scores[class] = score
end
return max(scores, by=value) # Return the class with the highest score
end
# Train model
class_probs, word_class_probs = train_naive_bayes(training_data)
# Test model
for text in test_data
result = classify(text, class_probs, word_class_probs)
println("Text: $text => Class: $(result.first)")
end
解释
- word_counts:计算文本中每个词的出现次数。
- train_naive_bayes:训练朴素贝叶斯模型,计算每个类别的先验概率和条件概率。
- classify:给定一段文本,计算它属于每个类别的得分,并返回得分最高的类别。
实现2
# 导入必要的库
using Statistics
# 朴素贝叶斯分类器结构
struct NaiveBayesClassifier
prior::Dict{Symbol, Float64} # 先验概率 P(C)
cond_prob::Dict{Symbol, Dict{Any, Float64}} # 条件概率 P(X_i|C)
features::Vector{Symbol} # 特征名称
classes::Vector{Symbol} # 类别名称
end
# 计算先验概率
function calculate_prior(data, class_col)
classes = unique(data[:, class_col])
prior = Dict{Symbol, Float64}()
total_count = size(data, 1)
for c in classes
count = sum(data[:, class_col] == c)
prior[c] = count / total_count
end
return prior
end
# 计算条件概率
function calculate_cond_prob(data, class_col, features)
cond_prob = Dict{Symbol, Dict{Any, Float64}}()
classes = unique(data[:, class_col])
for c in classes
cond_prob[c] = Dict{Any, Float64}()
data_c = data[data[:, class_col] == c, :]
for feature in features
feature_values = unique(data[:, feature])
for value in feature_values
count = sum(data_c[:, feature] == value)
# 使用拉普拉斯平滑避免除零错误
cond_prob[c][(feature, value)] = (count + 1) / (size(data_c, 1) + length(feature_values))
end
end
end
return cond_prob
end
# 训练朴素贝叶斯分类器
function train_naive_bayes(data, class_col, features)
prior = calculate_prior(data, class_col)
cond_prob = calculate_cond_prob(data, class_col, features)
return NaiveBayesClassifier(prior, cond_prob, features, collect(keys(prior)))
end
# 分类函数
function classify(nb, sample)
posteriors = Dict{Symbol, Float64}()
for c in nb.classes
log_prob = log(nb.prior[c])
for (feature, value) in sample
if haskey(nb.cond_prob[c], (feature, value))
log_prob += log(nb.cond_prob[c][(feature, value)])
else
# 处理未见过的特征值,可以赋予一个默认的小概率
log_prob += log(1e-10)
end
end
posteriors[c] = log_prob
end
# 返回概率最高的类别
return argmax(posteriors)
end
# 示例数据
data = [
:class1 :feature1 :feature2;
:class1 :value1 :valueA;
:class1 :value1 :valueB;
:class2 :value2 :valueA;
:class2 :value2 :valueC;
# ... 更多数据
]
# 将数据转换为适当的格式(这里假设数据已经是符号类型,否则需要转换)
# 训练分类器
nb_classifier = train_naive_bayes(data, 1, [:feature1, :feature2])
# 分类新样本
sample = [:feature1 => :value1, :feature2 => :valueA]
predicted_class = classify(nb_classifier, sample)
println("Predicted class: $predicted_class")
参考文献
1.文心一言