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程序中操作MySQL的基本方法
Jul 29 Python
Python中urllib+urllib2+cookielib模块编写爬虫实战
Jan 20 Python
玩转python爬虫之爬取糗事百科段子
Feb 17 Python
Python3 读、写Excel文件的操作方法
Oct 20 Python
python 一个figure上显示多个图像的实例
Jul 08 Python
在Python中获取操作系统的进程信息
Aug 27 Python
Django 项目布局方法(值得推荐)
Mar 22 Python
Python实现清理微信僵尸粉功能示例【基于itchat模块】
May 29 Python
Pytorch 高效使用GPU的操作
Jun 27 Python
详解Python 中的容器 collections
Aug 17 Python
Python中pass的作用与使用教程
Nov 13 Python
jupyter notebook快速入门及使用详解
Nov 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
中国第一家无线电行
2021/03/01 无线电
php str_replace的替换漏洞
2008/03/15 PHP
destoon调用discuz论坛中带图片帖子的实现方法
2014/08/21 PHP
自己写的php中文截取函数mb_strlen和mb_substr
2015/02/09 PHP
php实现专业获取网站SEO信息类实例
2015/04/02 PHP
PHP模块化安装教程
2016/06/01 PHP
Yii2.0预定义的别名功能小结
2016/07/04 PHP
PHP实现在数据库百万条数据中随机获取20条记录的方法
2017/04/19 PHP
Yii框架学习笔记之应用组件操作示例
2019/11/13 PHP
网页禁用右键实现代码(JavaScript代码)
2009/10/29 Javascript
事件委托与阻止冒泡阻止其父元素事件触发
2014/09/02 Javascript
跟我学习javascript的Date对象
2015/11/19 Javascript
AngularJS 2.0新特性有哪些
2016/02/18 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
2016/07/15 Javascript
Bootstrap基本样式学习笔记之按钮(4)
2016/12/07 Javascript
纯JS实现轮播图
2017/02/22 Javascript
深入理解react-router@4.0 使用和源码解析
2017/05/23 Javascript
使用JavaScript进行表单校验功能
2017/08/01 Javascript
浅谈在Vue.js中如何实现时间转换指令
2019/01/06 Javascript
JS实现横向轮播图(初级版)
2020/06/24 Javascript
[50:29]2014 DOTA2华西杯精英邀请赛 5 24 DK VS iG
2014/05/26 DOTA
[03:13]DOTA2-DPC中国联赛1月25日Recap集锦
2021/03/11 DOTA
Python re模块介绍
2014/11/30 Python
python微信跳一跳系列之自动计算跳一跳距离
2018/02/26 Python
Python中的并发处理之asyncio包使用的详解
2018/04/03 Python
Python ini文件常用操作方法解析
2020/04/26 Python
购买瑞典当代设计的腕表和太阳眼镜:TRIWA
2016/10/30 全球购物
美国的Eastbay旗下的运动款子品牌:Final-Score
2018/01/01 全球购物
CheapTickets香港机票预订网站:CheapTickets.hk
2019/06/26 全球购物
LACOSTE波兰官网:Polo衫、服装和鞋类
2020/09/29 全球购物
使用useBean标志初始化BEAN时如何接受初始化参数
2012/02/11 面试题
教育学专业实习生的自我鉴定
2013/11/26 职场文书
医院党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
房屋买卖协议书范本
2014/09/27 职场文书
2014年项目经理工作总结
2014/11/24 职场文书
表扬稿格式范文
2015/01/16 职场文书