本站消息

站长简介


前每日优鲜python全栈开发工程师,自媒体达人,逗比程序猿,钱少话少特宅,我的公众号:想吃麻辣香锅

  python大神匠心打造,零基础python开发工程师视频教程全套,基础+进阶+项目实战,包含课件和源码

  出租广告位,需要合作请联系站长



+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2020-06(12)

2020-07(30)

2020-08(30)

2020-09(66)

2020-10(79)

朴素贝叶斯算法——文本分类(离散型)

发布于2021-04-24 19:15     阅读(599)     评论(0)     点赞(28)     收藏(0)


0

1

2

3

4

5

6



朴素贝叶斯算法:按照概率分类的算法。

我们在豆瓣上经常能看到一些书籍和电影评价,有好的评价,也有差评。

关于影评好坏的结果是怎么来的呢?后台小姐姐一条条的看,然后进行分类吗?利用我们的朴素贝叶斯算法, 可以实现对文本的分类

在上代码之前先来进行一下数学预热:

概率基础复习

定义:概率定义为一件事发生的可能性,扔出一个硬币,结果头像朝上

P(X):取值在[0,1]

联合概率、条件概率与相互独立:

联合概率:包含多个条件,且所有条件同时成立的概率

                  记作:P(A,B)

条件概率:就是事件A在另外一个事件B已经发生条件下的发生概率

                  记作:P(A|B)

相互独立:如果P(A,B) = P(A)P(B),则称事件A与事件B相互独立

朴素贝叶斯公式:

朴素贝叶斯,简单理解,就是假定了特征与特征之间相互独立的贝叶斯公式。

也就是说,朴素贝叶斯,之所以朴素,就在于假定了特征与特征相互独立。

