朴素贝叶斯算法

目录

一、简介

二、算法原理

1.朴素贝叶斯方法

2.先验概率

3.条件概率

4.后验概率

5.拉普拉斯平滑

三、代码实现

1.数据准备

2.计算先验概率

3.计算条件概率

4.计算后验概率 

5.计算结果分析 

6.完整代码

四、总结


 

一、简介

朴素贝叶斯算法是一种基于贝叶斯定理的分类算法,它简单而高效。它的经典应用案例为人所熟知:文本分类(如垃圾邮件过滤)。本文将介绍朴素贝叶斯算法的原理和实现。

二、算法原理

1.朴素贝叶斯方法

朴素贝叶斯方法在分类任务中需要计算先验概率条件概率后验概率
先验概率是基于结论计算的概率,条件概率是通过不同的条件由因推果计算的概率,后验概率则是由先验概率和条件概率共同计算的结果,是作为判断最终结果的依据。
下面我通过一个数据集来直观的介绍这三种概率的计算方法。

a5582910cb60405abd6e74819e61d0ae.png

2.先验概率

先验概率的计算公式如下:

eq?P%28Y%20%3D%20c_%7Bi%7D%29%20%3D%20%5Cfrac%7BN_%7Bi%7D%7D%7BN%7D

其中,Y 是类别变量,c_i​ 是类别的取值,N_i​ 是属于类别 c_i​ 的样本数量,N 是总样本数量。

该数据集中贷款结果为拒绝的数量是6,批准的数量为9,因此先验概率由数据集的贷款结果来计算的结果为:

P(拒绝) = 6/15        P(批准) = 9/15

3.条件概率

条件概率是朴素贝叶斯算法中最重要的部分,它的计算公式如下:

eq?P%28A%7CB%29%20%3D%20%5Cfrac%7BP%28AB%29%7D%7BP%28B%29%7D

基于条件概率可以通过P(B|A)求P(A|B)的就是贝叶斯定理

eq?P%28A%7CB%29%20%3D%20%5Cfrac%7BP%28B%7CA%29*P%28A%29%7D%7BP%28B%29%7D

其中,P(A∣B) 是在给定B条件下A发生的概率,P(B∣A) 是在给定A条件下B发生的概率,P(A) 和 P(B) 分别是A和B的概率。

若有一组数据(工作:否,有房子:否,信誉:非常好),假设贷款批准,则该数据的条件概率为:

P(工作:否|批准) = 4/9        P(有房子:否|批准) = 1/3        P(信誉:非常好|批准) = 4/9        

4.后验概率

后验概率的计算是由先验概率和条件概率组成的,具体公式如下:

eq?P%28Y%20%3D%20c_%7Bi%7D%7CX%20%3D%20f_%7B1%7D%2C%20X%20%3D%20f_%7B2%7D%2C...%2C%20X%20%3D%20f_%7Bn%7D%29%20%3D%20%5Cfrac%7BP%28Y%20%3D%20c_%7Bi%7D%29%5Cprod_%7Bi%3D1%7D%5E%7Bn%7DP%28X%3Df_%7Bi%7D%7CY%3Dc_%7Bi%7D%29%7D%7BP%28X%20%3D%20f_%7B1%7D%2C%20X%20%3D%20f_%7B2%7D%2C...%2C%20X%20%3D%20f_%7Bn%7D%29%7D

由于对所有的P(Y = c_i),上式的分母的值都是一样的,测算时可以忽略父母部分,因此最终的表示式为:

eq?P%28Y%20%3D%20c_%7Bi%7D%7CX%20%3D%20f_%7B1%7D%2C...%2C%20X%20%3D%20f_%7Bn%7D%29%20%3D%20P%28Y%20%3D%20c_%7Bi%7D%29%5Cprod_%7Bi%3D1%7D%5E%7Bn%7DP%28X%3Df_%7Bi%7D%7CY%20%3D%20c_%7Bi%7D%29

