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实现大文件排序的方法
Jul 10 Python
详解Python中open()函数指定文件打开方式的用法
Jun 04 Python
python机器学习案例教程——K最近邻算法的实现
Dec 28 Python
Python实现针对给定单链表删除指定节点的方法
Apr 12 Python
对python中if语句的真假判断实例详解
Feb 18 Python
python celery分布式任务队列的使用详解
Jul 08 Python
python自动发微信监控报警
Sep 06 Python
关于win10在tensorflow的安装及在pycharm中运行步骤详解
Mar 16 Python
如何使用python切换hosts文件
Apr 29 Python
新版Pycharm中Matplotlib不会弹出独立的显示窗口的问题
Jun 02 Python
Numpy数组的广播机制的实现
Nov 03 Python
用python查找统一局域网下ip对应的mac地址
Jan 13 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
教你如何把一篇文章按要求分段
2006/10/09 PHP
php生成EAN_13标准条形码实例
2013/11/13 PHP
php源码分析之DZX1.5随机数函数random用法
2015/06/17 PHP
7个鲜为人知却非常实用的PHP函数
2015/07/01 PHP
php中mkdir()函数的权限问题分析
2016/09/24 PHP
PHP实现的简单sha1加密功能示例
2017/08/27 PHP
php如何计算两坐标点之间的距离
2018/12/29 PHP
Jquery实现页面加载时弹出对话框代码
2013/04/19 Javascript
jquery 动态创建元素的方式介绍及应用
2013/04/21 Javascript
jquery $.fn $.fx是什么意思有什么用
2013/11/04 Javascript
如何在MVC应用程序中使用Jquery
2014/11/17 Javascript
Windows系统下Node.js的简单入门教程
2015/06/23 Javascript
JS实现状态栏跑马灯文字效果代码
2015/10/24 Javascript
JavaScript中的数据类型转换方法小结
2015/10/26 Javascript
vue中引用阿里字体图标的方法
2018/02/10 Javascript
vue项目中使用vue-i18n报错的解决方法
2019/01/13 Javascript
聊聊鉴权那些事(推荐)
2019/08/22 Javascript
vue 通过 Prop 向子组件传递数据的实现方法
2020/10/30 Javascript
python和ruby,我选谁?
2017/09/13 Python
实例详解Matlab 与 Python 的区别
2019/04/26 Python
Python利用matplotlib做图中图及次坐标轴的实例
2019/07/08 Python
深入解析神经网络从原理到实现
2019/07/26 Python
解决Django后台ManyToManyField显示成Object的问题
2019/08/09 Python
tensorflow模型保存、加载之变量重命名实例
2020/01/21 Python
Python unittest工作原理和使用过程解析
2020/02/24 Python
python实现移动木板小游戏
2020/10/09 Python
英国在线滑雪板和冲浪商店:The Board Basement
2020/01/11 全球购物
总经理助理的职责
2014/03/14 职场文书
教育专业毕业生推荐信
2014/07/10 职场文书
大学奖学金获奖感言
2014/08/15 职场文书
国庆节演讲稿范文2014
2014/09/19 职场文书
大学毕业论文致谢词
2015/05/14 职场文书
团结主题班会
2015/08/13 职场文书
python用tkinter开发的扫雷游戏
2021/06/01 Python
Android Studio实现带三角函数对数运算功能的高级计算器
2022/05/20 Java/Android
使用Nginx+Tomcat实现负载均衡的全过程
2022/05/30 Servers