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中编写数据库模块的教程
Apr 29 Python
用Python程序抓取网页的HTML信息的一个小实例
May 02 Python
Python代码实现KNN算法
Dec 20 Python
Django教程笔记之中间件middleware详解
Aug 01 Python
对python生成业务报表的实例详解
Feb 03 Python
python Tkinter版学生管理系统
Feb 20 Python
详解10个可以快速用Python进行数据分析的小技巧
Jun 24 Python
Python Pandas数据结构简单介绍
Jul 03 Python
python性能测量工具cProfile使用解析
Sep 26 Python
python爬虫添加请求头代码实例
Dec 28 Python
快速解决jupyter notebook启动需要密码的问题
Apr 21 Python
Python 日期与时间转换的方法
Aug 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 面向对象程序设计(oop)学习笔记(三) - 单例模式和工厂模式
2014/06/12 PHP
php将图片保存入mysql数据库失败的解决方法
2014/12/27 PHP
php给图片添加文字水印方法汇总
2015/08/27 PHP
基于PHP实现生成随机水印图片
2020/12/09 PHP
jQuery读取和设定KindEditor值的方法
2013/11/22 Javascript
Jquery节点遍历next与nextAll方法使用示例
2014/07/22 Javascript
node.js开发中使用Node Supervisor实现监测文件修改并自动重启应用
2014/11/04 Javascript
JavaScript设计模式之装饰者模式介绍
2014/12/28 Javascript
jQuery中:first-child选择器用法实例
2014/12/31 Javascript
JS留言功能的简单实现案例(推荐)
2016/06/23 Javascript
整理关于Bootstrap警示框的慕课笔记
2017/03/29 Javascript
NodeJs通过async/await处理异步的方法
2017/10/09 NodeJs
详解Node.js模板引擎Jade入门
2018/01/19 Javascript
Node.js中的child_process模块详解
2018/06/08 Javascript
微信小程序云函数使用mysql数据库过程详解
2019/08/07 Javascript
通过GASP让vue实现动态效果实例代码详解
2019/11/24 Javascript
[04:48]DOTA2亚洲邀请赛林书豪为VGJ加油
2017/04/01 DOTA
详解Python当中的字符串和编码
2015/04/25 Python
Python编程之属性和方法实例详解
2015/05/19 Python
在Python的Django框架中更新数据库数据的方法
2015/07/17 Python
Python中常见的数据类型小结
2015/08/29 Python
Python实现多并发访问网站功能示例
2017/06/19 Python
Python随机函数random()使用方法小结
2018/04/29 Python
Python3使用turtle绘制超立方体图形示例
2018/06/19 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
2019/04/04 Python
Python实现12306火车票抢票系统
2019/07/04 Python
python通过对字典的排序,对json字段进行排序的实例
2020/02/27 Python
windows下python 3.9 Numpy scipy和matlabplot的安装教程详解
2020/11/28 Python
解决margin 外边距合并问题
2019/07/03 HTML / CSS
美国知名户外用品畅销中心:Sierra Trading Post
2016/07/19 全球购物
美国最大的存储市场:SpareFoot
2018/07/23 全球购物
新东方旗下远程教育网站:新东方在线
2020/03/19 全球购物
粗加工管理制度
2014/02/04 职场文书
运动会广播稿诗歌版
2014/09/12 职场文书
个人贷款收入证明
2014/10/26 职场文书
教师考核鉴定意见
2015/06/05 职场文书