1 概述

朴素贝叶斯(Naive Bayesian)法是基于贝叶斯定理与特征条件独立假设的分类方法(注意:朴素贝叶斯法与贝叶斯估计(Beyesian estimation)是不同的概念)。

2 算法

2.1 学习与分类

基本方法

设输入空间03 Naive Bayesian-朴素贝叶斯法 - 图1为n维向量的集合,输出空间为类标记集合03 Naive Bayesian-朴素贝叶斯法 - 图2。输入为特征向量03 Naive Bayesian-朴素贝叶斯法 - 图3,输出为类标记(class label)03 Naive Bayesian-朴素贝叶斯法 - 图403 Naive Bayesian-朴素贝叶斯法 - 图5是定义在输入空间03 Naive Bayesian-朴素贝叶斯法 - 图6上的随机向量,03 Naive Bayesian-朴素贝叶斯法 - 图7是定义在输出空间03 Naive Bayesian-朴素贝叶斯法 - 图8上的随机变量。03 Naive Bayesian-朴素贝叶斯法 - 图9是X和Y的联合概率分布。训练数据集
03 Naive Bayesian-朴素贝叶斯法 - 图10
03 Naive Bayesian-朴素贝叶斯法 - 图11独立同分布产生。
朴素贝叶斯法通过训练数据集学习联合概率分布03 Naive Bayesian-朴素贝叶斯法 - 图12。具体地,学习一下先验概率分布及条件概率分布。先验概率分布
03 Naive Bayesian-朴素贝叶斯法 - 图13 (2.1)

条件概率分布
03 Naive Bayesian-朴素贝叶斯法 - 图14 (2.2)
于是学习得到联合概率分布03 Naive Bayesian-朴素贝叶斯法 - 图15
条件概率分布03 Naive Bayesian-朴素贝叶斯法 - 图16有指数级数量的参数,其估计实际是不可行的。实时上,假设03 Naive Bayesian-朴素贝叶斯法 - 图17可取值有03 Naive Bayesian-朴素贝叶斯法 - 图18个,03 Naive Bayesian-朴素贝叶斯法 - 图1903 Naive Bayesian-朴素贝叶斯法 - 图20可取值有03 Naive Bayesian-朴素贝叶斯法 - 图21个,那么参数个数为03 Naive Bayesian-朴素贝叶斯法 - 图22.
朴素贝叶斯法对条件概率分布做了条件独立性的假设。由于这是一个较强的假设,朴素贝叶斯法也由此得名。具体地,条件独立性假设是
03 Naive Bayesian-朴素贝叶斯法 - 图23 (2.3)
朴素贝叶斯法实际上学习到生成数据的机制,所以属于生成模型。条件独立假设等于是说用于分类的特征在类确定的条件下都是条件独立的。这一假设使朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。
朴素贝叶斯法分类时,对给定的输入03 Naive Bayesian-朴素贝叶斯法 - 图24,通过学习到的模型计算后验概率分布03 Naive Bayesian-朴素贝叶斯法 - 图25,将后验概率最大的类作为03 Naive Bayesian-朴素贝叶斯法 - 图26的类输出。后验概率计算根据贝叶斯定理进行:
03 Naive Bayesian-朴素贝叶斯法 - 图27 (2.4)
将式(2.3)带入(2.4),有
03 Naive Bayesian-朴素贝叶斯法 - 图28 (2.5)
这是朴素贝叶斯法分类的基本公式。于是,朴素贝叶斯分类器可表示为
03 Naive Bayesian-朴素贝叶斯法 - 图29 (2.6)
注意到,在式(2.6)中分母对所有03 Naive Bayesian-朴素贝叶斯法 - 图30都是相同的,所以
03 Naive Bayesian-朴素贝叶斯法 - 图31 (2.7)

后验概率最大化的含义

朴素贝叶斯法将实例分到后验概率最大的类中。这等价于期望风险最小化。假设选择0-1损失函数:
03 Naive Bayesian-朴素贝叶斯法 - 图32
式中03 Naive Bayesian-朴素贝叶斯法 - 图33是分类决策函数。这时,期望风险函数为
03 Naive Bayesian-朴素贝叶斯法 - 图34
期望是对联合分布03 Naive Bayesian-朴素贝叶斯法 - 图35取的。由此取条件期望
03 Naive Bayesian-朴素贝叶斯法 - 图36
为了使期望风险最小化,只需对03 Naive Bayesian-朴素贝叶斯法 - 图37逐个极小化,由此得到:
03 Naive Bayesian-朴素贝叶斯法 - 图38
这样一来,根据期望风险最小化准则就得到了后验概率最大化准则:
03 Naive Bayesian-朴素贝叶斯法 - 图39
即朴素贝叶斯法所采用的的原理。

2.2 参数估计

极大似然估计

