机器学习算法原理实现——朴素贝叶斯

【先说条件概率】

条件概率是指在某个事件发生的条件下,另一个事件发生的概率。以下是一个实际的例子:

假设你有一副扑克牌(不包括大小王,共52张牌),你随机抽一张牌。我们设事件A为"抽到的牌是红色的"(红心和方块为红色,共26张),事件B为"抽到的牌是心"(红心共13张)。

1. 首先,我们可以计算事件A和事件B的概率:

P(A) = 26/52 = 1/2,因为一半的牌是红色的。

P(B) = 13/52 = 1/4,因为四分之一的牌是心。

2. 然后,我们可以计算在事件A发生的条件下,事件B发生的概率,即在抽到的牌是红色的条件下,这张牌是心的概率:

P(B|A) = P(A∩B) / P(A) = P(B) / P(A) = (1/4) / (1/2) = 1/2

这个结果告诉我们,如果你已经知道抽到的牌是红色的,那么这张牌是心的概率就是1/2。

 

【贝叶斯定理公式推导】

贝叶斯定理是基于条件概率的定义推导出来的。条件概率是指在事件B发生的条件下,事件A发生的概率,记作P(A|B),定义为:

P(A|B) = P(A∩B) / P(B) ,其中P(B) ≠ 0

这个公式表示的是在事件B发生的情况下,事件A和事件B同时发生的概率与事件B发生的概率的比值。

P(A|B) = P(A∩B) / P(B) 这个公式的直观理解是:在所有事件B发生的情况中,事件A也发生的比例是多少。这就是为什么条件概率公式表示的是在事件B发生的情况下,事件A和事件B同时发生的概率与事件B发生的概率的比值。


我们可以将P(A∩B)看作是事件A和事件B同时发生的概率,根据条件概率的定义,它等于事件B发生的概率乘以在事件B发生的条件下事件A发生的概率,即:

P(A∩B) = P(B)P(A|B)

同样,我们也可以将P(A∩B)看作是事件B和事件A同时发生的概率,它等于事件A发生的概率乘以在事件A发生的条件下事件B发生的概率,即:

P(A∩B) = P(A)P(B|A)

因为P(A∩B) = P(B∩A),所以我们有:

P(B)P(A|B) = P(A)P(B|A)

然后我们将P(A|B)表示为:

P(A|B) = P(A)P(B|A) / P(B)

这就是贝叶斯定理的公式。

 

【先说贝叶斯概率】

贝叶斯概率是一种解释统计概率的方式,它是以英国数学家托马斯·贝叶斯的名字命名的。在贝叶斯概率理论中,概率被解释为"信度"或"信念"的度量,即对某一命题为真的信念程度。这种信念可能会随着我们获取更多的信息而改变。

贝叶斯概率的核心是贝叶斯定理,它提供了一种在给定新的证据时更新概率的方法。贝叶斯定理的公式如下:

P(A|B) = P(B|A) P(A) / P(B)

其中,P(A|B)是在给定B发生的情况下A发生的概率,也被称为后验概率;P(B|A)是在给定A发生的情况下B发生的概率;P(A)和P(B)是A和B发生的先验概率。

例子:

假设你有两个碗,碗1有30个苹果和10个橙子,碗2有20个苹果和20个橙子。现在你随机从一个碗中抽出一个水果,发现是一个苹果。那么,这个苹果来自碗1的概率是多少呢?

我们可以用贝叶斯定理来解答这个问题。首先,我们设A为"苹果来自碗1",B为"抽出一个苹果"。我们想要求的是P(A|B),即在抽出一个苹果的情况下,这个苹果来自碗1的概率。

我们知道,P(A) = 1/2(因为我们随机选择一个碗),P(B|A) = 30/40(因为碗1有30个苹果和10个橙子),P(B) = (30+20) / (40+40) = 5/8(因为两个碗中总共有50个苹果和30个橙子)。

根据贝叶斯定理,我们有:

P(A|B) = P(B|A) P(A) / P(B) = (30/40) (1/2) / (5/8) = 3/5

所以,如果你抽出一个苹果,那么这个苹果有60%的概率来自碗1。

 

【朴素贝叶斯算法原理和示例】

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

原理:

朴素贝叶斯算法基于贝叶斯定理,贝叶斯定理描述了两个条件概率之间的关系,即:


P(A|B) = P(B|A) P(A) / P(B)

