机器学习实战:基于概率论的分类方法:朴素贝叶斯

mac2022-06-30  9

朴素贝叶斯:

优点:在数据较少的情况下仍然有效,可以处理多类别问题。

缺点:对于输入数据的准备方式较为敏感。适用于标称型数据。

 

贝叶斯决策理论的核心思想:选择具有最高概率的决策。

 

实现内容:以在线社区的留言板为例,为了不影响社区的发展,我们要屏蔽侮辱性的言论,所以要构建 一个快速过滤器,如果某条留言使用了负面或者侮辱性的语言,那么就改将该留言标识为内容不当。

对此问题建立两个类别:侮辱类和非侮辱类,使用1和0分别表示。

接下来首先给出将文本转化为数字向量的过程,然后介绍如何基于这些向量来计算条件概率,并在此基础上构建分类器。

 

1. 准备数据,从文本中构建向量

1 def load_data_set(): 2 """ 3 创建模拟的数据集 4 :return: 单词列表,所属类别 5 """ 6 posting_list=[ 7 ['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'], 8 ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'], 9 ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'], 10 ['stop', 'posting', 'stupid', 'worthless', 'gar e'], 11 ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'], 12 ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']] 13 #1 表示侮辱性的文字, 0代表非侮辱性文字 14 class_vec=[0,1,0,1,0,1] 15 return posting_list,class_vec

 

 

2. 向量转化函数(先获取无重读的词汇表,然后进行向量转化)

1 #获得词汇表,不含重复元素的单词列表 2 def create_vocab_list(data_set): 3 #创建一个空的去重集合 4 vocab_set=set() 5 for item in data_set: 6 # 求两个集合的并集 7 vocab_set=vocab_set | set(item) 8 return list(vocab_set) 9 10 def set_of_words2vec(vocab_list,input_set): 11 """ 12 遍历查看该单词是否出现,出现该单词则该单词置为1 13 :param vocab_list: 所有单词集合列表 14 :param input_set: 输入的数据集 15 :return: 数字向量,0表示存在该单词,1表示不存在该单词 16 """ 17 #创建一个和词汇表等长的向量,并将其元素都设置为0 18 result=[0]*len(vocab_list) 19 # 遍历文档中的所有单词,如果出现了词汇表中的单词,则将输出文档向量中的对应值设为1 20 for word in input_set: 21 if word in vocab_list: 22 result[vocab_list.index(word)]=1 23 else: 24 pass 25 return result

 

3. 训练贝叶斯网络

1 def train_naive_bayes(train_mat,train_category): 2 """ 3 朴素贝叶斯网络训练 4 :param train_mat:是数据向量 5 :param trian_category: 对应的类别 6 :return: 7 """ 8 trian_doc_num=len(train_mat) 9 words_num=len(train_mat[0]) 10 #侮辱性文件出现的概率=文档类别是1的个数/总文档数 11 pos_abusive=np.sum(train_category)/trian_doc_num 12 # 如果其中一个概率为0,最后的乘积也是0,为降低这种影响,可以将所有词的出现数初始化为1,并将分母初始化为2 13 p0num=np.ones(words_num) 14 p1num=np.ones(words_num) 15 p0num_all=2.0 16 p1num_all=2.0 17 18 for i in range(trian_doc_num): 19 #遍历所有文件,如果是侮辱性文件,就计算词侮辱性文件中出现的侮辱性单词的个数 20 # 在for循环中,要遍历训练集中所有文档,一旦某个词语(是侮辱性的1)在某一文档上出现,则对应该词的位置上 21 #个数就加1,p0num和p1num是个特征长度的向量。train_mat[i]加到这个向量上,那么相应的特征词就会有加1。 22 # 而且在所有文档中,该文档的总词数也相加。sum(train_mat[i])文档元素的个数。 23 if train_category[i]==1: 24 p1num+=train_mat[i] 25 p1num_all+=np.sum(train_mat[i]) 26 else: 27 p0num+=train_mat[i] 28 p0num_all+=np.sum(train_mat[i]) 29 # 取log函数,得到的是向量中每个词的概率(相应位置词的个数除于总词数) 30 p1Vect=np.log(p1num/p1num_all) 31 p0Vect=np.log(p0num/p0num_all) 32 return p0Vect,p1Vect,pos_abusive

 

4. 朴素贝叶斯分类函数

1 def classify_naive_bayes(vec2classify,p0vec,p1vec,p_class1): 2 """ 3 使用算法: 4 # 将乘法转换为加法 5 乘法:P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C)/P(F1F2...Fn) 6 加法:P(F1|C)*P(F2|C)....P(Fn|C)P(C) -> log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C)) 7 :param vec2classify: 待测数据[0,1,1,1,1...],即要分类的向量 8 :param p0vec: 类别0,即正常文档的[log(P(F1|C0)),log(P(F2|C0)),log(P(F3|C0)),log(P(F4|C0)),log(P(F5|C0))....]列表 9 :param p1vec: 类别1,即侮辱性文档的[log(P(F1|C1)),log(P(F2|C1)),log(P(F3|C1)),log(P(F4|C1)),log(P(F5|C1))....]列表 10 :param p_class1: 类别1,侮辱性文件的出现概率 11 :return: 类别1 or 0 12 """ 13 p1=np.sum(vec2classify * p1vec) + np.log(p_class1) 14 p0=np.sum(vec2classify * p0vec) + np.log(1-p_class1) 15 if p1>p0: 16 return 1 17 else: 18 return 0

 

5. 测试分类效果

1 def testing_naive_bayes(): 2 # 1. 加载数据集 3 list_post,list_classes=load_data_set() 4 #2. 创建单词向量 5 vocab_list=create_vocab_list(list_post) 6 #3.计算单词是否出现并创建数据矩阵 7 train_mat=[] 8 for post_in in list_post: 9 train_mat.append(set_of_words2vec(vocab_list,post_in)) 10 #4 训练数据 11 p0v,p1v,p_abusive=train_naive_bayes(np.array(train_mat),np.array(list_classes)) 12 #5 测试数据 13 test_one=['love','my','dalmation'] 14 test_one_doc=np.array(set_of_words2vec(vocab_list,test_one)) 15 print('the result is:{}'.format(classify_naive_bayes(test_one_doc,p0v,p1v,p_abusive))) 16 17 if __name__=="__main__": 18 testing_naive_bayes()

 

 

该项目代码github:https://github.com/CynthiaWendy/Machine-Learning-in-Action-NaiveBayes

 

转载于:https://www.cnblogs.com/CynthiaWendy/p/11214283.html

相关资源:跟着Leo机器学习实战–基于概率论的分类方法:朴素贝叶斯
最新回复(0)