记录维维的每一篇Hello World

9.jpg

朴素贝叶斯公式

朴素贝叶斯判断西瓜好坏 - 图2

西瓜数据

复制保存为csv文件格式

  1. 色泽,根蒂,敲声,纹理,脐部,触感,好瓜
  2. 青绿,蜷缩,浊响,清晰,凹陷,硬滑,是
  3. 乌黑,蜷缩,沉闷,清晰,凹陷,硬滑,是
  4. 乌黑,蜷缩,浊响,清晰,凹陷,硬滑,是
  5. 青绿,蜷缩,沉闷,清晰,凹陷,硬滑,是
  6. 浅白,蜷缩,浊响,清晰,凹陷,硬滑,是
  7. 青绿,稍蜷,浊响,清晰,稍凹,软粘,是
  8. 乌黑,稍蜷,浊响,稍糊,稍凹,软粘,是
  9. 乌黑,稍蜷,浊响,清晰,稍凹,硬滑,是
  10. 乌黑,稍蜷,沉闷,稍糊,稍凹,硬滑,否
  11. 青绿,硬挺,清脆,清晰,平坦,软粘,否
  12. 浅白,硬挺,清脆,模糊,平坦,硬滑,否
  13. 浅白,蜷缩,浊响,模糊,平坦,软粘,否
  14. 青绿,稍蜷,浊响,稍糊,凹陷,硬滑,否
  15. 浅白,稍蜷,沉闷,稍糊,凹陷,硬滑,否
  16. 乌黑,稍蜷,浊响,清晰,稍凹,软粘,否
  17. 浅白,蜷缩,浊响,模糊,平坦,硬滑,否
  18. 青绿,蜷缩,沉闷,稍糊,稍凹,硬滑,否

实现理论

假设事件西瓜是好瓜为Y,是坏瓜为N,
属性色泽,根蒂,敲声,纹理,脐部,触感,分别为a,b,c,d,e,f,

在已知西瓜属性的情况下西瓜是好瓜的概率为:

朴素贝叶斯判断西瓜好坏 - 图3
又有:
朴素贝叶斯判断西瓜好坏 - 图4

在已知西瓜属性的情况下西瓜不是好瓜的概率为:

朴素贝叶斯判断西瓜好坏 - 图5
又有:
朴素贝叶斯判断西瓜好坏 - 图6

两个相除,得到
朴素贝叶斯判断西瓜好坏 - 图7
当其大于1是,可以判断西瓜是好瓜
朴素贝叶斯判断西瓜好坏 - 图8

在计算过程中,有可能出现值为0或者值过于小的情况,所以进行log处理
朴素贝叶斯判断西瓜好坏 - 图9
=
朴素贝叶斯判断西瓜好坏 - 图10
=
朴素贝叶斯判断西瓜好坏 - 图11
=
朴素贝叶斯判断西瓜好坏 - 图12
=
朴素贝叶斯判断西瓜好坏 - 图13

为了防止0的情况出现,所以我们进行全部加1来进行比较
朴素贝叶斯判断西瓜好坏 - 图14

代码实现

需要安装的工具包

  1. import numpy
  2. import pandas

数据预处理

  1. import json
  2. import pandas as pd
  3. # 导入数据/生成数据表
  4. dataSheet = pd.read_csv("E:\\Data\\西瓜\\123.csv", encoding="utf-8")
  5. # print(dataSheet)
  6. # 预数据
  7. data_proba = {}
  8. # 标签/列名称
  9. header = dataSheet.columns
  10. # 案例个数/行数
  11. length = dataSheet.shape[0]
  12. # 数据表值
  13. values = dataSheet.values
  14. # 最后一列的不重复数据
  15. end_unique = dataSheet[header[-1]].unique()
  16. # 遍历
  17. for end in end_unique:
  18. # [header[-1]==end]时end出现的次数
  19. end_sum = dataSheet[dataSheet[header[-1]].isin([end])].shape[0]
  20. # [header[-1]==end]时end出现的频率
  21. end_proba = dataSheet[dataSheet[header[-1]].isin([end])].shape[0] / length
  22. # 预保存
  23. data_proba[end] = {'proba': end_proba, 'data': {}}
  24. # 遍历标签/列名称
  25. for head in header[:-1]:
  26. # 初始化
  27. data_proba[end]['data'][head] = {}
  28. # 该标签/名称下不重复值
  29. head_unique = dataSheet[head].unique()
  30. # 遍历属性
  31. for head_val in head_unique:
  32. # [header[-1]==end]时head_val出现的次数
  33. head_val_sum = dataSheet[dataSheet[head].isin([head_val]) & dataSheet[header[-1]].isin([end])].shape[0]
  34. # [header[-1]==end]时head_val出现的频率
  35. head_val_proba = head_val_sum / end_sum
  36. # 预保存
  37. data_proba[end]['data'][head][head_val] = head_val_proba
  38. # 打印结果
  39. print(json.dumps(data_proba, indent=4, ensure_ascii=False))

