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获取指定路径下所有指定后缀文件的方法
May 26 Python
同时安装Python2 & Python3 cmd下版本自由选择的方法
Dec 09 Python
详谈Python3 操作系统与路径 模块(os / os.path / pathlib)
Apr 26 Python
python sys,os,time模块的使用(包括时间格式的各种转换)
Apr 27 Python
详谈套接字中SO_REUSEPORT和SO_REUSEADDR的区别
Apr 28 Python
python实现求特征选择的信息增益
Dec 18 Python
python爬虫超时的处理的实例
Dec 19 Python
python3.5 cv2 获取视频特定帧生成jpg图片
Aug 28 Python
python 批量修改 labelImg 生成的xml文件的方法
Sep 09 Python
用Python实现校园通知更新提醒功能
Nov 23 Python
python实现的批量分析xml标签中各个类别个数功能示例
Dec 30 Python
Python抓新型冠状病毒肺炎疫情数据并绘制全国疫情分布的代码实例
Feb 05 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获取linux服务器状态的代码
2014/05/27 PHP
CI框架安全类Security.php源码分析
2014/11/04 PHP
jquery插件开发方法(初学者)
2012/02/03 Javascript
js如何取消事件冒泡
2013/09/23 Javascript
原生js制作简单的数字键盘
2015/04/24 Javascript
【JS+CSS3】实现带预览图幻灯片效果的示例代码
2016/03/17 Javascript
jQuery使用cookie与json简单实现购物车功能
2016/04/15 Javascript
Javascript基础之数组的使用
2016/05/13 Javascript
AngularJS 整理一些优化的小技巧
2016/08/18 Javascript
jQuery条件分页 代替离线查询(附代码)
2017/08/17 jQuery
VUE+node(express)实现前后端分离
2019/10/13 Javascript
JS函数参数的传递与同名参数实例分析
2020/03/16 Javascript
详解Vue3.0 + TypeScript + Vite初体验
2021/02/22 Vue.js
[57:09]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第一场 1月26日
2021/03/11 DOTA
Django中login_required装饰器的深入介绍
2017/11/24 Python
python中报错"json.decoder.JSONDecodeError: Expecting value:"的解决
2019/04/29 Python
python 写函数在一定条件下需要调用自身时的写法说明
2020/06/01 Python
Python 基于jwt实现认证机制流程解析
2020/06/22 Python
Python requests接口测试实现代码
2020/09/08 Python
Django celery异步任务实现代码示例
2020/11/26 Python
python脚本使用阿里云slb对恶意攻击进行封堵的实现
2021/02/04 Python
Pytorch - TORCH.NN.INIT 参数初始化的操作
2021/02/27 Python
伦敦哈德森鞋:Hudson Shoes
2018/02/06 全球购物
Europcar澳大利亚官网:全球汽车租赁领域的领导者
2019/03/24 全球购物
英国国家美术馆商店:National Gallery
2019/05/01 全球购物
农村婚礼主持词
2014/03/13 职场文书
环保建议书200字
2014/05/14 职场文书
多媒体教室标语
2014/06/26 职场文书
小学生感恩父母演讲稿
2014/08/28 职场文书
2014年生活老师工作总结
2014/12/23 职场文书
学生评语集锦
2015/01/04 职场文书
嘉年华活动新闻稿
2015/07/17 职场文书
《认识年月日》教学反思
2016/02/19 职场文书
SpringMVC 整合SSM框架详解
2021/08/30 Java/Android
Nginx图片服务器配置之后图片访问404的问题解决
2022/03/21 Servers
Nginx虚拟主机的配置步骤过程全解
2022/03/31 Servers