对于数据(工作:否,有房子:否,信誉:非常好),它的后验概率为:

P(批准|工作:否,有房子:否,信誉:非常好) = P(批准)*P(工作:否|批准)*P(有房子:否|批准)*P(信誉:非常好) = 9/15 * 4/9 * 1/3 * 4/9 = 16/405 = 0.0395

同理P(拒绝|工作:否,有房子:否,信誉:非常好) = 6/15 * 1 * 1 * 0 = 0,计算表明该数据应该判批准,但是出现的0和1就不得不让人考虑某些决定性因素导致的结果单一化,这可能会造成我们结果预测错误,为了解决这个问题就引入了拉普拉斯平滑。

5.拉普拉斯平滑

拉普拉斯平滑通过在概率估计中引入一个小的正数(通常为1)来平滑概率分布。改变的公式为:

eq?P%28Y%20%3D%20c_%7Bi%7D%7CX%20%3D%20f_%7Bi%7D%29%20%3D%20%5Cfrac%7BN_%7Bi%7D%20+%20a%7D%7BN%20+%20a*%5Cleft%20%7C%20Y%20%3D%20c_%7Bi%7D%20%5Cright%20%7C%7D

a为指定系数,在我们的运算中取1,|Y=c_i|为特征c_i的数量,在计算先验概率时为2,即“拒绝”和“批准”。我们可以算出引入拉普拉斯平滑后的先验概率:

P(拒绝) = 7/17        P(批准) = 10/17

在按上述步骤可以算出该数据的条件概率、后验概率:

P(工作:否|拒绝) = 1039/1428 =0.7275       P(有房子:否|拒绝) = 1071/1309 = 0.8182       P(信誉:非常好|拒绝) = 85/882 = 0.0963
P(工作:否|批准) = 935/2040 = 0.4583      P(有房子:否|批准) =  459/1870 = 0.2455       P(信誉:非常好|批准) = 595/1980 = 0.3005   

P(拒绝|工作:否,有房子:否,信誉:非常好) = 0.0236
P(批准|工作:否,有房子:否,信誉:非常好) = 0.0186

所以数据(工作:否,有房子:否,信誉:非常好)的最终结果是拒绝贷款。

三、代码实现

1.数据准备

# 样本数据
data = {
    '工作': ['否', '否', '是', '是', '否', '是', '否', '否'],
    '有房子': ['否', '否', '否', '是', '是', '否', '否', '是'],
    '信誉': ['一般', '好', '好', '一般', '非常好', '好', '一般', '非常好'],
    '贷款结果': ['拒绝', '拒绝', '批准', '批准', '批准', '批准', '拒绝', '批准']
}

X_train = np.array([
    [0, 0, 0],
    [0, 0, 1],
    [1, 0, 1],
    [1, 1, 0],
    [0, 1, 2],
    [1, 0, 1],
    [0, 0, 0],
    [1, 1, 2]
])
y_train = np.array([0, 0, 1, 1, 1, 1, 0, 1])

2.计算先验概率

# 计算每个类别的先验概率
        self.class_probs = np.zeros(num_classes)
        for i, c in enumerate(self.classes):
            self.class_probs[i] = (np.sum(y == c) + self.alpha) / (float(num_samples) + num_classes * self.alpha)

3.计算条件概率

# 计算每个特征的可能取值数量
        self.num_values = np.zeros(num_features, dtype=int)
        for feature in range(num_features):
            self.num_values[feature] = len(np.unique(X[:, feature]))

        # 计算每个类别下每个特征的条件概率
        self.feature_probs = np.zeros((num_classes, num_features, np.max(self.num_values)))

        for i, c in enumerate(self.classes):
            X_c = X[y == c]
            for feature in range(num_features):
                for value in range(self.num_values[feature]):
                    self.feature_probs[i, feature, value] = (np.sum(X_c[:, feature] == value) + self.alpha) / (
                            float(len(X_c)) + self.num_values[feature] * self.alpha)

