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中使用swapCase()方法转换大小写的教程
May 20 Python
Python实现截屏的函数
Jul 25 Python
python实现基于SVM手写数字识别功能
May 27 Python
python打包压缩、读取指定目录下的指定类型文件
Apr 12 Python
Python Matplotlib库安装与基本作图示例
Jan 09 Python
用Python+OpenCV对比图像质量的几种方法
Jul 15 Python
Django中reverse反转并且传递参数的方法
Aug 06 Python
python Web flask 视图内容和模板实现代码
Aug 23 Python
Python操作qml对象过程详解
Sep 26 Python
pytorch 中forward 的用法与解释说明
Feb 26 Python
Python实现信息轰炸工具(再也不怕说不过别人了)
Jun 11 Python
Elasticsearch 数据类型及管理
Apr 19 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
WordPress中重置文章循环的rewind_posts()函数讲解
2016/01/11 PHP
php简单复制文件的方法
2016/05/09 PHP
ZendFramework2连接数据库操作实例
2017/04/18 PHP
jQuery实现的跨容器无缝拖动效果代码
2016/06/21 Javascript
angular ngClick阻止冒泡使用默认行为的方法
2016/11/03 Javascript
jQuery访问浏览器本地存储cookie、localStorage和sessionStorage的基本用法
2017/10/20 jQuery
JS和JQuery实现雪花飘落效果
2017/11/30 jQuery
基于Swiper实现移动端页面图片轮播效果
2017/12/28 Javascript
tangram.js库实现js类的方式实例分析
2018/01/06 Javascript
Angular4 反向代理Details实践
2018/05/30 Javascript
VUE简单的定时器实时刷新的实现方法
2019/01/20 Javascript
一些你可能不熟悉的JS知识点总结
2019/03/15 Javascript
node.js如何根据URL返回指定的图片详解
2020/10/21 Javascript
[03:51]吞吞映像 每周精彩击杀top10第二弹
2014/06/25 DOTA
[40:13]Ti4 冒泡赛第二天 iG vs NEWBEE 2
2014/07/15 DOTA
[02:53]DOTA2亚洲邀请赛 NewBee战队巡礼
2015/02/03 DOTA
python实现博客文章爬虫示例
2014/02/26 Python
Python装饰器实现几类验证功能做法实例
2017/05/18 Python
Python简单网络编程示例【客户端与服务端】
2017/05/26 Python
Python分支结构(switch)操作简介
2018/01/17 Python
python八皇后问题的解决方法
2018/09/27 Python
Python中psutil的介绍与用法
2019/05/02 Python
pandas计数 value_counts()的使用
2019/06/24 Python
Python中Unittest框架的具体使用
2019/08/27 Python
python3常用的数据清洗方法(小结)
2019/10/31 Python
Windows下实现将Pascal VOC转化为TFRecords
2020/02/17 Python
python中前缀运算符 *和 **的用法示例详解
2020/05/28 Python
详解CSS3中Media Queries的相关使用
2015/07/17 HTML / CSS
用你熟悉的语言写一个连接ORACLE数据库的程序,能够完成修改和查询工作
2012/06/11 面试题
会计自我鉴定范文
2013/10/06 职场文书
自考生毕业自我鉴定
2013/10/10 职场文书
文秘个人求职信范文
2014/04/22 职场文书
班级心理活动总结
2014/07/04 职场文书
模范教师事迹材料
2014/12/16 职场文书
Django如何创作一个简单的最小程序
2021/05/12 Python
一文搞懂Golang 时间和日期相关函数
2021/12/06 Golang