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


Posted in Python onSeptember 30, 2020

特点

  • 这是分类算法贝叶斯算法的较为简单的一种,整个贝叶斯分类算法的核心就是在求解贝叶斯方程P(y|x)=[P(x|y)P(y)]/P(x)
  • 而朴素贝叶斯算法就是在牺牲一定准确率的情况下强制特征x满足独立条件,求解P(x|y)就更为方便了
  • 但基本上现实生活中,没有任何关系的两个特征几乎是不存在的,故朴素贝叶斯不适合那些关系密切的特征
from collections import defaultdict
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from loguru import logger


class NaiveBayesScratch():
 """朴素贝叶斯算法Scratch实现"""
 def __init__(self):
  # 存储先验概率 P(Y=ck)
  self._prior_prob = defaultdict(float)
  # 存储似然概率 P(X|Y=ck)
  self._likelihood = defaultdict(defaultdict)
  # 存储每个类别的样本在训练集中出现次数
  self._ck_counter = defaultdict(float)
  # 存储每一个特征可能取值的个数
  self._Sj = defaultdict(float)

 def fit(self, X, y):
  """
  模型训练,参数估计使用贝叶斯估计
  X:
   训练集,每一行表示一个样本,每一列表示一个特征或属性
  y:
   训练集标签
  """
  n_sample, n_feature = X.shape
  # 计算每个类别可能的取值以及每个类别样本个数
  ck, num_ck = np.unique(y, return_counts=True)
  self._ck_counter = dict(zip(ck, num_ck))
  for label, num_label in self._ck_counter.items():
   # 计算先验概率,做了拉普拉斯平滑处理,即计算P(y)
   self._prior_prob[label] = (num_label + 1) / (n_sample + ck.shape[0])

  # 记录每个类别样本对应的索引
  ck_idx = []
  for label in ck:
   label_idx = np.squeeze(np.argwhere(y == label))
   ck_idx.append(label_idx)

  # 遍历每个类别
  for label, idx in zip(ck, ck_idx):
   xdata = X[idx]
   # 记录该类别所有特征对应的概率
   label_likelihood = defaultdict(defaultdict)
   # 遍历每个特征
   for i in range(n_feature):
    # 记录该特征每个取值对应的概率
    feature_val_prob = defaultdict(float)
    # 获取该列特征可能的取值和每个取值出现的次数
    feature_val, feature_cnt = np.unique(xdata[:, i], return_counts=True)
    self._Sj[i] = feature_val.shape[0]
    feature_counter = dict(zip(feature_val, feature_cnt))
    for fea_val, cnt in feature_counter.items():
     # 计算该列特征每个取值的概率,做了拉普拉斯平滑,即为了计算P(x|y)
     feature_val_prob[fea_val] = (cnt + 1) / (self._ck_counter[label] + self._Sj[i])
    label_likelihood[i] = feature_val_prob
   self._likelihood[label] = label_likelihood

 def predict(self, x):
  """
  输入样本,输出其类别,本质上是计算后验概率
  **注意计算后验概率的时候对概率取对数**,概率连乘可能导致浮点数下溢,取对数将连乘转化为求和
  """
  # 保存分类到每个类别的后验概率,即计算P(y|x)
  post_prob = defaultdict(float)
  # 遍历每个类别计算后验概率
  for label, label_likelihood in self._likelihood.items():
   prob = np.log(self._prior_prob[label])
   # 遍历样本每一维特征
   for i, fea_val in enumerate(x):
    feature_val_prob = label_likelihood[i]
    # 如果该特征值出现在训练集中则直接获取概率
    if fea_val in feature_val_prob:
     prob += np.log(feature_val_prob[fea_val])
    else:
     # 如果该特征没有出现在训练集中则采用拉普拉斯平滑计算概率
     laplace_prob = 1 / (self._ck_counter[label] + self._Sj[i])
     prob += np.log(laplace_prob)
   post_prob[label] = prob
  prob_list = list(post_prob.items())
  prob_list.sort(key=lambda v: v[1], reverse=True)
  # 返回后验概率最大的类别作为预测类别
  return prob_list[0][0]


def main():
 X, y = load_iris(return_X_y=True)
 xtrain, xtest, ytrain, ytest = train_test_split(X, y, train_size=0.8, shuffle=True)

 model = NaiveBayesScratch()
 model.fit(xtrain, ytrain)

 n_test = xtest.shape[0]
 n_right = 0
 for i in range(n_test):
  y_pred = model.predict(xtest[i])
  if y_pred == ytest[i]:
   n_right += 1
  else:
   logger.info("该样本真实标签为:{},但是Scratch模型预测标签为:{}".format(ytest[i], y_pred))
 logger.info("Scratch模型在测试集上的准确率为:{}%".format(n_right * 100 / n_test))

