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 中的int()函数怎么用
Oct 17 Python
Python实现带参数与不带参数的多重继承示例
Jan 30 Python
Python爬虫信息输入及页面的切换方法
May 11 Python
Python中pandas模块DataFrame创建方法示例
Jun 20 Python
python利用requests库进行接口测试的方法详解
Jul 06 Python
使用python进行波形及频谱绘制的方法
Jun 17 Python
详解Python3迁移接口变化采坑记
Oct 11 Python
Python with标签使用方法解析
Jan 17 Python
Python图像处理库PIL的ImageDraw模块介绍详解
Feb 26 Python
python使用PIL剪切和拼接图片
Mar 23 Python
如何将anaconda安装配置的mmdetection环境离线拷贝到另一台电脑
Oct 15 Python
一篇文章弄懂Python关键字、标识符和变量
Jul 15 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
第4章 数据处理-php数组的处理-郑阿奇
2011/07/04 PHP
PHP中“简单工厂模式”实例代码讲解
2012/09/04 PHP
php使用正则过滤js脚本代码实例
2014/05/10 PHP
PHP中使用CURL模拟登录并获取数据实例
2014/07/01 PHP
ThinkPHP框架实现session跨域问题的解决方法
2014/07/01 PHP
php提高脚本性能的4个技巧
2020/08/18 PHP
javascript fullscreen全屏实现代码
2009/04/09 Javascript
JQuery Tips(2) 关于$()包装集你不知道的
2009/12/14 Javascript
jquery实现下拉菜单的二级联动利用json对象从DB取值显示联动
2014/03/27 Javascript
详解JavaScript编程中的数组结构
2015/10/24 Javascript
跟我学习javascript的prototype使用注意事项
2015/11/17 Javascript
深入理解jQuery中的事件冒泡
2016/05/24 Javascript
Bootstrap轮播插件中图片变形的终极解决方案 使用jqthumb.js
2016/07/10 Javascript
JS身份证信息验证正则表达式
2017/06/12 Javascript
详解webpack 多页面/入口支持&公共组件单独打包
2017/06/29 Javascript
详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)
2017/07/13 Javascript
Node.JS更改Windows注册表Regedit的方法小结
2017/08/18 Javascript
jQuery事件对象的属性和方法详解
2017/09/09 jQuery
JS实现可针对算术表达式求值的计算器功能示例
2018/09/04 Javascript
vuedraggable+element ui实现页面控件拖拽排序效果
2020/07/29 Javascript
jquery操作checkbox的常用方法总结【附测试源码下载】
2019/06/10 jQuery
Javascript call及apply应用场景及实例
2020/08/26 Javascript
Vue利用localStorage本地缓存使页面刷新验证码不清零功能的实现
2020/09/04 Javascript
Python 开发Activex组件方法
2009/11/08 Python
Python中的FTP通信模块ftplib的用法整理
2016/07/08 Python
Python学生成绩管理系统简洁版
2020/04/05 Python
Python回文字符串及回文数字判定功能示例
2018/03/20 Python
django之跨表查询及添加记录的示例代码
2018/10/16 Python
python爬虫-模拟微博登录功能
2019/09/12 Python
python tkinter canvas使用实例
2019/11/04 Python
Python3.6 + TensorFlow 安装配置图文教程(Windows 64 bit)
2020/02/24 Python
python 实现数据库中数据添加、查询与更新的示例代码
2020/12/07 Python
法国春天百货官网:Printemps.com
2020/06/29 全球购物
放飞梦想演讲稿800字
2014/08/26 职场文书
2015年加油站站长工作总结
2015/05/27 职场文书
《巨人的花园》教学反思
2016/02/19 职场文书