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中用has_key()方法查找键是否存在的教程
May 21 Python
Python制作钉钉加密/解密工具
Dec 07 Python
python matplotlib中文显示参数设置解析
Dec 15 Python
Python实现的本地文件搜索功能示例【测试可用】
May 30 Python
解决python3运行selenium下HTMLTestRunner报错的问题
Dec 27 Python
pytorch实现用Resnet提取特征并保存为txt文件的方法
Aug 20 Python
python之列表推导式的用法
Nov 29 Python
python清空命令行方式
Jan 13 Python
Python查找不限层级Json数据中某个key或者value的路径方式
Feb 27 Python
django之从html页面表单获取输入的数据实例
Mar 16 Python
python numpy实现rolling滚动案例
Jun 08 Python
python如何使用代码运行助手
Jul 03 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 setcookie指定domain参数后,在IE下设置cookie失效的解决方法
2011/09/09 PHP
PHP5权威编程阅读学习笔记 附电子书下载
2012/07/05 PHP
PHP输出英文时间日期的安全方法(RFC 1123格式)
2014/06/13 PHP
php的GD库imagettftext函数解决中文乱码问题
2015/01/24 PHP
php实现兼容2038年后Unix时间戳转换函数
2015/03/18 PHP
PHP中list()函数用法实例简析
2016/01/08 PHP
PHP实现的防止跨站和xss攻击代码【来自阿里云】
2018/01/29 PHP
Django 标签筛选的实现代码(一对多、多对多)
2018/09/05 PHP
js 表单验证方法(实用)
2009/04/28 Javascript
EasyUi tabs的高度与宽度根据IE窗口的变化自适应代码
2010/10/26 Javascript
js数组的操作指南
2014/12/28 Javascript
js实现仿爱微网两级导航菜单效果代码
2015/08/31 Javascript
echarts学习笔记之箱线图的分析与绘制详解
2017/11/22 Javascript
30分钟快速入门掌握ES6/ES2015的核心内容(上)
2018/04/18 Javascript
vue 不使用select实现下拉框功能(推荐)
2018/05/17 Javascript
Vue中实现权限控制的方法示例
2019/06/07 Javascript
vue(2.x,3.0)配置跨域代理
2019/11/27 Javascript
vue tab切换,解决echartst图表宽度只有100px的问题
2020/07/19 Javascript
Element中Slider滑块的具体使用
2020/07/29 Javascript
python中迭代器(iterator)用法实例分析
2015/04/29 Python
python基于pygame实现响应游戏中事件的方法(附源码)
2015/11/11 Python
实例讲解Python中SocketServer模块处理网络请求的用法
2016/06/28 Python
python字典一键多值实例代码分享
2019/06/14 Python
python挖矿算力测试程序详解
2019/07/03 Python
Python如何在DataFrame增加数值
2020/02/14 Python
Python 调用有道翻译接口实现翻译
2020/03/02 Python
Python进程间通信multiprocess代码实例
2020/03/18 Python
Python关键字及可变参数*args,**kw原理解析
2020/04/04 Python
Opencv+Python识别PCB板图片的步骤
2021/01/07 Python
Michael Kors加拿大官网:购买设计师手袋、手表、鞋子、服装等
2019/03/16 全球购物
师范大学音乐表演专业求职信
2013/10/23 职场文书
个人求职信范文分享
2013/12/13 职场文书
党员公开承诺书
2014/03/25 职场文书
公开承诺书格式
2014/05/21 职场文书
党员对照检查材料整改措施思想汇报
2014/09/26 职场文书
担保公司2015年终工作总结
2015/10/14 职场文书