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下的twisted框架入门指引
Apr 15 Python
简单介绍Python中的decode()方法的使用
May 18 Python
利用Python破解验证码实例详解
Dec 08 Python
Python中Django发送带图片和附件的邮件
Mar 31 Python
Python多进程并发与多线程并发编程实例总结
Feb 08 Python
Python实现修改IE注册表功能示例
May 10 Python
Pandas:DataFrame对象的基础操作方法
Jun 07 Python
tensorflow使用神经网络实现mnist分类
Sep 08 Python
python读文件的步骤
Oct 08 Python
python怎么判断素数
Jul 01 Python
python爬取代理IP并进行有效的IP测试实现
Oct 09 Python
Python内置包对JSON文件数据进行编码和解码
Apr 12 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类
2006/07/15 PHP
完美实现GIF动画缩略图的php代码
2011/01/02 PHP
php从右向左/从左向右截取字符串的实现方法
2011/11/28 PHP
作为PHP程序员应该了解MongoDB的五件事
2013/06/03 PHP
PHP清除缓存的几种方法总结
2017/09/12 PHP
javascript 有用的脚本函数
2009/05/07 Javascript
高性能Javascript笔记 数据的存储与访问性能优化
2012/08/02 Javascript
Javascript操作cookie的函数代码
2012/10/03 Javascript
使用firebug进行调试javascript的示例
2013/12/16 Javascript
jquery实现人性化的有选择性禁用鼠标右键
2014/06/30 Javascript
个人总结的一些JavaScript技巧、实用函数、简洁方法、编程细节
2015/06/10 Javascript
ECHO.js 纯javascript轻量级延迟加载的实例代码
2016/05/24 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
2016/10/14 Javascript
微信小程序 出现47001 data format error原因解决办法
2017/03/10 Javascript
JavaScript常用截取字符串的三种方式用法区别实例解析
2018/05/15 Javascript
js异步上传多张图片插件的使用方法
2018/10/22 Javascript
基于mpvue小程序使用echarts画折线图的方法示例
2019/04/24 Javascript
[01:02:55]CHAOS vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
python 接口_从协议到抽象基类详解
2017/08/24 Python
Python字符串拼接六种方法介绍
2017/12/18 Python
Python GUI编程 文本弹窗的实例
2019/06/11 Python
Python 实现自动导入缺失的库
2019/10/29 Python
如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱
2019/11/19 Python
python通用读取vcf文件的类(复制粘贴即可用)
2020/02/29 Python
聊聊python中的异常嵌套
2020/09/01 Python
基于PyTorch中view的用法说明
2021/03/03 Python
Joe Fresh官网:加拿大时尚品牌和零售连锁店
2016/11/30 全球购物
为您的家、后院、车库等在线购物:Spreetail
2019/06/17 全球购物
小学教研工作制度
2014/01/15 职场文书
优秀管理者事迹材料
2014/05/22 职场文书
软环境建设心得体会
2014/09/09 职场文书
购房个人委托书范本
2014/10/11 职场文书
机关干部作风建设剖析材料
2014/10/23 职场文书
检讨书范文1000字
2015/01/28 职场文书
户外活动总结
2015/02/04 职场文书
2015年十月一日放假通知
2015/08/18 职场文书