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翻译软件实现代码(使用google api完成)
Nov 26 Python
Python实现的tab文件操作类分享
Nov 20 Python
python Selenium爬取内容并存储至MySQL数据库的实现代码
Mar 16 Python
Python 网页解析HTMLParse的实例详解
Aug 10 Python
Python实现备份MySQL数据库的方法示例
Jan 11 Python
python二维列表一维列表的互相转换实例
Jul 02 Python
Python实现获取本地及远程图片大小的方法示例
Jul 21 Python
python面试题小结附答案实例代码
Apr 11 Python
如何解决tensorflow恢复模型的特定值时出错
Feb 06 Python
python gui开发——制作抖音无水印视频下载工具(附源码)
Feb 07 Python
pytest进阶教程之fixture函数详解
Mar 29 Python
Python中使用ipython的详细教程
Jun 22 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
杏林同学录(二)
2006/10/09 PHP
php使用pack处理二进制文件的方法
2014/07/03 PHP
php框架知识点的整理和补充
2021/03/01 PHP
jquery实现简易的移动端验证表单
2015/11/08 Javascript
js父页面中使用子页面的方法
2016/01/09 Javascript
JavaScript 经典实例日常收集整理(常用经典)
2016/03/30 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
2016/12/31 Javascript
jQuery插件HighCharts实现的2D回归直线散点效果示例【附demo源码下载】
2017/03/09 Javascript
javascript实现多张图片左右无缝滚动效果
2017/03/22 Javascript
关于vue.js v-bind 的一些理解和思考
2017/06/06 Javascript
Jquery ajax书写方法代码实例解析
2020/06/12 jQuery
Vue 实现创建全局组件,并且使用Vue.use() 载入方式
2020/08/11 Javascript
[00:34]DOTA2上海特级锦标赛 Spirit战队宣传片
2016/03/04 DOTA
python检测lvs real server状态
2014/01/22 Python
Python里disconnect UDP套接字的方法
2015/04/23 Python
你所不知道的Python奇技淫巧13招【实用】
2016/12/14 Python
python的dataframe和matrix的互换方法
2018/04/11 Python
python数字图像处理之骨架提取与分水岭算法
2018/04/27 Python
python ---lambda匿名函数介绍
2019/03/13 Python
使用Python快乐学数学Github万星神器Manim简介
2019/08/07 Python
对tensorflow中的strides参数使用详解
2020/01/04 Python
使用tensorflow DataSet实现高效加载变长文本输入
2020/01/20 Python
Python ORM编程基础示例
2020/02/02 Python
Python文件操作基础流程解析
2020/03/19 Python
用python按照图像灰度值统计并筛选图片的操作(PIL,shutil,os)
2020/06/04 Python
CSS3 实现侧边栏展开收起动画
2014/12/22 HTML / CSS
美国著名的婴儿学步鞋老品牌:Robeez
2016/08/20 全球购物
Tomcat Mysql datasource数据源配置
2015/12/28 面试题
个人能力自我鉴赏
2014/01/25 职场文书
员工培训邀请函
2014/02/02 职场文书
境外导游求职信
2014/02/27 职场文书
司机岗位职责说明书
2014/07/29 职场文书
2015年学校信息技术工作总结
2015/05/25 职场文书
工作建议书范文
2019/07/08 职场文书
经典人生语录分享:不畏将来,不念过去,笑对当下
2019/12/12 职场文书
Django如何与Ajax交互
2021/04/29 Python