- 实验目的
- 实验内容:
1、先把数据手动输入,data是特征值及标签
2、求先验概率P(c),根据公式可以求出,在这里使用布尔值索引lable==i可以减少代码量,更加简便快捷。使用np.unique(lable)可以直接去重得出所有取值。由于属性是-1和1,使用列表等下标必须是非负整数,所以这里使用字典存储,索引更加灵活。同时考虑到有的属性在训练集中未出现,导致求出的概率为0,使用拉普拉斯修正进行数据平滑,求法变为:
。
3、求出条件概率,即不同属性在不同类别中出现的概率。需要保存两个键,键可能是负数或字符,使用嵌套的字典。三层循环,最外层枚举类型,第二层枚举属性列,最内层枚举该属性的所有取值。同样使用拉普拉斯修正进行数据平滑,公式为
4、按照公式对x进行预测,哪个类型的概率最大结果就为哪个
实验结果:
- 实验原理:
- 心得体会:
遇到的问题及解决:
- 实验中可以使用很多numpy方法使代码更简洁,如枚举一列中的属性种类,可以使用np.unique方法结合切片实现;求某一类型的数量,可以使用布尔值索引加上shape求出。
- 遇到了键为负数和字符的情况,列表等数据结构无法存储和查找,可以使用字典进行存储。
心得体会:
通过这次实验,我学习到了朴素贝叶斯分类器,相较于以前的SVM等分类方法,又学习到了基于概率的分类,提供了另一种解决分类问题的思路。期间还了解到了拉普拉斯修正进行数据平滑,可以确保程序的健壮性。巩固所学知识,为以后的学习打下基础。
import numpy as np
data = np.array([[1, 'S', -1], [1, 'M', -1], [1, 'M', 1],
[1, 'S', 1], [1, 'S', -1], [2, 'S', -1],
[2, 'M', -1], [2, 'M', 1], [2, 'L', 1],
[2, 'L', 1], [3, 'L', 1], [3, 'M', 1],
[3, 'M', 1], [3, 'L', 1], [3, 'L', -1]])
lable = np.array([-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1])
prior_p = {} # 先验概率
for i in np.unique(lable):
prior_p[i] = (np.sum(lable == i) + 1) / (lable.size + np.unique(lable).size)
conditional_p = {} # 条件概率
for i in np.unique(lable):
conditional_p[i] = {}
data1 = data[lable == i]
for col in range(data.shape[1] - 1):
for j in np.unique(data[:, col]):
conditional_p[i][j] = ((data1[data1[:, col] == j]).shape[0] + 1) / (
data1.shape[0] + np.unique(data[:, 0]).size)
# print((data1[data1[:, col] == j]).shape[0] + 1, data1.shape[0] + np.unique(data[:, 0]).size)
# print(conditional_p[-1])
# print(np.unique(data[:, 0]).size)
if '__main__' == __name__:
x = ['2', 'S']
y = 0
max_p = 0
for i in np.unique(lable): # 假设所有分类结果
p = prior_p[i]
for j in x:
p *= conditional_p[i][j]
print(i, p)
if p > max_p:
y = i
max_p = p
print("result:", y)