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 Requests安装与简单运用
Apr 07 Python
Python 正则表达式入门(初级篇)
Dec 07 Python
Python数据分析中Groupby用法之通过字典或Series进行分组的实例
Dec 08 Python
Python实现判断一行代码是否为注释的方法
May 23 Python
python字符串常用方法
Jun 14 Python
python使用selenium登录QQ邮箱(附带滑动解锁)
Jan 23 Python
Python使用sax模块解析XML文件示例
Apr 04 Python
Python Web框架之Django框架cookie和session用法分析
Aug 16 Python
python中使用you-get库批量在线下载bilibili视频的教程
Mar 10 Python
python数据抓取3种方法总结
Feb 07 Python
浅谈tf.train.Saver()与tf.train.import_meta_graph的要点
May 26 Python
python实现股票历史数据可视化分析案例
Jun 10 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
【COS正片】蕾姆睡衣cos,纯洁可爱被治愈了 cn名濑弥七
2020/03/02 日漫
支持oicq头像的留言簿(二)
2006/10/09 PHP
ThinkPHP中的系统常量和预定义常量集合
2014/07/01 PHP
php实现网站留言板功能
2015/11/04 PHP
OAuth认证协议中的HMACSHA1加密算法(实例)
2017/10/25 PHP
纯JavaScript实现HTML5 Canvas六种特效滤镜示例
2013/06/28 Javascript
bootstrap学习笔记之初识bootstrap
2016/06/21 Javascript
vue+axios+mock.js环境搭建的方法步骤
2018/08/28 Javascript
vue将毫秒数转化为正常日期格式的实例
2018/09/16 Javascript
IE8中jQuery.load()加载页面不显示的原因
2018/11/15 jQuery
Nuxt.js 数据双向绑定的实现
2019/02/17 Javascript
vue基础之使用get、post、jsonp实现交互功能示例
2019/03/12 Javascript
ES6知识点整理之数组解构和字符串解构的应用示例
2019/04/17 Javascript
解决vue组件props传值对象获取不到的问题
2019/06/06 Javascript
vue实现多级菜单效果
2019/10/19 Javascript
在Python的Flask框架中构建Web表单的教程
2016/06/04 Python
Python字符串处理实例详解
2017/05/18 Python
python文件名和文件路径操作实例
2017/09/29 Python
python中Apriori算法实现讲解
2017/12/10 Python
Python爬虫工程师面试问题总结
2018/03/22 Python
Python中跳台阶、变态跳台阶与矩形覆盖问题的解决方法
2018/05/19 Python
Python单元测试实例详解
2018/05/25 Python
Python pycharm 同时加载多个项目的方法
2019/01/17 Python
Python 中包/模块的 `import` 操作代码
2019/04/22 Python
Django ORM多对多查询方法(自定义第三张表&ManyToManyField)
2019/08/09 Python
python读取Kafka实例
2019/12/23 Python
Python 实现加密过的PDF文件转WORD格式
2020/02/04 Python
Python getattr()函数使用方法代码实例
2020/08/10 Python
python3 os进行嵌套操作的实例讲解
2020/11/19 Python
HTML5 拖拽批量上传文件的示例代码
2018/03/28 HTML / CSS
Hotels.com中国区:好订网
2016/08/18 全球购物
某科技软件测试面试题
2013/05/19 面试题
小学生学习感言
2014/03/10 职场文书
社保转移委托书范本
2014/10/08 职场文书
2016教师校本研修心得体会
2016/01/08 职场文书
导游词之崇武古城
2019/10/07 职场文书