数据预测

  1. import numpy as np
  2. # 创建一个存放判断结果的数组
  3. new = np.empty((length, 1), str)
  4. # 遍历values的每一行
  5. for val_num in np.arange(length):
  6. judge = {}
  7. # 遍历最后一列不重复数据
  8. for end in end_unique:
  9. # 标签/列名称除最后一列的数量
  10. header_sum = len(header[:-1])
  11. # 创建一个临时存放数据的数组
  12. tempor = np.empty(header_sum + 1, float)
  13. # 最后一个标签/列名称的属性对应的先验概率
  14. end_proba = data_proba[end]['proba']
  15. # 加1处理
  16. end_proba += 1
  17. # 临时保存
  18. tempor[-1] = end_proba
  19. # 遍历除最后一行的标签/列名称
  20. for head_num in np.arange(header_sum):
  21. # 标签/列名称
  22. head = header[head_num]
  23. # 该标签/列名称下的属性
  24. val = values[val_num][head_num]
  25. # 属性对应的先验概率
  26. head_val_proba = data_proba[end]['data'][head][val]
  27. # 加1处理
  28. head_val_proba += 1
  29. # 临时保存
  30. tempor[head_num] = head_val_proba
  31. # 对数据log处理并求和保存
  32. temp = np.log(tempor).sum()
  33. judge[temp] = end
  34. # 提取后验概率较大的值
  35. judge_max = np.max(list(judge.keys()))
  36. # 保存预测结果
  37. new[val_num] = judge[judge_max]
  38. # 将预测结果添加到数据表新列
  39. dataSheet['new'] = new
  40. # 预测正确的数量
  41. rate = dataSheet[dataSheet[header[-1]] == dataSheet['new']].shape[0]
  42. # 打印数据表
  43. print(dataSheet)
  44. # 准确率
  45. print('准确率: {rate:.7f}%'.format(rate=100 * rate / length))

