统计学习方法读书笔记8-朴素贝叶斯

首页 » 算法 » 正文

1.朴素贝叶斯的基本方法

统计学习方法读书笔记8-朴素贝叶斯

2.朴素贝叶斯的参数估计

1.极大似然估计

统计学习方法读书笔记8-朴素贝叶斯
统计学习方法读书笔记8-朴素贝叶斯

2.朴素贝叶斯算法

统计学习方法读书笔记8-朴素贝叶斯
统计学习方法读书笔记8-朴素贝叶斯
统计学习方法读书笔记8-朴素贝叶斯

3.贝叶斯估计

用极大似然估计可能出现所要估计的概率值为0的情况,这是会影响到后验概率的计算结果,使分类产生偏差。解决这一问题的方法就是采用贝叶斯估计,原理是在分子、分母中加上指定数值,使得不同项之间大小关系不变,,但消除了分母为0的可能性
统计学习方法读书笔记8-朴素贝叶斯
统计学习方法读书笔记8-朴素贝叶斯
统计学习方法读书笔记8-朴素贝叶斯
统计学习方法读书笔记8-朴素贝叶斯

3.后验概率最大化-期望风险最小化

统计学习方法读书笔记8-朴素贝叶斯
统计学习方法读书笔记8-朴素贝叶斯

4.朴素贝叶斯代码实现

