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中列表元素连接方法join用法实例
Apr 07 Python
Python复制文件操作实例详解
Nov 10 Python
python 与GO中操作slice,list的方式实例代码
Mar 20 Python
Python实现的微信公众号群发图片与文本消息功能实例详解
Jun 30 Python
Bottle框架中的装饰器类和描述符应用详解
Oct 28 Python
对pyqt5多线程正确的开启姿势详解
Jun 14 Python
Tensorflow:转置函数 transpose的使用详解
Feb 11 Python
Python多线程多进程实例对比解析
Mar 12 Python
Python 多线程共享变量的实现示例
Apr 17 Python
浅谈keras保存模型中的save()和save_weights()区别
May 21 Python
python爬虫scrapy框架的梨视频案例解析
Feb 20 Python
python装饰器代码解析
Mar 23 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 Static延迟静态绑定用法分析
2016/03/16 PHP
EarthLiveSharp中cloudinary的CDN图片缓存自动清理python脚本
2017/04/04 PHP
PHP封装的XML简单操作类完整实例
2017/11/13 PHP
PJBlog插件 防刷新的在线播放器
2006/10/25 Javascript
Javascript操纵Cookie实现购物车程序
2006/11/23 Javascript
效率高的Javscript字符串替换函数的benchmark
2008/08/02 Javascript
jQuery防止click双击多次提交及传递动态函数或多参数
2014/04/02 Javascript
在JavaScript中用getMinutes()方法返回指定的分时刻
2015/06/10 Javascript
javascript中对变量类型的判断方法
2015/08/09 Javascript
js实现类似菜单风格的TAB选项卡效果代码
2015/08/28 Javascript
JavaScript中Function函数与Object对象的关系
2015/12/17 Javascript
JS仿京东移动端手指拨动切换轮播图效果
2020/04/10 Javascript
Iphone手机、安卓手机浏览器控制默认缩放大小的方法总结(附代码)
2017/08/18 Javascript
node.js实现的装饰者模式示例
2017/09/06 Javascript
vscode下的vue文件格式化问题
2018/11/28 Javascript
vue-cli2 构建速度优化的实现方法
2019/01/08 Javascript
JS创建自定义对象的六种方法总结
2020/12/15 Javascript
win系统下为Python3.5安装flask-mongoengine 库
2016/12/20 Python
python实现快速排序的示例(二分法思想)
2018/03/12 Python
python实现超市扫码仪计费
2018/05/30 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
详解python中sort排序使用
2019/03/23 Python
关于初始种子自动选取的区域生长实例(python+opencv)
2020/01/16 Python
Python中常见的数制转换有哪些
2020/05/27 Python
Python word文本自动化操作实现方法解析
2020/11/05 Python
matplotlib阶梯图的实现(step())
2021/03/02 Python
CSS3中border-radius属性设定圆角的使用技巧
2016/05/10 HTML / CSS
英国旅行箱包和行李箱购物网站:Travel Luggage & Cabin Bags
2019/08/26 全球购物
swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上
2013/07/06 面试题
结对共建协议书
2014/08/20 职场文书
交通事故协议书范本
2014/11/18 职场文书
回复函格式及范文
2015/07/14 职场文书
建立共青团委员会的请示
2019/04/02 职场文书
详解vue中v-for的key唯一性
2021/05/15 Vue.js
SpringMVC 整合SSM框架详解
2021/08/30 Java/Android
JS高级程序设计之class继承重点详解
2022/07/07 Javascript