当前位置:   article > 正文

Python实现机器学习算法:朴素贝叶斯算法

python读取训练集和测试集进行朴素贝叶斯预测并输出准确率代码
  1. '''
  2. 数据集:Mnist
  3. 训练集数量:60000
  4. 测试集数量:10000
  5. '''
  6. import numpy as np
  7. import time
  8. def loadData(fileName):
  9. '''
  10. 加载文件
  11. :param fileName:要加载的文件路径
  12. :return: 数据集和标签集
  13. '''
  14. # 存放数据及标记
  15. dataArr = [];
  16. labelArr = []
  17. # 读取文件
  18. fr = open(fileName)
  19. # 遍历文件中的每一行
  20. for line in fr.readlines():
  21. # 获取当前行,并按“,”切割成字段放入列表中
  22. # strip:去掉每行字符串首尾指定的字符(默认空格或换行符)
  23. # split:按照指定的字符将字符串切割成每个字段,返回列表形式
  24. curLine = line.strip().split(',')
  25. # 将每行中除标记外的数据放入数据集中(curLine[0]为标记信息)
  26. # 在放入的同时将原先字符串形式的数据转换为整型
  27. # 此外将数据进行了二值化处理,大于128的转换成1,小于的转换成0,方便后续计算
  28. dataArr.append([int(int(num) > 128) for num in curLine[1:]])
  29. # 将标记信息放入标记集中
  30. # 放入的同时将标记转换为整型
  31. labelArr.append(int(curLine[0]))
  32. # 返回数据集和标记
  33. return dataArr, labelArr
  34. def NaiveBayes(Py, Px_y, x):
  35. '''
  36. 通过朴素贝叶斯进行概率估计
  37. :param Py: 先验概率分布
  38. :param Px_y: 条件概率分布
  39. :param x: 要估计的样本x
  40. :return: 返回所有label的估计概率
  41. '''
  42. # 设置特征数目
  43. featrueNum = 784
  44. # 设置类别数目
  45. classNum = 10
  46. # 建立存放所有标记的估计概率数组
  47. P = [0] * classNum
  48. # 对于每一个类别,单独估计其概率
  49. for i in range(classNum):
  50. # 初始化sum0sum为求和项。
  51. # 在训练过程中对概率进行了log处理,所以这里原先应当是连乘所有概率,最后比较哪个概率最大
  52. # 但是当使用log处理时,连乘变成了累加,所以使用sum
  53. sum = 0
  54. # 获取每一个条件概率值,进行累加
  55. for j in range(featrueNum):
  56. sum += Px_y[i][j][x[j]]
  57. # 最后再和先验概率相加(也就是式4.7中的先验概率乘以后头那些东西,乘法因为log全变成了加法)
  58. P[i] = sum + Py[i]
  59. # max(P):找到概率最大值
  60. # P.index(max(P)):找到该概率最大值对应的所有(索引值和标签值相等)
  61. return P.index(max(P))
  62. def accuracy(Py, Px_y, testDataArr, testLabelArr):
  63. '''
  64. 对测试集进行测试
  65. :param Py: 先验概率分布
  66. :param Px_y: 条件概率分布
  67. :param testDataArr: 测试集数据
  68. :param testLabelArr: 测试集标记
  69. :return: 准确率
  70. '''
  71. # 错误值计数
  72. errorCnt = 0
  73. # 循环遍历测试集中的每一个样本
  74. for i in range(len(testDataArr)):
  75. # 获取预测值
  76. presict = NaiveBayes(Py, Px_y, testDataArr[i])
  77. # 与答案进行比较
  78. if presict != testLabelArr[i]:
  79. # 若错误 错误值计数加1
  80. errorCnt += 1
  81. # 返回准确率
  82. return 1 - (errorCnt / len(testDataArr))
  83. def getAllProbability(trainDataArr, trainLabelArr):
  84. '''
  85. 通过训练集计算先验概率分布和条件概率分布
  86. :param trainDataArr: 训练数据集
  87. :param trainLabelArr: 训练标记集
  88. :return: 先验概率分布和条件概率分布
  89. '''
  90. # 设置样本特诊数目,数据集中手写图片为28*28,转换为向量是784维。
  91. # (我们的数据集已经从图像转换成784维的形式了,CSV格式内就是)
  92. featureNum = 784
  93. # 设置类别数目,0-9共十个类别
  94. classNum = 10
  95. # 初始化先验概率分布存放数组,后续计算得到的P(Y = 0)放在Py[0]中,以此类推
  96. # 数据长度为101
  97. # 各个类别的先验概率分布
  98. Py = np.zeros((classNum, 1))
  99. # 对每个类别进行一次循环,分别计算它们的先验概率分布
  100. # 计算公式为书中"4.2节 朴素贝叶斯法的参数估计 公式4.8"
  101. for i in range(classNum):
  102. # 下方式子拆开分析
  103. # np.mat(trainLabelArr) == i:将标签转换为矩阵形式,里面的每一位与i比较,若相等,该位变为Ture,反之False
  104. # np.sum(np.mat(trainLabelArr) == i):计算上一步得到的矩阵中Ture的个数,进行求和(直观上就是找所有label中有多少个
  105. # 为i的标记,求得4.8式P(Y = Ck)中的分子)
  106. # np.sum(np.mat(trainLabelArr) == i)) + 1:参考“4.2.3节 贝叶斯估计”,例如若数据集总不存在y=1的标记,也就是说
  107. # 手写数据集中没有1这张图,那么如果不加1,由于没有y=1,所以分子就会变成0,那么在最后求后验概率时这一项就变成了0,再
  108. # 和条件概率乘,结果同样为0,不允许存在这种情况,所以分子加1,分母加上K(K为标签可取的值数量,这里有10个数,取值为10
  109. # 参考公式4.11
  110. # (len(trainLabelArr) + 10):标签集的总长度+10.
  111. # ((np.sum(np.mat(trainLabelArr) == i)) + 1) / (len(trainLabelArr) + 10):最后求得的先验概率
  112. Py[i] = ((np.sum(np.mat(trainLabelArr) == i)) + 1) / (len(trainLabelArr) + 10)
  113. # 转换为log对数形式
  114. # log书中没有写到,但是实际中需要考虑到,原因是这样:
  115. # 最后求后验概率估计的时候,形式是各项的相乘(“4.1 朴素贝叶斯法的学习” 式4.7),这里存在两个问题:1.某一项为0时,结果为0.
  116. # 这个问题通过分子和分母加上一个相应的数可以排除,前面已经做好了处理。2.如果特征特别多(例如在这里,需要连乘的项目有784个特征
  117. # 加一个先验概率分布一共795项相乘,所有数都是0-1之间,结果一定是一个很小的接近0的数。)理论上可以通过结果的大小值判断, 但在
  118. # 程序运行中很可能会向下溢出无法比较,因为值太小了。所以人为把值进行log处理。log在定义域内是一个递增函数,也就是说log(x)中,
  119. # x越大,log也就越大,单调性和原数据保持一致。所以加上log对结果没有影响。此外连乘项通过log以后,可以变成各项累加,简化了计算。
  120. # 在似然函数中通常会使用log的方式进行处理(至于此书中为什么没涉及,我也不知道)
  121. Py = np.log(Py)
  122. # 计算条件概率 Px_y=P(X=x|Y = y)
  123. # 计算条件概率分成了两个步骤,下方第一个大for循环用于累加,参考书中“4.2.3 贝叶斯估计 式4.10”,下方第一个大for循环内部是
  124. # 用于计算式4.10的分子,至于分子的+1以及分母的计算在下方第二个大For
  125. # 初始化为全0矩阵,用于存放所有情况下的条件概率
  126. Px_y = np.zeros((classNum, featureNum, 2))
  127. # 对标记集进行遍历
  128. for i in range(len(trainLabelArr)):
  129. # 获取当前循环所使用的标记
  130. label = trainLabelArr[i]
  131. # 获取当前要处理的样本
  132. x = trainDataArr[i]
  133. # 对该样本的每一维特诊进行遍历
  134. for j in range(featureNum):
  135. # 在矩阵中对应位置加1
  136. # 这里还没有计算条件概率,先把所有数累加,全加完以后,在后续步骤中再求对应的条件概率
  137. Px_y[label][j][x[j]] += 1
  138. # 第二个大for,计算式4.10的分母,以及分子和分母之间的除法
  139. # 循环每一个标记(共10个)
  140. for label in range(classNum):
  141. # 循环每一个标记对应的每一个特征
  142. for j in range(featureNum):
  143. # 获取y=label,第j个特诊为0的个数
  144. Px_y0 = Px_y[label][j][0]
  145. # 获取y=label,第j个特诊为1的个数
  146. Px_y1 = Px_y[label][j][1]
  147. # 对式4.10的分子和分母进行相除,再除之前依据贝叶斯估计,分母需要加上2(为每个特征可取值个数)
  148. # 分别计算对于y= label,x第j个特征为01的条件概率分布
  149. Px_y[label][j][0] = np.log((Px_y0 + 1) / (Px_y0 + Px_y1 + 2))
  150. Px_y[label][j][1] = np.log((Px_y1 + 1) / (Px_y0 + Px_y1 + 2))
  151. # 返回先验概率分布和条件概率分布
  152. return Py, Px_y
  153. if __name__ == "__main__":
  154. start = time.time()
  155. # 获取训练集
  156. print('start read transSet')
  157. trainDataArr, trainLabelArr = loadData('../Mnist/mnist_train.csv')
  158. # 获取测试集
  159. print('start read testSet')
  160. testDataArr, testLabelArr = loadData('../Mnist/mnist_test.csv')
  161. # 开始训练,学习先验概率分布和条件概率分布
  162. print('start to train')
  163. Py, Px_y = getAllProbability(trainDataArr, trainLabelArr)
  164. # 使用习得的先验概率分布和条件概率分布对测试集进行测试
  165. print('start to test')
  166. accuracy = accuracy(Py, Px_y, testDataArr, testLabelArr)
  167. # 打印准确率
  168. print('the accuracy is:', accuracy)
  169. # 打印时间
  170. print('time span:', time.time() - start)
  1. start read transSet
  2. start read testSet
  3. start to train
  4. start to test
  5. the accuracy is: 0.8432999999999999
  6. time span: 90.73810172080994

转载于:https://www.cnblogs.com/chenxiangzhen/p/10516583.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/916010
推荐阅读
相关标签
  

闽ICP备14008679号