zoukankan      html  css  js  c++  java
  • 机器学习实战:基于概率论的分类方法:朴素贝叶斯

    朴素贝叶斯:

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

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

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

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

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

  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/CynthiaWendy/p/11214283.html
Copyright © 2011-2022 走看看