4.计算后验概率 

    def predict(self, X):
        num_samples = X.shape[0]
        y_pred = np.zeros(num_samples)

        for i in range(num_samples):
            probs = []
            for j, c in enumerate(self.classes):
                # 计算后验概率
                prob = self.class_probs[j]
                for feature, value in enumerate(X[i]):
                    prob *= self.feature_probs[j, feature, value]
                probs.append(prob)
            y_pred[i] = self.classes[np.argmax(probs)]

        return y_pred.astype(int)

5.计算结果分析 

测试数据

X_test = np.array([
    [0, 0, 2],
    [1, 0, 1]
])

结果

8a1ed765e33f4e8eaef5cd027607b61b.png

分析

与上述计算结果相同,数据(工作:否,有房子:否,信誉:非常好)的结果为拒绝贷款。
另一组测试数据(工作:是,有房子:否,信誉:好)的结果为批准贷款。

6.完整代码

import numpy as np


class NaiveBayes:
    def __init__(self, alpha=1):
        self.alpha = alpha
        self.class_probs = None
        self.feature_probs = None

    def fit(self, X, y):
        num_samples, num_features = X.shape
        self.classes = np.unique(y)
        num_classes = len(self.classes)

        # 计算每个类别的先验概率
        self.class_probs = np.zeros(num_classes)
        for i, c in enumerate(self.classes):
            self.class_probs[i] = (np.sum(y == c) + self.alpha) / (float(num_samples) + num_classes * self.alpha)

        # 计算每个特征的可能取值数量
        self.num_values = np.zeros(num_features, dtype=int)
        for feature in range(num_features):
            self.num_values[feature] = len(np.unique(X[:, feature]))

        # 计算每个类别下每个特征的条件概率
        self.feature_probs = np.zeros((num_classes, num_features, np.max(self.num_values)))

        for i, c in enumerate(self.classes):
            X_c = X[y == c]
            for feature in range(num_features):
                for value in range(self.num_values[feature]):
                    self.feature_probs[i, feature, value] = (np.sum(X_c[:, feature] == value) + self.alpha) / (
                            float(len(X_c)) + self.num_values[feature] * self.alpha)

    def predict(self, X):
        num_samples = X.shape[0]
        y_pred = np.zeros(num_samples)

        for i in range(num_samples):
            probs = []
            for j, c in enumerate(self.classes):
                # 计算后验概率
                prob = self.class_probs[j]
                for feature, value in enumerate(X[i]):
                    prob *= self.feature_probs[j, feature, value]
                probs.append(prob)
            y_pred[i] = self.classes[np.argmax(probs)]

        return y_pred.astype(int)

# 样本数据
data = {
    '工作': ['否', '否', '是', '是', '否', '是', '否', '否'],
    '有房子': ['否', '否', '否', '是', '是', '否', '否', '是'],
    '信誉': ['一般', '好', '好', '一般', '非常好', '好', '一般', '非常好'],
    '贷款结果': ['拒绝', '拒绝', '批准', '批准', '批准', '批准', '拒绝', '批准']
}

X_train = np.array([
    [0, 0, 0],
    [0, 0, 1],
    [1, 0, 1],
    [1, 1, 0],
    [0, 1, 2],
    [1, 0, 1],
    [0, 0, 0],
    [1, 1, 2]
])
y_train = np.array([0, 0, 1, 1, 1, 1, 0, 1])

X_test = np.array([
    [0, 0, 2],
    [1, 0, 1]
])

# 实例化和拟合模型
nb = NaiveBayes(alpha=1)  # 设置拉普拉斯平滑参数alpha
nb.fit(X_train, y_train)

# 预测并输出结果
predictions = nb.predict(X_test)
print("Predictions:", predictions)

四、总结

朴素贝叶斯算法是一种简单而有效的分类方法,在入门机器学习和处理文本数据时具有重要意义。通过本文抛砖引玉,希望读者能够对朴素贝叶斯算法有所了解,若有错误和建议请在评论区中提出。

 

 

  • 23
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值