在这个案例中,需要用到的包:numpy

  1. import numpy as np
  2. def loadDataSet():
  3. """
  4. 加载训练数据, postingList是所有的训练集, 每一个列表代表一条言论, 一共有6条言论 classVec代表每一条言论的类别,
  5. 0是正常, 1是有侮辱性 返回 言论和类别
  6. :return:
  7. """
  8. # 步骤的缺失,和正常的比较,此处省略了文本的切割,都是直接弄好的,直接切割成单词用了
  9. postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
  10. ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
  11. ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
  12. ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
  13. ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
  14. ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
  15. classVec = [0,1,0,1,0,1]
  16. return postingList,classVec
  17. def createVocabList(dataSet):
  18. """
  19. 创建词汇表, 就是把这个文档中所有的单词不重复的放在一个列表里面
  20. :param dataSet:
  21. :return:
  22. """
  23. vocabSet = set([])
  24. for data in dataSet:
  25. # 此处的|表示合并两个集合
  26. vocabSet = vocabSet | set(data)
  27. return list(vocabSet)
  28. def setofword(vacablist,inputdata):
  29. """
  30. 制作词向量矩阵
  31. 将每一个文档转换为词向量, 然后放入矩阵中
  32. :param vocabSet:
  33. :param dataSet:
  34. :return:
  35. """
  36. vectors=[]
  37. # 两个向量相乘,一开始默认都是0
  38. vectors = [0] * len(vacablist)
  39. for word in inputdata:
  40. if word in vacablist:
  41. vectors[vacablist.index(word)] = 1
  42. else:
  43. print(f'没有{word}这个词')
  44. # print('没有 {} 这个词'.format(word))
  45. return vectors
  46. def trainNB1(trainMat,trainCategory):
  47. """
  48. 根据上面set集合提取出来,一共有32个特征
  49. trainMat是文档矩阵[]32位0,1,trainCategory是每篇文档类别标签所构成的向量[0,1,0,1,0,1]
  50. """
  51. # 总的训练语句数=文档矩阵的条数6
  52. numTrainDocs = len(trainMat)
  53. # 总的词数 此处为32
  54. numWords = len(trainMat[0])
  55. # 矩阵的sum是所有元素相加,此处是0+1+0+1+0+1=3
  56. sumOfCate1 = sum(trainCategory)
  57. # 6-3 = 3
  58. sumOfCate0 = len(trainCategory) - sumOfCate1
  59. # 侮辱性词汇的概率 = 3/6 =0.5
  60. pAbusive = sumOfCate1/float(numTrainDocs)
  61. # 创建一个32位的1矩阵,表示初始的p0,为了避免出现零的情况,根据拉普拉斯公式创建1填充的矩阵
  62. p0Num = np.ones(numWords)
  63. # 创建一个32位的1矩阵,表示初始的p1,为了避免出现零的情况,根据拉普拉斯公式创建1填充的矩阵
  64. p1Num = np.ones(numWords)
  65. # 创建一个变量p0Denom 非侮辱性词汇总数,为了避免出现零的情况,根据拉普拉斯公式设置为2.0
  66. p0Denom = 2.0
  67. # 创建一个变量p1Denom 侮辱性词汇总数,为了避免出现零的情况,根据拉普拉斯公式设置为2.0
  68. p1Denom = 2.0
  69. #计算每个词在对应类别中出现的样本数量
  70. for i in range(numTrainDocs):
  71. if trainCategory[i] == 1:
  72. # 最终得到一个侮辱性的32位矩阵
  73. p1Num += trainMat[i]
  74. p1Denom += sum(trainMat[i])
  75. else:
  76. # 最终得到一个非侮辱性的32位矩阵
  77. p0Num += trainMat[i]
  78. p0Denom += sum(trainMat[i])
  79. # log不能直接对矩阵进行操作,np.log
  80. # 词出现的样本数与一个分类样本所有样本数量的比
  81. # 得到侮辱性词汇概率矩阵 (矩阵除以一个浮点数)
  82. # 为了防止下溢出的问题,把矩阵转化成对数的形式,f(x)与ln(f(x))趋势和极值点相同
  83. p1Vect = np.log(p1Num/p1Denom)
  84. # 得到非侮辱性词汇概率矩阵 (矩阵除以一个浮点数)
  85. p0Vect = np.log(p0Num/p0Denom)
  86. return p0Vect,p1Vect,pAbusive
  87. # 用得到的概率分类
  88. def classfyNB(vec2Classify, p0Vect, p1Vect, pAbusive):
  89. """
  90. 参数包括要分类的向量vec2Classify
  91. 以及使用函数trainNB1()计算得到的三个概率
  92. """
  93. # 使用numpy数组来计算两个向量相乘的结果,这里的相乘是指对应元素相乘,
  94. # 即先将两个向量中的第一个元素相乘,然后将第二个元素相乘,以此类推
  95. p1 = sum(vec2Classify * p1Vect) + np.log(pAbusive)
  96. p0 = sum(vec2Classify * p0Vect) + np.log(1.0 - pAbusive)
  97. if p1 > p0:
  98. return 1
  99. else:
  100. return 0
  101. #测试代码
  102. def testingNB():
  103. print('数字0表示没有侮辱性,数字1表示有侮辱性:')
  104. dataSet, listClasses = loadDataSet()
  105. myVocabList = createVocabList(dataSet)
  106. # print(f'我是词袋长度{len(myVocabList)}')
  107. # print(f'我是词袋{dataSet}')
  108. trainMat = []
  109. for data in dataSet:
  110. trainMat.append(setofword(myVocabList,data))
  111. # print(f'我是矩阵{trainMat}')
  112. p0V,p1V,pAb = trainNB1(trainMat, listClasses)
  113. # print(f'我是概率{p0V,p1V}')
  114. testEntry = ['love','my','dalmation']
  115. thisDOc =setofword(myVocabList,testEntry)
  116. p1 = classfyNB(thisDOc,p0V,p1V,pAb)
  117. print(f'当前词条{testEntry}的结果为:{p1}')
  118. testEntry = ['dog','stupid']
  119. thisDOc =setofword(myVocabList, testEntry)
  120. p2 = classfyNB(thisDOc, p0V, p1V, pAb)
  121. print(f'当前词条{testEntry}的结果为:{p2}')
  122. testingNB()

在代码测试完以后,可以调用sklearn中自带的byes的API验证一下自己写的代码准确性,MultinomialNB(alpha = 1.0),默认拉普拉斯公式为1;

注:上述代码是把所有特征放到一个矩阵中进行运算的,利用numpy的array格式进行计算,速度远远快于循环遍历(它不经过python的解释器,numpy的底层是c代码)




0

1

2

3

4

5

6

7

8

9



所属网站分类: 技术文章 > 博客

作者:dfd323

链接:https://www.pythonheidong.com/blog/article/952705/1e9ed7fd71dc63750947/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

28 0
收藏该文
已收藏

评论内容:(最多支持255个字符)