在朴素贝叶斯法中,学习意味着估计03 Naive Bayesian-朴素贝叶斯法 - 图4003 Naive Bayesian-朴素贝叶斯法 - 图41。可以应用极大似然估计法估计相应的概率。先验概率03 Naive Bayesian-朴素贝叶斯法 - 图42的极大似然估计是
03 Naive Bayesian-朴素贝叶斯法 - 图43 (2.8)
设第03 Naive Bayesian-朴素贝叶斯法 - 图44个特征03 Naive Bayesian-朴素贝叶斯法 - 图45可能取值的集合为03 Naive Bayesian-朴素贝叶斯法 - 图46,条件概率03 Naive Bayesian-朴素贝叶斯法 - 图47的极大似然估计是
03 Naive Bayesian-朴素贝叶斯法 - 图48
式中,03 Naive Bayesian-朴素贝叶斯法 - 图49是第03 Naive Bayesian-朴素贝叶斯法 - 图50个样本的第03 Naive Bayesian-朴素贝叶斯法 - 图51个特征;03 Naive Bayesian-朴素贝叶斯法 - 图52是第03 Naive Bayesian-朴素贝叶斯法 - 图53个特征可能去的第03 Naive Bayesian-朴素贝叶斯法 - 图54个值;03 Naive Bayesian-朴素贝叶斯法 - 图55为指示函数。

学习与分类算法

下面给出朴素贝叶斯法的学习与分类算法。

算法2.1 (朴素贝叶斯算法(naive Bayes algorithm))

输入:训练数据03 Naive Bayesian-朴素贝叶斯法 - 图56,其中03 Naive Bayesian-朴素贝叶斯法 - 图57,03 Naive Bayesian-朴素贝叶斯法 - 图58是第03 Naive Bayesian-朴素贝叶斯法 - 图59个样本的第03 Naive Bayesian-朴素贝叶斯法 - 图60个特征,03 Naive Bayesian-朴素贝叶斯法 - 图6103 Naive Bayesian-朴素贝叶斯法 - 图62是第03 Naive Bayesian-朴素贝叶斯法 - 图63个特征可能去的第03 Naive Bayesian-朴素贝叶斯法 - 图64个值,03 Naive Bayesian-朴素贝叶斯法 - 图6503 Naive Bayesian-朴素贝叶斯法 - 图6603 Naive Bayesian-朴素贝叶斯法 - 图67;实例03 Naive Bayesian-朴素贝叶斯法 - 图68
输出,实例03 Naive Bayesian-朴素贝叶斯法 - 图69的分类。
(1)计算先验概率及条件概率
03 Naive Bayesian-朴素贝叶斯法 - 图70
03 Naive Bayesian-朴素贝叶斯法 - 图71
(2)对于给定的实例03 Naive Bayesian-朴素贝叶斯法 - 图72,计算
03 Naive Bayesian-朴素贝叶斯法 - 图73
(3)确定实例03 Naive Bayesian-朴素贝叶斯法 - 图74的类

03 Naive Bayesian-朴素贝叶斯法 - 图75

3 实现

