一、模型
我们要求的最终结果是使 P(|X=x)最大的值,而依据贝叶斯定理可知:
以上公式中x为,待遇测的样本,c为具体的分类标签,由最后的等式可知分母不会发生变化,要求
argminP(|X=x),即求argminP(X=x|Y=|)P(Y=)
损失函数为0,1损失函数。
二、拉布拉斯平滑
从原始模型可以看到,某些情况下概率为0,则整个计算结果为0,这会影响最后的预测结果,所以这里引入了拉布拉斯平滑。
一般的引入方法是在分子中统一加1,而在分母上加上标签类的数目(边缘概率或者条件概率时则是条件标签数目)
三、代码实现
与网上传统的词袋模型不一样,这里我实现了一种更通用的贝叶斯预测模型,适用于多分类和多个特征多个取值的情况,至于词袋模型,我也会在以后贴出代码。不当之处,欢迎批评指正,相互交流,相互提高。
__author__ = 'Gujun(Bill)'
#朴素贝叶斯一般实现
#2018/11/05
class bayes(object):#朴素贝叶斯多分类多特征多取值的通用实现非词袋模型
def __init__(self,class_num,charact_num):
self.class_num = class_num#标签类别数
self.charact_num = charact_num
self.dict_c = {}
self.dict_fun = {}
self.dict_pro = {}
self.dict_fun_pro = {}
def training(self,dataMat):#适用于多分类问题
charact_num = dataMat.shape[1] - 1 #特征数
data_num = dataMat.shape[0] #训练的数据量
sum_c = self.class_num*[0] #用于统计
dict_c = {} #新建字典统计每个类的样本数
dict_fun = {}#某一个类某一个特征取某一值的样本数
dict_pro = {}#每个类的概率
dict_fun_pro = {}#某一类某一特征取某一值的概率
for i in range(data_num):
dict_c[dataMat[i][-1]] += 1
for j in range(charact_num):
dict_fun[dataMat[i][-1]][j][dataMat[i][j]] += 1#第j个特征取的值字典嵌套{A:{B:{C:x}}}
for key in dict_c:
#分子分母分别加了拉布拉斯平滑
dict_pro[key] = (dict_c[key] + 1)/(data_num+self.class_num)
for key1 in dict_fun[key]:
for key2 in dict_fun[key][key1]:
#分子分母分别加了拉布拉斯平滑
dict_fun_pro[key][key1][key2] = (dict_pro[key][key1][key2]+1)/(dict_c[key]
+ len(dict_pro[key][key1][key2])) #计算一类某一特征取某一值的概率
self.dict_c = dict_c
self.dict_fun = dict_fun
self.dict_pro = dict_pro
self.dict_fun_pro = dict_fun_pro
return dict_pro,dict_fun_pro,dict_c,dict_fun
def predict(self,dict_pro,dict_fun_pro,input_vec,dict_c,dict_fun):#预测
pro_max = 0
c_k = dict_c.keys()[0]
for key in dict_pro:
pro_temp = dict_pro[key]
for j in range(self.charact_num):#第j个特征
if input_vec[j] not in dict_fun_pro[key][j]:#如果这一特征出现了训练数据未出现的值
dict_fun_pro[key][j][input_vec[j]] = 1/(dict_c[key] + 1)
pro_temp *= dict_fun_pro[key][j][input_vec[j]]
if pro_temp > pro_max:
pro_max = pro_temp
c_k = key
print("prediction result :",c_k)
return c_k
def predict_to_training(self):#用于将新的预测数据转为训练集中
pass