朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。
最为广泛的两种分类模型是决策树模型(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属于每一类中的可能,找出最大的,这就是朴素贝叶斯的算法思路。
由此得到朴素贝叶斯分类算法流程:
- 利用贝叶斯公式,求出预测得结果属于每一种类别得可能
- 找出最大值
有房 | 婚姻状况 | 拖欠贷款 |
---|---|---|
是 | 单身 | 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!