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 相关文章推荐
python3使用tkinter实现ui界面简单实例
Jan 10 Python
Python中的time模块与datetime模块用法总结
Jun 30 Python
Python读写Json涉及到中文的处理方法
Sep 12 Python
利用python生成一个导出数据库的bat脚本文件的方法
Dec 30 Python
用python写一个windows下的定时关机脚本(推荐)
Mar 21 Python
Python3多进程 multiprocessing 模块实例详解
Jun 11 Python
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
Apr 09 Python
Ubuntu+python将nii图像保存成png格式
Jul 18 Python
pyinstaller打包成无控制台程序时运行出错(与popen冲突的解决方法)
Apr 15 Python
利用OpenCV中对图像数据进行64F和8U转换的方式
Jun 03 Python
Django如何实现防止XSS攻击
Oct 13 Python
Python包管理工具pip的15 个使用小技巧
May 17 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网站提速三大“软”招
2006/10/09 PHP
深入Memcache的Session数据的多服务器共享详解
2013/06/13 PHP
Linux环境下搭建php开发环境的操作步骤
2013/06/17 PHP
php中JSON的使用与转换
2015/01/14 PHP
js 数值转换为3位逗号分隔的示例代码
2014/02/19 Javascript
Node.js文件操作详解
2014/08/16 Javascript
javascript获取文档坐标和视口坐标
2015/05/26 Javascript
快速学习jQuery插件 Form表单插件使用方法
2015/12/01 Javascript
js学习阶段总结(必看篇)
2016/06/16 Javascript
jquery实现tab键进行选择后enter键触发click行为
2017/03/29 jQuery
jquery中each循环的简单回滚操作
2017/05/05 jQuery
Vue 创建组件的两种方法小结(必看)
2018/02/23 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
基于Bootstrap下拉框插件bootstrap-select使用方法详解
2018/08/07 Javascript
如何从0开始用node写一个自己的命令行程序
2018/12/29 Javascript
详解JavaScript中的函数、对象
2019/04/01 Javascript
vue-父子组件和ref实例详解
2019/11/10 Javascript
小谈angular ng deploy的实现
2020/04/07 Javascript
vue 里面的 $forceUpdate() 强制实例重新渲染操作
2020/09/21 Javascript
[43:24]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS Liquid
2018/03/30 DOTA
[02:02:38]VG vs Mineski Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
Python和JavaScript间代码转换的4个工具
2016/02/22 Python
详解MySQL数据类型int(M)中M的含义
2016/11/20 Python
Django使用Mysql数据库已经存在的数据表方法
2018/05/27 Python
无法使用pip命令安装python第三方库的原因及解决方法
2018/06/12 Python
python用opencv完成图像分割并进行目标物的提取
2020/05/25 Python
详解python算法常用技巧与内置库
2020/10/17 Python
整个世界的设计师家具在哈恩:Designathome
2019/03/25 全球购物
美国儿童服装、家具和玩具精品店:Maisonette
2019/11/24 全球购物
自荐信范文
2013/12/10 职场文书
大学生职业规划范文:象牙塔生活的四年计划
2014/01/14 职场文书
主要负责人任命书
2014/06/06 职场文书
课外小组活动总结
2014/08/27 职场文书
个人整改措施落实情况汇报
2014/10/29 职场文书
CSS 实现多彩、智能的阴影效果
2021/05/12 HTML / CSS
Mybatis 一级缓存和二级缓存原理区别
2022/09/23 Java/Android