完整代码

  1. import json
  2. import numpy as np
  3. import pandas as pd
  4. # 导入数据/生成数据表
  5. dataSheet = pd.read_csv("E:\\Data\\西瓜\\123.csv", encoding="utf-8")
  6. # print(dataSheet)
  7. # 预数据
  8. data_proba = {}
  9. # 标签/列名称
  10. header = dataSheet.columns
  11. # 案例个数/行数
  12. length = dataSheet.shape[0]
  13. # 数据表值
  14. values = dataSheet.values
  15. # 最后一列的不重复数据
  16. end_unique = dataSheet[header[-1]].unique()
  17. # 遍历
  18. for end in end_unique:
  19. # [header[-1]==end]时end出现的次数
  20. end_sum = dataSheet[dataSheet[header[-1]].isin([end])].shape[0]
  21. # [header[-1]==end]时end出现的频率
  22. end_proba = dataSheet[dataSheet[header[-1]].isin([end])].shape[0] / length
  23. # 预保存
  24. data_proba[end] = {'proba': end_proba, 'data': {}}
  25. # 遍历标签/列名称
  26. for head in header[:-1]:
  27. # 初始化
  28. data_proba[end]['data'][head] = {}
  29. # 该标签/名称下不重复值
  30. head_unique = dataSheet[head].unique()
  31. # 遍历属性
  32. for head_val in head_unique:
  33. # [header[-1]==end]时head_val出现的次数
  34. head_val_sum = dataSheet[dataSheet[head].isin([head_val]) & dataSheet[header[-1]].isin([end])].shape[0]
  35. # [header[-1]==end]时head_val出现的频率
  36. head_val_proba = head_val_sum / end_sum
  37. # 预保存
  38. data_proba[end]['data'][head][head_val] = head_val_proba
  39. # 打印结果
  40. # print(json.dumps(data_proba, indent=4, ensure_ascii=False))
  41. # 创建一个存放判断结果的数组
  42. new = np.empty((length, 1), str)
  43. # 遍历values的每一行
  44. for val_num in np.arange(length):
  45. judge = {}
  46. # 遍历最后一列不重复数据
  47. for end in end_unique:
  48. # 标签/列名称除最后一列的数量
  49. header_sum = len(header[:-1])
  50. # 创建一个临时存放数据的数组
  51. tempor = np.empty(header_sum + 1, float)
  52. # 最后一个标签/列名称的属性对应的先验概率
  53. end_proba = data_proba[end]['proba']
  54. # 加1处理
  55. end_proba += 1
  56. # 临时保存
  57. tempor[-1] = end_proba
  58. # 遍历除最后一行的标签/列名称
  59. for head_num in np.arange(header_sum):
  60. # 标签/列名称
  61. head = header[head_num]
  62. # 该标签/列名称下的属性
  63. val = values[val_num][head_num]
  64. # 属性对应的先验概率
  65. head_val_proba = data_proba[end]['data'][head][val]
  66. # 加1处理
  67. head_val_proba += 1
  68. # 临时保存
  69. tempor[head_num] = head_val_proba
  70. # 对数据log处理并求和保存
  71. temp = np.log(tempor).sum()
  72. judge[temp] = end
  73. # 提取后验概率较大的值
  74. judge_max = np.max(list(judge.keys()))
  75. # 保存预测结果
  76. new[val_num] = judge[judge_max]
  77. # 将预测结果添加到数据表新列
  78. dataSheet['new'] = new
  79. # 预测正确的数量
  80. rate = dataSheet[dataSheet[header[-1]] == dataSheet['new']].shape[0]
  81. # 打印数据表
  82. print(dataSheet)
  83. # 准确率
  84. print('准确率: {rate:.7f}%'.format(rate=100 * rate / length))

未修改代码

  1. import json
  2. import numpy as np
  3. import pandas as pd
  4. dataTrain = pd.read_csv("E:\\Data\\西瓜\\123.csv", encoding="utf-8")
  5. # print(dataTrain)
  6. data = {}
  7. header = dataTrain.columns
  8. length = dataTrain.shape[0]
  9. values = dataTrain.values
  10. for i in dataTrain[header[-1]].unique():
  11. data[i] = {'proba': dataTrain[dataTrain[header[-1]].isin([i])].shape[0] / length, 'data': {}}
  12. for j in header[:-1]:
  13. data[i]['data'][j] = {}
  14. for n in dataTrain[j].unique():
  15. data[i]['data'][j][n] = \
  16. dataTrain[dataTrain[j].isin([n]) & dataTrain[header[-1]].isin([i])].shape[0] / \
  17. dataTrain[dataTrain[header[-1]].isin([i])].shape[0]
  18. # print(json.dumps(data, indent=4, ensure_ascii=False))
  19. r = np.empty((length, 1), str)
  20. for v in np.arange(values.shape[0]):
  21. a_l = {}
  22. for i in dataTrain[header[-1]].unique():
  23. a = np.log([data[i]['data'][header[j]][values[v][j]] + 1
  24. for j in np.arange(len(header[:-1]))]).sum()
  25. a_l[a + np.log(data[i]['proba']+1)] = i
  26. r[v] = a_l[np.max(list(a_l.keys()))]
  27. dataTrain['new'] = r
  28. rate = dataTrain[dataTrain[header[-1]] == dataTrain['new']].shape[0]
  29. print('准确率: {rate:.7f}%'.format(rate=100 * rate / length))

注意事项

1、根据数据预测正确率为88.24%

2、没有弄数据错误的处理,需要自行优化

python环境

电脑:Windows10

python:3.10.4