#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: liujie
@software: PyCharm
@file: natives.py
@time: 2020/10/21 17:18
"""
import time
import numpy as np
from tqdm import tqdm


def loaddata(filename):
    """
    加载数据集
    :param filename: 文件路径
    :return: 数据与标签
    """
    # 存放数据及标签
    dataArr = []
    labelArr = []
    # 读取文件
    fr = open(filename)
    # 遍历读取文件每一行
    for line in tqdm(fr.readlines()):
        # 获取当前行,并按','进行切割,返回列表
        curLine = line.strip().split(',')
        # 获取数据
        # 将数据进行了二值化处理,大于128的转换成1,小于的转换成0,方便后续计算
        dataArr.append([int(int(num) > 128) for num in curLine[1:]])
        # 获取标签
        labelArr.append(int(curLine[0]))
    # 返回数据集与标签
    return dataArr, labelArr


def NaivesBayes(Py, Px_y, x):
    """
    通过贝叶斯进行概率估计
    :param Py: 先验概率分布
    :param Px_y: 条件概率分布
    :param x: 要估计的样本
    :return: 返回所有label的估计概率
    """

    # 设置特征数目
    featureNum = 784
    # 设置类别数目
    classNum = 10
    # 建立存放所有标记的概率的数组
    P = [0] * classNum

    # 对于每一个类别,单独估计其概率
    for i in range(classNum):
        # 初始化sum为0,sum为求和项。
        # 在训练过程中对概率进行了log处理,所以这里原先应当是连乘所有概率,最后比较哪个概率最大
        # 但是当使用log处理时,连乘变成了累加,所以使用sum
        sum = 0
        # 获取某一个类别的某个特征的概率,进行累加
        for j in range(featureNum):
            # x[j] = 0或1
            sum += Px_y[i][j][x[j]]
        # 最后再和先验概率相加(也就是式4.7中的先验概率乘以后头那些东西,乘法因为log全变成了加法)
        P[i] = sum + Py[i]
    # 返回该概率最大值对应的索引,即为分类
    return P.index(max(P))


def model_test(Py, Px_y, testDataArr, testLabelArr):
    """
    对数据集进行测试
    :param Py: 先验概率
    :param Px_y: 条件概率
    :param testDataArr:测试数据集
    :param testLabelArr: 测试数据标签
    :return: 返回正确率
    """

    # 错误值计数
    errorCnt = 0
    # 遍历测试集的每一个样本
    for i in tqdm(range(len(testDataArr))):
        # 获取预测值
        predict = NaivesBayes(Py, Px_y, testDataArr[i])
        # 如果预测值不等于标志,则errorCnt + 1
        if predict != testLabelArr[i]:
            errorCnt += 1

    # 返回准确率
    return 1 - (errorCnt / len(testDataArr))


def getAllProbability(trainDataArr, trainLabelArr):
    """
    通过训练集获得先验概率与条件概率
    :param trainDataArr: 训练数据集
    :param trainLabelArr: 训练数据集标签
    :return: 返回先验概率与条件概率
    """
    # 设置特征数目
    featureNum = 784
    # 设置类别数目
    labelNum = 10

    # 初始化先验概率存放数组
    Py = np.zeros((labelNum, 1))
    # 对每个类别进行一次循环,分别计算它们的先验概率分布
    for i in range(labelNum):
        # np.mat(trainLabelArr) == i:将标签转换为矩阵形式,里面的每一位与i比较,若相等,该位变为Ture,反之False
        # np.sum(np.mat(trainLabelArr) == i):计算上一步得到的矩阵中Ture的个数,进行求和(直观上就是找所有label中有多少个
        # 为i的标记,求得4.8式P(Y = Ck)中的分子)
        # 贝叶斯估计:分子加1,分母加上K(K为标签可取的值数量,这里有10个数,取值为10)
        Py[i] = (np.sum(np.mat(trainLabelArr) == True) + 1) / (len(trainLabelArr) + 10)
    # 转为log形式,防止下溢出
    Py = np.log(Py)

    # 计算条件概率 Px_y=P(X=x|Y = y)
    # 计算条件概率分成了两个步骤,下方第一个大for循环用于累加,参考书中“4.2.3 贝叶斯估计 式4.10”,下方第一个大for循环内部是
    # 用于计算式4.10的分子,至于分子的+1以及分母的计算在下方第二个大For内
    # 初始化为全0矩阵,用于存放所有情况下的条件概率,xj只有0和1
    Px_y = np.zeros((labelNum, featureNum, 2))
    # 对标记集进行遍历
    for i in range(len(trainLabelArr)):
        # 获取当前循环所使用的标记
        label = trainLabelArr[i]
        # 获取当前要处理的样本
        x = trainDataArr[i]
        # 对该样本的每一维特诊进行遍历
        for j in range(featureNum):
            # 在矩阵中对应位置加1
            # 这里还没有计算条件概率,先把所有数累加,全加完以后,在后续步骤中再求对应的条件概率
            Px_y[label][j][int(x[j])] += 1

    # 第二个大for循环,计算式4.10的分母,以及分子和分母之间的除法
    # 循环每一个标记
    for label in range(labelNum):
        # 循环每一个标记对应的每一个特征
        for j in range(featureNum):
            # 获取y=label,第j个特诊为0的个数
            Px_y0 = Px_y[label][j][0]
            # 获取y=label,第j个特诊为1的个数
            Px_y1 = Px_y[label][j][1]
            # 对式4.10的分子和分母进行相除,再除之前依据贝叶斯估计,分母需要加上2(为每个特征可取值个数)
            # 分别计算对于y= label,x第j个特征为0和1的条件概率分布
            Px_y[label][j][0] = np.log((Px_y0 + 1) / (Px_y0 + Px_y1 + 2))
            Px_y[label][j][1] = np.log((Px_y1 + 1) / (Px_y0 + Px_y1 + 2))

    return Py, Px_y


if __name__ == '__main__':
    start = time.time()

    # 读取数据集
    print('start to read trainSet')
    trainDataArr, trainLabelArr = loaddata('data/mnist_train.csv')
    print('start to read testSet')
    testDataArr, testLabelArr = loaddata('data/mnist_test.csv')

    # 开始训练,学习先验概率与条件概率分布
    print('start to train')
    Py, Px_y = getAllProbability(trainDataArr, trainLabelArr)

    # 使用习得的先验概率与条件概率分布,开始测试
    print('start to test')
    accuracy = model_test(Py, Px_y, testDataArr, testLabelArr)

    # 打印准确率
    print('accuracy = ', accuracy)
    # 打印时间
    end = time.time()
    print('time=', end - start)

start to read trainSet
100%|██████████| 60000/60000 [00:17<00:00, 3379.31it/s]
start to read testSet
100%|██████████| 10000/10000 [00:02<00:00, 3418.50it/s]
start to train
start to test
100%|██████████| 10000/10000 [00:41<00:00, 242.28it/s]
accuracy =  0.8435
time= 102.47366952896118

未经允许不得转载:作者:1147-柳同学, 转载或复制请以 超链接形式 并注明出处 拜师资源博客
原文地址:《统计学习方法读书笔记8-朴素贝叶斯》 发布于2020-10-21

分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录