贝叶斯分类
贝叶斯分类基于贝叶斯定理,它的核心思想是通过已有数据来估计不同类别出现的概率。简单来说,就是在已知某些特征的情况下,判断一个样本属于某个类别的可能性有多大。贝叶斯定理的公式为: 。
在这个公式里
是后验概率,也就是我们要求的在观测到特征 X 时,样本属于类别 C 的概率;
是似然概率,表示在类别 C 的条件下,出现特征 X 的概率;
是先验概率,即类别 C 本身出现的概率;
是证据因子,是一个归一化常数,确保后验概率的总和为 1。
在实际应用中,计算 可能会比较复杂,不过在一些情况下可以通过一些技巧简化计算。
朴素贝叶斯
概念
朴素贝叶斯是一种简单但强大的概率分类器。它 “朴素” 地假设特征之间相互独立,即一个特征的出现不影响其他特征的出现,基于这个假设和贝叶斯定理来计算样本属于各个类别的概率,将样本分类到概率最大的类别中。
数学原理
其核心是贝叶斯定理,公式为。
假设所有特征 相互独立,那么
结合贝叶斯定理,分类时选择后验概率最大的类别作为预测结果,即
算法特点
- 优点
- 简单高效:算法逻辑简单,易于实现,计算速度快,在处理大规模数据集时效率较高。
- 需要数据量少:在数据量较少的情况下也能有不错的表现,能有效避免过拟合问题。
- 对缺失数据不敏感:即使数据中存在部分缺失值,也能进行分类。
- 缺点
- 特征独立性假设限制:在现实中,特征之间往往存在一定的关联,该假设可能导致信息丢失,影响分类的准确性。
- 先验概率假设影响:先验概率的估计可能会受到数据分布的影响,如果先验概率估计不准确,可能会对分类结果产生不良影响。
贝叶斯实现
给定的西瓜数据集
代码
import numpy as np
# 西瓜数据集,每一行代表一个西瓜的各项特征以及是否为好瓜的标签
data = [
[1, '青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460, '是'],
[2, '乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.774, 0.376, '是'],
[3, '乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.634, 0.264, '是'],
[4, '青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.608, 0.318, '是'],
[5, '浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.556, 0.215, '是'],
[6, '青绿', '稍蜷', '浊响', '清晰', '凹陷', '软粘', 0.403, 0.237, '是'],
[7, '乌黑', '稍蜷', '浊响', '清晰', '凹陷', '软粘', 0.481, 0.149, '是'],
[8, '乌黑', '稍蜷', '浊响', '清晰', '凹陷', '硬滑', 0.437, 0.211, '是'],
[9, '乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', 0.666, 0.091, '否'],
[10, '青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', 0.243, 0.267, '否'],
[11, '浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', 0.245, 0.057, '否'],
[12, '浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', 0.343, 0.099, '否'],
[13, '青绿', '稍蜷', '浊响', '模糊', '凹陷', '硬滑', 0.639, 0.161, '否'],
[14, '浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', 0.657, 0.198, '否'],
[15, '乌黑', '稍蜷', '浊响', '清晰', '凹陷', '软粘', 0.360, 0.370, '否'],
[16, '浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', 0.593, 0.042, '否'],
[17, '青绿', '蜷缩', '沉闷', '稍糊', '凹陷', '硬滑', 0.719, 0.103, '否']
]
# 提取特征和标签
# 将数据集中除了第一个(编号)和最后一个(是否好瓜标签)的列提取出来作为特征矩阵X
X = np.array([row[1:-1] for row in data])
# 将数据集中最后一列提取出来作为标签向量y
y = np.array([row[-1] for row in data])
# 计算先验概率
# 统计好瓜的数量
good_count = np.sum(y == '是')
# 统计坏瓜的数量
bad_count = np.sum(y == '否')
# 样本总数
total_count = len(y)
# 好瓜的先验概率
p_good = good_count / total_count
# 坏瓜的先验概率
p_bad = bad_count / total_count
# 划分离散特征和连续特征的索引
discrete_features = [0, 1, 2, 3, 4, 5]
continuous_features = [6, 7]
# 用于存储每个特征值在不同类别下的条件概率以及连续特征的均值和方差
feature_probs = {}
# 遍历离散特征
for i in discrete_features:
# 获取当前离散特征的所有取值
feature_values = np.unique(X[:, i])
feature_probs[i] = {}
for value in feature_values:
# 筛选出好瓜中该特征取值为value的样本掩码
good_mask = (y == '是') & (X[:, i] == value)
# 筛选出坏瓜中该特征取值为value的样本掩码
bad_mask = (y == '否') & (X[:, i] == value)
# 利用拉普拉斯平滑计算该特征值在好瓜类别下的条件概率
p_value_given_good = (np.sum(good_mask) + 1) / (good_count + len(feature_values))
# 利用拉普拉斯平滑计算该特征值在坏瓜类别下的条件概率
p_value_given_bad = (np.sum(bad_mask) + 1) / (bad_count + len(feature_values))
feature_probs[i][value] = (p_value_given_good, p_value_given_bad)
# 遍历连续特征
for i in continuous_features:
# 获取好瓜中该连续特征的值,并转换为浮点数类型
good_values = X[y == '是', i].astype(float)
# 获取坏瓜中该连续特征的值,并转换为浮点数类型
bad_values = X[y == '否', i].astype(float)
# 计算好瓜中该连续特征的均值
good_mean = np.mean(good_values)
# 计算好瓜中该连续特征的方差
good_var = np.var(good_values)
# 计算坏瓜中该连续特征的均值
bad_mean = np.mean(bad_values)
# 计算坏瓜中该连续特征的方差
bad_var = np.var(bad_values)
feature_probs[i] = (good_mean, good_var, bad_mean, bad_var)
def gaussian_probability(x, mean, var):
"""计算高斯概率密度函数值,用于计算连续特征的条件概率"""
exponent = np.exp(-((x - mean) ** 2) / (2 * var))
return (1 / (np.sqrt(2 * np.pi * var))) * exponent
def predict(features):
"""预测西瓜是好瓜还是坏瓜"""
# 初始化好瓜的后验概率为好瓜的先验概率
p_good_given_features = p_good
# 初始化坏瓜的后验概率为坏瓜的先验概率
p_bad_given_features = p_bad
for i, value in enumerate(features):
if i in discrete_features:
# 获取当前离散特征值在好瓜和坏瓜类别下的条件概率
p_value_given_good, p_value_given_bad = feature_probs[i].get(value, (1e-10, 1e-10))
# 更新好瓜的后验概率
p_good_given_features *= p_value_given_good
# 更新坏瓜的后验概率
p_bad_given_features *= p_value_given_bad
elif i in continuous_features:
# 获取当前连续特征在好瓜和坏瓜类别下的均值和方差
good_mean, good_var, bad_mean, bad_var = feature_probs[i]
# 计算当前连续特征值在好瓜类别下的条件概率
p_value_given_good = gaussian_probability(float(value), good_mean, good_var)
# 计算当前连续特征值在坏瓜类别下的条件概率
p_value_given_bad = gaussian_probability(float(value), bad_mean, bad_var)
# 更新好瓜的后验概率
p_good_given_features *= p_value_given_good
# 更新坏瓜的后验概率
p_bad_given_features *= p_value_given_bad
if p_good_given_features > p_bad_given_features:
return '是'
else:
return '否'
while True:
print("请输入西瓜的特征(格式:色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率),输入 'q' 退出:")
input_str = input()
if input_str.lower() == 'q':
break
features = input_str.split()
if len(features) == 8:
result = predict(features)
print(f"预测结果:{'好瓜' if result == '是' else '坏瓜'}")
else:
print("输入格式错误,请重新输入。")
预测结果