3.1 原始算法实现

  1. # -*- coding: UTF-8 -*-
  2. import numpy as np
  3. from functools import reduce
  4. def load_dataset():
  5. """
  6. 创建实验样本
  7. :returns posting_list: 实验样本切分的词条
  8. :returns class_vec: 类别标签向量
  9. """
  10. posting_list = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'], # 切分的词条
  11. ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
  12. ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
  13. ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
  14. ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
  15. ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
  16. class_vec = [0, 1, 0, 1, 0, 1] # 类别标签向量,1代表侮辱性词汇,0代表不是
  17. return posting_list, class_vec # 返回实验样本切分的词条和类别标签向量
  18. def create_vocab_list(data_set):
  19. """
  20. 将切分的实验样本词条整理成不重复的词条列表,也就是词汇表
  21. :param data_set: 整理的样本数据集
  22. :returns vocab_set: 返回不重复的词条列表,也就是词汇表
  23. """
  24. vocab_set = set([]) # 创建一个空的不重复列表
  25. for document in data_set:
  26. vocab_set = vocab_set | set(document) # 取并集
  27. return list(vocab_set)
  28. def set_off_words2vec(vocab_list, input_set):
  29. """
  30. 根据vocab_list词汇表,将input_set向量化,向量的每个元素为1或0
  31. :param vocab_list: create_vocab_list返回的列表 input_set - 切分的词条列表
  32. :returns return_vec: 文档向量,词集模型
  33. """
  34. return_vec = [0] * len(vocab_list) # 创建一个其中所含元素都为0的向量
  35. for word in input_set: # 遍历每个词条
  36. if word in vocab_list: # 如果词条存在于词汇表中,则置1
  37. return_vec[vocab_list.index(word)] = 1
  38. else:
  39. print("the word: %s is not in my Vocabulary!" % word)
  40. return return_vec
  41. def train_nb0(train_matrix, train_category):
  42. """
  43. 朴素贝叶斯分类器训练函数
  44. :param train_matrix: 训练文档矩阵,即setOfWords2Vec返回的returnVec构成的矩阵
  45. :param train_category: 训练类别标签向量,即loadDataSet返回的classVec
  46. :returns p0_vect: 非的条件概率数组
  47. :returns p1_vect: 侮辱类的条件概率数组
  48. :returns p_abusive: 文档属于侮辱类的概率
  49. """
  50. num_train_docs = len(train_matrix) # 计算训练的文档数目
  51. num_words = len(train_matrix[0]) # 计算每篇文档的词条数
  52. p_abusive = sum(train_category) / float(num_train_docs) # 文档属于侮辱类的概率
  53. p0_num = np.zeros(num_words);
  54. p1_num = np.zeros(num_words) # 创建numpy.zeros数组,
  55. p0_denim = 0.0;
  56. p1_denim = 0.0 # 分母初始化为0.0
  57. for i in range(num_train_docs):
  58. if train_category[i] == 1: # 统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···
  59. p1_num += train_matrix[i]
  60. p1_denim += sum(train_matrix[i]) ## 该词条的总的词数目 这压样求得每个词条出现的概率 P(w1),P(w2), P(w3)...
  61. else: # 统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···
  62. p0_num += train_matrix[i]
  63. p0_denim += sum(train_matrix[i])
  64. p1_vect = p1_num / p1_denim # 相除
  65. p0_vect = p0_num / p0_denim
  66. return p0_vect, p1_vect, p_abusive # 返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率
  67. def classify_nb(vec2classify, p0vec, p1_vec, p_class1):
  68. """
  69. 朴素贝叶斯分类器分类函数
  70. :param vec2classify: 待分类的词条数组
  71. :param p0vec: 非侮辱类的条件概率数组
  72. :param p1_vec: 侮辱类的条件概率数组
  73. :param p_class1: 文档属于侮辱类的概率
  74. :returns 类别: 0 - 属于非侮辱类、1 - 属于侮辱类
  75. """
  76. p1 = reduce(lambda x, y: x * y, vec2classify * p1_vec) * p_class1 # 对应元素相乘 这里需要好好理解一下
  77. p0 = reduce(lambda x, y: x * y, vec2classify * p0vec) * (1.0 - p_class1)
  78. print('p0:', p0)
  79. print('p1:', p1)
  80. if p1 > p0:
  81. return 1
  82. else:
  83. return 0
  84. def testing_nb():
  85. """
  86. 测试朴素贝叶斯分类器
  87. """
  88. list_o_posts, list_classes = load_dataset() # 创建实验样本
  89. my_vocab_list = create_vocab_list(list_o_posts) # 创建词汇表
  90. train_mat = []
  91. for postin_doc in list_o_posts:
  92. train_mat.append(set_off_words2vec(my_vocab_list, postin_doc)) # 将实验样本向量化
  93. p0_v, p1_v, p_ab = train_nb0(np.array(train_mat), np.array(list_classes)) # 训练朴素贝叶斯分类器
  94. test_entry = ['love', 'my', 'dalmation'] # 测试样本1
  95. this_doc = np.array(set_off_words2vec(my_vocab_list, test_entry)) # 测试样本向量化
  96. if classify_nb(this_doc, p0_v, p1_v, p_ab):
  97. print(test_entry, '属于侮辱类') # 执行分类并打印分类结果
  98. else:
  99. print(test_entry, '属于非侮辱类') # 执行分类并打印分类结果
  100. test_entry = ['stupid', 'garbage'] # 测试样本2
  101. this_doc = np.array(set_off_words2vec(my_vocab_list, test_entry)) # 测试样本向量化
  102. if classify_nb(this_doc, p0_v, p1_v, p_ab):
  103. print(test_entry, '属于侮辱类') # 执行分类并打印分类结果
  104. else:
  105. print(test_entry, '属于非侮辱类') # 执行分类并打印分类结果
  106. if __name__ == '__main__':
  107. testing_nb()

4 实践

4.1 一般使用流程

4.2 超参数和模型参数

4.3 基于scikit-learn的使用

5 问题集合

1. 用极大似然估计退出朴素贝叶斯发中的概率估计公式(2.8)及公式(2.9)。
2. 用贝叶斯估计法推出朴素贝叶斯法中的概率估计公式(2.10)及公式(2.11)。

6 继续阅读

详见《统计机器学习》第二版03 Naive Bayesian-朴素贝叶斯法 - 图76参考文献

CHANGELOG

2020年12月15日20:40:11

第一版更新,参考自《统计机器学习》第二版 03 Naive Bayesian-朴素贝叶斯法 - 图77-03 Naive Bayesian-朴素贝叶斯法 - 图78