Python手工实现朴素贝叶斯分类及预测
朴素贝叶斯的简单介绍
例题及代码实现
下面例题为《人工智能数学基础》第八章的第一道习题
| 职业 |
症状 |
类别 |
| 护士 |
打喷嚏 | 感冒 |
| 农夫 |
打喷嚏 | 过敏 |
| 建筑工人 |
头痛 |
脑震荡 |
| 建筑工人 | 头痛 | 感冒 |
| 教师 | 打喷嚏 | 感冒 |
| 教师 |
头痛 | 脑震荡 |
| 职业 |
症状 |
类别 |
| 护士 |
打喷嚏 | 感冒 |
| 建筑工人 | 头痛 | 感冒 |
| 教师 | 打喷嚏 | 感冒 |
| 职业 |
症状 |
类别 |
| 农夫 |
打喷嚏 | 过敏 |
| 建筑工人 |
头痛 |
脑震荡 |
| 教师 |
头痛 | 脑震荡 |
首先来手算一部分来加深对公式的理解:
(1)设
为感冒,
为过敏,
为脑震荡
则不知道任何信息情况下的先验概率为
(2)设特征 为"职业为建筑工人",则患感冒的人为建筑工人的似然概率
类似的,设特征 为"症状为打喷嚏",则感冒的人打喷嚏的似然概率
(3)此时,打喷嚏且为建筑工人的人患感冒的概率为 。类似的,可以算出脑震荡和过敏的后验概率。
python代码实现如下:
import pandas as pdimport numpy as npdef get_data():'''获取数据,此处为直接输入,也可读取csv文件'''df = pd.DataFrame([['护士', '打喷嚏', '感冒'], ['农夫', '打喷嚏', '过敏'], ['建筑工人', '头痛', '脑震荡'],['建筑工人', '头痛', '感冒'], ['教师', '打喷嚏', '感冒'], ['教师', '头痛', '脑震荡']],columns=['职业', '症状', '类别'])return (df)def test_data(): #获取测试数据,也可读取csv文件df = pd.DataFrame([['建筑工人', '打喷嚏']], columns=['职业', '症状'])return dfclass NBClassify(object):'''创建一个实现朴素贝斯模型的类'''def __init__(self):_tagProbablity = None #使用字典tagProbablity记录各类别的先验概率_featuresProbablity = None #字典featureProbablity记录类别下各特征取值的条件概率def train(self, df):'''传入训练数据df,计算条件概率'''# 计算每种类别的先验概率并输出self._tagProbablity = dict(df['类别'].value_counts(normalize=True))print('各类别的先验概率:\n', self._tagProbablity, '\n')# 计算各特征及取值出现的次数,例如{'职业'{'护士':1, '农夫':1, ...}dictFeaturesBase = {}.fromkeys(df.columns)for column in df.columns:SeriesFeature = dict(df[column].value_counts())dictFeaturesBase[column] = SeriesFeaturedel dictFeaturesBase['类别'] #删除类别信息# print('各特征取值出现次数:\n', dictFeaturesBase)# 初始化字典dictFeatures# 格式{'感冒':{'职业':{'建筑工人':0, '教师':0...},{'症状':...}}'脑震荡':...}dictFeatures = {}.fromkeys(df['类别']) #第一层字典{感冒:None,脑震荡:None...}for key in dictFeatures.keys():dictFeatures[key] = {}.fromkeys(dictFeaturesBase) #第二层字典{'感冒': {'职业': None, '症状': None}...}for key, value in dictFeatures.items():for subkey in value.keys():value[subkey] = {}.fromkeys(dictFeaturesBase[subkey],0) # 第三层字典,初始值设为0# print('dictFeature:\n', dictFeatures) #编写代码时方便理解和调试,可转换成代码执行# 计算各类别,特征值及出现次数,存入字典dictFeatures中for i in range(0, len(df)):label = df.iloc[i]['类别']for feature in df.columns[:-1]:fvalue = df.iloc[i][feature]dictFeatures[label][feature][fvalue] += 1# print(dictFeatures)#计算似然概率for tag, featuresDict in dictFeatures.items():for featureName, featureValueDict in featuresDict.items():totalCount = sum(featureValueDict.values())for featureKey, featureValues in featureValueDict.items():featureValueDict[featureKey] = featureValues / totalCountself._featuresProbablity = dictFeaturesprint('每种特征的似然概率\n:', dictFeatures, '\n')def predict(self, test_data):for i in range(0, len(test_data)): # 遍历测试数据probability = self._tagProbablity # 先验概率for key in probability:for column in test_data.columns:# 先验概率 * Π似然概率probability[key] = probability[key] * self._featuresProbablity[key][column][test_data[column][i]]print(f'第{i+1}位患者的后验概率:', probability)if __name__ == '__main__':'''执行主程序'''data = get_data() #获取训练数据test_data = test_data()model = NBClassify() #定义朴素贝叶斯模型model.train(data)model.predict(test_data)
执行结果为
各类别的先验概率:{'感冒': 0.5, '脑震荡': 0.3333333333333333, '过敏': 0.16666666666666666}每种特征的似然概率: {'感冒': {'职业': {'建筑工人': 0.3333333333333333, '教师': 0.3333333333333333, '护士': 0.3333333333333333, '农夫': 0.0}, '症状': {'打喷嚏': 0.6666666666666666, '头痛': 0.3333333333333333}}, '过敏': {'职业': {'建筑工人': 0.0, '教师': 0.0, '护士': 0.0, '农夫': 1.0}, '症状': {'打喷嚏': 1.0, '头痛': 0.0}}, '脑震荡': {'职业': {'建筑工人': 0.5, '教师': 0.5, '护士': 0.0, '农夫': 0.0}, '症状': {'打喷嚏': 0.0, '头痛': 1.0}}}第1位患者的后验概率: {'感冒': 0.1111111111111111, '脑震荡': 0.0, '过敏': 0.0}