在分类问题中,我们通常把A看作类别,B看作特征。因此,贝叶斯定理可以写成:

P(Y|X) = P(X|Y) P(Y) / P(X)

其中,Y是类别,X是特征。

朴素贝叶斯算法还假设所有特征都是条件独立的,即给定类别Y的条件下,特征X1, X2, ..., Xn是独立的。因此,条件概率P(X|Y)可以写成:

P(X|Y) = P(X1|Y) P(X2|Y) ... P(Xn|Y)

公式推导:

将条件独立假设代入贝叶斯定理,我们得到:

P(Y|X) = P(Y) P(X1|Y) P(X2|Y) ... P(Xn|Y) / P(X)

在分类问题中,由于P(X)对于所有类别都是相同的,因此我们通常忽略P(X),并选择使P(Y) P(X1|Y) P(X2|Y) ... P(Xn|Y)最大的类别作为预测结果。

 

简单案例:

假设我们有以下数据,描述了天气情况和是否打篮球的关系:

| 天气 | 打篮球 |
| ---- | ------ |
| 晴天 | 是 |
| 阴天 | 是 |
| 雨天 | 否 |
| 晴天 | 是 |
| 晴天 | 否 |

我们想要预测在晴天的情况下,是否会打篮球。

 



首先,我们计算先验概率P(是)和P(否),即打篮球(是)和不打篮球(否)的概率:

P(是) = 3/5
P(否) = 2/5

然后,我们计算条件概率P(晴天|是)和P(晴天|否),即在打篮球和不打篮球的情况下,天气是晴天的概率:

P(晴天|是) = 2/3
P(晴天|否) = 1/2

最后,我们计算P(是|晴天)和P(否|晴天),并选择概率较大的一方作为预测结果:

P(是|晴天) = P(晴天|是) P(是) = 2/3 3/5 = 2/5
P(否|晴天) = P(晴天|否) P(否) = 1/2 2/5 = 1/5

因此,我们预测在晴天的情况下,会打篮球。

 

【python实现朴素贝叶斯算法示例】

# 构造数据集
x1 = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]
x2 = ['S','M','M','S','S','S','M','M','L','L','L','M','M','L','L']
y = [-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1]

# 将数据集组合
data = list(zip(x1, x2, y))

def nb_fit(data):
    classes = list(set([d[-1] for d in data]))
    class_prior = {c: 0 for c in classes}
    prior = {}
    for d in data:
        class_prior[d[-1]] += 1
        for i, value in enumerate(d[:-1]):
            prior[(i, value, d[-1])] = prior.get((i, value, d[-1]), 0) + 1
    for key, value in prior.items():
        prior[key] = value / class_prior[key[2]]
    for key, value in class_prior.items():
        class_prior[key] = value / len(data)
    return classes, class_prior, prior

classes, class_prior, prior = nb_fit(data)

def predict(X_test):
    res = []
    for c in classes:
        p_y = class_prior[c]
        p_x_y = 1
        for i, x in enumerate(X_test):
            p_x_y *= prior.get((i, x, c), 1e-6)
        res.append(p_y * p_x_y)
    return classes[res.index(max(res))]

X_test = [2, 'S']
print('测试数据预测类别为:', predict(X_test))


from sklearn.preprocessing import LabelEncoder
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split

# 数据预处理
x1 = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]
x2 = ['S','M','M','S','S','S','M','M','L','L','L','M','M','L','L']
y = [-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1]

# 将类别特征转换为数值特征
le = LabelEncoder()
x2 = le.fit_transform(x2)

# 划分训练集和测试集
X = list(zip(x1, x2))
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
X_train, y_train = X, y
# 创建并训练模型
model = MultinomialNB()
model.fit(X_train, y_train)

# 测试数据
X_test = {'x1': 2, 'x2': 'S'}
X_test_transformed = [X_test['x1'], le.transform([X_test['x2']])[0]]
# 预测
prediction = model.predict([X_test_transformed])
print(prediction)

  

输出:

测试数据预测类别为: -1
[-1]

二者结果一致!

 

【关键代码说明】

p_y = class_prior[c]
        p_x_y = 1
        for i, x in enumerate(X_test):
            p_x_y *= prior.get((i, x, c), 1e-6)
 
 就是对应:
P(X1|Y) P(X2|Y) ... P(Xn|Y)
 
 
 
 
 
posted @ 2023-09-30 23:21  bonelee  阅读(201)  评论(0编辑  收藏  举报