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 相关文章推荐
PHP魔术方法__ISSET、__UNSET使用实例
Nov 25 Python
python通过socket查询whois的方法
Jul 18 Python
Python实现文件复制删除
Apr 19 Python
Python程序员面试题 你必须提前准备!(答案及解析)
Jan 23 Python
Random 在 Python 中的使用方法
Aug 09 Python
django-filter和普通查询的例子
Aug 12 Python
python用quad、dblquad实现一维二维积分的实例详解
Nov 20 Python
numpy 返回函数的上三角矩阵实例
Nov 25 Python
python实现引用其他路径包里面的模块
Mar 09 Python
python 生成任意形状的凸包图代码
Apr 16 Python
Django自带的用户验证系统实现
Dec 18 Python
python re模块和正则表达式
Mar 24 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高级编程-函数-郑阿奇
2011/07/04 PHP
redis 队列操作的例子(php)
2012/04/12 PHP
变量在 PHP7 内部的实现(二)
2015/12/21 PHP
php和redis实现秒杀活动的流程
2019/07/17 PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
2019/12/04 PHP
脚本吧 - 幻宇工作室用到js,超强推荐base.js
2006/12/23 Javascript
JavaScript脚本性能的优化方法
2007/02/02 Javascript
JavaScript 设计模式学习 Factory
2009/07/29 Javascript
jQuery EasyUI API 中文文档 - TimeSpinner时间微调器
2011/10/23 Javascript
javascript获取网页中指定节点的父节点、子节点的方法小结
2013/04/24 Javascript
Js+php实现异步拖拽上传文件
2015/06/23 Javascript
js运动应用实例解析
2015/12/28 Javascript
javascript之Array 数组对象详解
2016/06/07 Javascript
jQuery Ajax 上传文件处理方式介绍(推荐)
2016/06/30 Javascript
AngularJs Dependency Injection(DI,依赖注入)
2016/09/02 Javascript
AngularJS过滤器filter用法总结
2016/12/13 Javascript
Web纯前端“旭日图”实现元素周期表
2017/03/10 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
2017/04/17 jQuery
Node.js利用js-xlsx处理Excel文件的方法详解
2017/07/05 Javascript
JavaScript引用类型Function实例详解
2018/08/09 Javascript
Vue路由前后端设计总结
2019/08/06 Javascript
微信小程序 轮播图实现原理及优化详解
2019/09/29 Javascript
vue elementUI 表单校验的实现代码(多层嵌套)
2019/11/06 Javascript
[01:48]帕吉至宝加入游戏,遗迹战场现“千劫神屠”
2018/04/07 DOTA
Python3.4实现远程控制电脑开关机
2018/02/22 Python
Python3+django2.0+apache2+ubuntu14部署网站上线的方法
2018/07/07 Python
Python实现的拉格朗日插值法示例
2019/01/08 Python
Python3爬虫之自动查询天气并实现语音播报
2019/02/21 Python
高级销售员求职信
2013/10/25 职场文书
模具设计与制造专业推荐信
2014/02/16 职场文书
伊索寓言教学反思
2014/05/01 职场文书
调解书格式范本
2015/05/20 职场文书
学历证明范文
2015/06/16 职场文书
元旦联欢晚会主持词
2015/07/01 职场文书
莫言诺贝尔获奖感言(全文)
2015/07/31 职场文书
python实现简易名片管理系统
2021/04/11 Python