if __name__ == "__main__":
 main()

以上就是python 实现朴素贝叶斯算法的示例的详细内容,更多关于python实现朴素贝叶斯算法的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python实现设置windows桌面壁纸代码分享
Mar 28 Python
Python实现求两个csv文件交集的方法
Sep 06 Python
django中的setting最佳配置小结
Nov 21 Python
python复制文件到指定目录的实例
Apr 27 Python
Python+OpenCV目标跟踪实现基本的运动检测
Jul 10 Python
python读取和保存图片5种方法对比
Sep 12 Python
Django框架表单操作实例分析
Nov 04 Python
python百行代码自制电脑端网速悬浮窗的实现
May 12 Python
用pandas划分数据集实现训练集和测试集
Jul 20 Python
python 如何设置守护进程
Oct 29 Python
python编程的核心知识点总结
Feb 08 Python
Python实战之大鱼吃小鱼游戏的实现
Apr 01 Python
Python字典取键、值对的方法步骤
Sep 30 #Python
Python根据字典的值查询出对应的键的方法
Sep 30 #Python
python字典通过值反查键的实现(简洁写法)
Sep 30 #Python
python中字典增加和删除使用方法
Sep 30 #Python
Scrapy爬虫文件批量运行的实现
Sep 30 #Python
如何使用scrapy中的ItemLoader提取数据
Sep 30 #Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
Sep 30 #Python
You might like
php set_time_limit(0) 设置程序执行时间的函数
2010/05/26 PHP
解析strtr函数的效率问题
2013/06/26 PHP
详谈php ip2long 出现负数的原因及解决方法
2017/04/05 PHP
Aster vs KG BO3 第一场2.18
2021/03/10 DOTA
document对象execCommand的command参数介绍
2006/08/01 Javascript
javaScript 简单验证代码(用户名,密码,邮箱)
2009/09/28 Javascript
javascript css styleFloat和cssFloat
2010/03/15 Javascript
js 处理URL实用技巧
2010/11/23 Javascript
网站如何做到完全不需要jQuery也可以满足简单需求
2013/06/27 Javascript
js 获取页面高度和宽度兼容 ie firefox chrome等
2014/05/14 Javascript
JS操作XML实例总结(加载与解析XML文件、字符串)
2015/12/08 Javascript
AngularJS中控制器函数的定义与使用方法示例
2017/10/10 Javascript
浅谈Node.js之异步流控制
2017/10/25 Javascript
在Swiper内如何制作CSS3动画效果示例代码
2017/12/07 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
vue总线机制(bus)知识点详解
2020/05/10 Javascript
javascript+Canvas实现画板功能
2020/06/23 Javascript
ES6 十大特性简介
2020/12/09 Javascript
[44:47]Ti4 循环赛第三日 iG vs NaVi
2014/07/12 DOTA
[02:51]2014DOTA2国际邀请赛 IG战队官方纪录片
2014/07/21 DOTA
[45:44]完美世界DOTA2联赛PWL S2 FTD vs PXG 第一场 11.27
2020/12/01 DOTA
python通过正则查找微博@(at)用户的方法
2015/03/13 Python
详解python中的 is 操作符
2017/12/26 Python
python读取word 中指定位置的表格及表格数据
2019/10/23 Python
Pytorch DataLoader 变长数据处理方式
2020/01/08 Python
pygame用blit()实现动画效果的示例代码
2020/05/28 Python
使用HTML5拍照示例代码
2013/08/06 HTML / CSS
HTML5 source标签:媒介元素定义媒介资源
2018/01/29 HTML / CSS
德国内衣、泳装和睡衣网上商店:Bigsize Dessous
2018/07/09 全球购物
法国一家多品牌成衣精品中/高档商店:Graduate Store
2019/08/28 全球购物
大学生见习报告范文
2014/11/03 职场文书
2014年大学学生会工作总结
2014/12/02 职场文书
德劲DE1108畅想
2021/04/22 无线电
5道关于python基础 while循环练习题
2021/11/27 Python
【js设计模式】SOLID五大设计原则
2022/03/24 Javascript
MyBatis在注解上使用动态SQL方式(@select使用if)
2022/07/07 Java/Android