朴素贝叶斯算法原理与Python实现
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法[1]。最为广泛的两种分类模型是决策树模型(Decision Tree Model)和朴素贝叶斯模型(Naive Bayesian Model,NBM)。和决策树模型相比,朴素贝叶斯分类器(Naive Bayes Classifier 或 NBC)发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率。同时,NBC模型所需估计的参数很少,
1 算法介绍
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。
最为广泛的两种分类模型是决策树模型(Decision Tree Model)和朴素贝叶斯模型(Naive Bayesian Model,NBM)。和决策树模型相比,朴素贝叶斯分类器(Naive Bayes Classifier 或 NBC)发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率。同时,NBC模型所需估计的参数很少,对缺失数据不太敏感,算法也比较简单。理论上,NBC模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为NBC模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,这给NBC模型的正确分类带来了一定影响。
朴素贝叶斯公式如下:
这个是什么意思呢?该如何用呢?相信大家有一定的概率知识基础的同学,对先验概率及条件概率都比较清楚,在这里简单的说一下这条公式的含义:
1、首先代表的意思就是在B条件发生的情况下,Ai发生的概率
2、这公式代表的意思就是,在所有A类的结果中,B发生的概率之和,也就是B的概率
3、所以在这个公式,表达的意思就是(B条件发生的情况下,Ai发生的概率=Ai与B同时发生的概率占整个B发生的概率的多少)
于是这个公式就可以转化为,(加上后面这个公式,是为了让我们更好的理解,实际上的使用,一般只用第一个等式的公式)
4、因此,由于P(B)是固定得,所以发生得概率与分子相关,也就是分子越大,概率越高
5、推导过程如下:
仔细品了一下这个公式,也确实发现其很适合用在分类的算法中;对于这个贝叶斯公式来说,就像是求B属于Ai的概率,运用在分类中,就得先求出B属于每一类中的可能,找出最大的,这就是朴素贝叶斯的算法思路。
由此得到朴素贝叶斯分类算法流程:
- 利用贝叶斯公式,求出预测得结果属于每一种类别得可能
- 找出最大值
2 案例介绍
有房 | 婚姻状况 | 拖欠贷款 |
---|---|---|
是 | 单身 | no |
否 | 已婚 | no |
否 | 单身 | no |
是 | 已婚 | no |
否 | 离婚 | yes |
否 | 已婚 | no |
是 | 离婚 | no |
否 | 单身 | yes |
否 | 已婚 | no |
否 | 单身 | yes |
是 | 已婚 | no |
是 | 已婚 | no |
是 | 已婚 | yes |
基于上面的数据,希望预测没房、单身的人,会不会拖欠贷款???
代码流程:
- 先将样本数据处理成字典,并统计每一类发生得个数(第一个函数)
- 将待预测得样本写入,并根据之前得样本数据,对分类结果进行求概率,得出最大概率得分类结果
代码如下:
import pandas as pd
def handle_data(data):
"""
将数据处理成字典,用于保存样本数据中的类别数据存储情况
:param data: dataframe 数据源
:return:样本数据中的类别数据字典,分类结果字典
"""
# 初始化类别数据字典
cate_dict = {}
# 数据集表头列表(各个条件及分类结果)
header_list = data.columns.tolist()
# 条件列表
factor_list = header_list[:-1]
# 分类结果所在位置
k = len(header_list) - 1
# result_dict 为分类的结果类型字典
result_dict = dict(data.iloc[:, k].value_counts())
# 或使用如下语句:
# result_dict = dict(data.iloc[:, -1].value_counts())
result_dict_key = result_dict.keys()
# 将每个分类结果写入 cate_dict
# 循环各个分类结果
for result_key in result_dict_key:
# 如果类别数据字典不存在该分类结果,默认设置空字典
if result_key not in cate_dict:
# dict.setdefault(key, default=None) 键不存在于字典中,将会添加键并将值设为默认值
cate_dict.setdefault(result_key, {})
# 在该分类结果下,循环各个条件(因素)
for factor in factor_list:
# 如果该分类结果字典不存在该条件(因素),默认设置空字典
if factor not in cate_dict[result_key]:
cate_dict[result_key].setdefault(factor, {})
# 获取该条件的分类列表
factor_key_list = data[factor].value_counts().index.tolist()
# 循环获取该条件的各个分类数量
for key in factor_key_list:
# 获取该分类结果下,该因素中某个分类的数量
number = data[(data[header_list[k]] == result_key) & (data[factor] == key)].shape[0]
if key not in cate_dict[result_key][factor]:
cate_dict[result_key][factor].setdefault(key, number)
return cate_dict, result_dict
def calculate(cate_dict, result_dict, new_data):
"""
对每个待预测得结果进行贝叶斯公式得计算,并得出预测类别与概率
:param cate_dict: 样本数据中的类别数据字典
:param result_dict: 分类结果字典
:param new_data: 待预测的数据集
:return: 预测结果列表
"""
# 获取数据集的各个条件(因素)列表
factor_list = new_data.columns.tolist()
# 初始化预测结果列表
result_list = []
# 分类结果列表
result_key_list = cate_dict.keys()
# 循环预测新数据
for i in range(len(new_data)):
new_result_dict = {}
# 循环计算各个分类指标的概率
for result_key in result_key_list:
# 该分类结果在所有分类结果中的占比
all_ratio = result_dict[result_key] / sum(list(result_dict.values()))
# 循环获取该分类结果下,该因素中各个 分类 在 该分类结果 中的占比
for factor in factor_list:
ratio = cate_dict[result_key][factor][new_data.iloc[i, factor_list.index(factor)]] / result_dict[result_key]
# 总占比 乘以 该因素下的各个分类占比
all_ratio *= ratio
new_result_dict.setdefault(result_key, all_ratio)
print(new_result_dict)
# 获取占比最大的分类结果
max_result_key = max(new_result_dict, key=new_result_dict.get)
# 获取占比最大的分类结果的占比
max_value = new_result_dict[max_result_key]
result_list.append([max_result_key, max_value])
return result_list
if __name__ == '__main__':
file_path = "./朴素贝叶斯数据集.xlsx"
data = pd.read_excel(file_path)
print("数据源\n", data)
# 待预测数据
new_data = pd.DataFrame({"有房": "是", "婚姻状况": "已婚"}, index=[0])
cate_dict, result_dict = handle_data(data)
print(cate_dict)
print(result_dict)
result = calculate(cate_dict, result_dict, new_data)
print(result)
运行结果:
数据源
有房 婚姻状况 拖欠贷款
0 是 单身 no
1 否 已婚 no
2 否 单身 no
3 是 已婚 no
4 否 离婚 yes
5 否 已婚 no
6 是 离婚 no
7 否 单身 yes
8 否 已婚 no
9 否 单身 yes
10 是 已婚 no
11 是 已婚 no
12 是 已婚 yes
{'no': {'有房': {'否': 4, '是': 5}, '婚姻状况': {'已婚': 6, '单身': 2, '离婚': 1}}, 'yes': {'有房': {'否': 3, '是': 1}, '婚姻状况': {'已婚': 1, '单身': 2, '离婚': 1}}}
{'no': 9, 'yes': 4}
{'no': 0.2564102564102564, 'yes': 0.019230769230769232}
[['no', 0.2564102564102564]]
所以得出结果为NO!
更多推荐
所有评论(0)