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

朴素贝叶斯:

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

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

 

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

 

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

对此问题建立两个类别:侮辱类和非侮辱类,使用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

 

posted @ 2019-07-19 16:52  轩窗尘清  阅读(244)  评论(0编辑  收藏  举报