更多文章可以访问我的博客Aengus | Blog
朴素贝叶斯是基于贝叶斯定理和特征条件独立假设的分类方法,所谓特征条件独立是指在类别已经确定的条件下,特征之间都是相互独立、互不干扰的,这也正是“朴素”一词的来由。
基本方法
假设输入空间为,输出空间为类标签集合
,测试样本
。朴素贝叶斯通过学习模型得到计算后验概率分布
,将后验概率最大的类作为
的类输出。后验概率通过贝叶斯定理得到:
而根据条件独立假设,有:
代入上式可以得到:
由于分母对于所有的都是相同的,因此朴素贝叶斯可以表示为:
后验概率最大的含义
假设损失函数为:
为决策函数,对联合分布
取期望,这时,期望风险函数为:
由此取条件期望:
为了使期望风险最小化,只需要对逐个极小化,即:
这样就得到了后验概率最大化准则,因此我们说后验概率最大化等价于期望风险最小化。
参数估计
朴素贝叶斯的学习意味着估计和
。
极大似然估计
先验概率的极大似然估计是:
设第个特征
可能取值的集合为
,则条件概率
的极大似然估计是
是第
个样本中的第
个特征;
是第
个特征可能取的第
个值;
为指示函数。
贝叶斯估计
贝叶斯估计可以解决极大似然估计可能出现要估计的概率为0的问题。
对于先验概率,在极大似然估计的基础上分子加;分母加
,
是类别数量;
对于条件概率,在极大似然估计的基础上分子加;分母加
,
为第
个特征可取值的数量;
上述的,常取
,这时称为拉普拉斯平滑。
学习算法
下面是利用极大似然估计进行朴素贝叶斯学习。
假设给定的训练集为,其中
,
,
是第
个样本的第
个特征,
,
是第
个特征的第
个取值,
,
,
。按照以下步骤进行求解:
(1)计算先验概率和条件概率:
(2)对于给定的测试样本,计算:
(3)确定测试样本:
Python实现
这里我用的方法比较复杂,目的是对于复杂的数据集也可以处理,这里没有采用《机器学习实战》那本书中的代码,因为那个代码的分类是1和0,比较简单而且有局限性。因为在实现中数据结构几乎都用了字典还有不少for循环,所以处理数据量比较大的数据集可能很慢。有更简单的方法欢迎交流。
问题主要是在求条件概率上,这里并没有使用指示函数和sum
函数。
- 求先验概率是将所有类别放在字典中,
key
是类别,value
是此类别的概率和数量(之后会用到); - 因为我们最终要求的是
,可以将这个式子转化为
的形式,进一步转化为
,
是数量,在第一步已经求得了此类别的数量,所以接下来求
的同时
的样本数量即可;
- 上面的特征数量存在了字典中,即{类别1: {与测试样本相同特征1: 数量, 与测试样本相同特征2: 数量, ..}, 类别2:{..}, ..};
- 最后返回的语句利用
lambda
表达式将字典中最大的value
所对应的key
返回;
def naive_bayes(dataset, label, test_data):
"""
基于极大似然估计的朴素贝叶斯
:param dataset: 包含标注的训练集[[1, "S"], [2, "M"]]
:param label: 标注
:param test_data: 待分类数据
:return: 预测结果
"""
# 样本数量
m = len(dataset)
# 特征数量
n = len(dataset[0])
# 计算先验概率
pre_probability = {} # 先验概率
count_label = {} # 不同类别的数量
# 初始化每个key的值
for y in label:
pre_probability[y] = 0
count_label[y] = 0
# 计数
for y in label:
count_label[y] += 1
for count in count_label.keys():
pre_probability[count] = count_label[count] / m
# 对测试样本来说,每个特征在训练集中与它相同的数量
# conditional_count = {类别1: {特征1: 数量, 特征2: 数量, ..}, 类别2:{..}, ..}
conditional_count = {}
for y in pre_probability.keys():
conditional_count[y] = {}
for y in pre_probability.keys():
# 初始化训练集中与测试集特征相同的数量
for feature in test_data:
conditional_count[y][feature] = 0
# 计算数量
for y in pre_probability.keys():
for dimension in range(n):
for data_index in range(m):
if label[data_index] == y and test_data[dimension] == dataset[data_index][dimension]:
conditional_count[y][test_data[dimension]] += 1
# 计算后验概率
pos_probability = {}
for y in label:
prob = 1
for count in conditional_count[y].values():
prob *= (count / count_label[y])
prob *= pre_probability[y]
pos_probability[y] = prob
print(pos_probability)
return max(pos_probability.items(), key=lambda d: d[1])[0]
参考
李航《统计学习方法(第二版)》第四章
网友评论