机器学习——贝叶斯分类
一、贝叶斯分类基础
贝叶斯分类是一类基于贝叶斯定理的监督学习算法,在统计学分类方法中占有重要地位。贝叶斯方法的核心是通过概率统计方法进行分类决策。
1. 贝叶斯定理
贝叶斯定理描述了在已知某些条件下某事件发生的概率。公式表示为:
其中:
P(A|B) 是后验概率:在B发生条件下A发生的概率
P(B|A) 是似然概率:在A发生条件下B发生的概率
P(A) 是先验概率:A发生的概率
P(B) 是边际概率:B发生的概率
2. 朴素贝叶斯分类器
朴素贝叶斯分类器基于一个"朴素"的假设:所有特征之间相互独立。尽管这个假设在现实中很少成立,但朴素贝叶斯在实践中表现往往出人意料地好。
原理:
特征条件假设:假设每个特征之间没有联系,给定训练数据集,其中每个样本都包括维特征,即,类标记集合含有种类别,即。
对于给定的新样本,判断其属于哪个标记的类别,根据贝叶斯定理,可以得到属于类别的概率:
后验概率最大的类别记为预测类别,即。
朴素贝叶斯算法对条件概率分布作出了独立性的假设,通俗地讲就是说假设各个维度的特征x1,x2,⋯,xn互相独立,在这个假设的前提上,条件概率可以转化为:
代入贝叶斯公式中,得到:
于是,朴素贝叶斯分类器可表示为:
因为对所有的,上式中的分母的值都是一样的,所以可以忽略分母部分,朴素贝叶斯分类器最终表示为:
算法简单,易于实现
对小规模数据表现良好
对缺失数据不太敏感
在多分类问题中表现良好
主要缺点:
特征独立性假设可能导致精度下降
对输入数据的表达形式敏感
二、朴素贝叶斯分类器的实现步骤
题目:
“西瓜数据集”是机器学习入门中一个非常经典的分类数据集,常用于讲解和实现基本的分类算法。该数据集通过若干个特征来描述西瓜的外观和内部质量,并据此判断是否为“好瓜”。
1. 数据准备
在代码中,我们首先通过load_data函数加载数据,将数据分为特征和标签两部分。对于西瓜数据集,前6个特征是离散值(色泽、根蒂等),后2个是连续值(密度、含糖率)。
2. 计算先验概率
先验概率P(Y)表示在没有其他信息的情况下,某个类别出现的概率。在代码中通过calc_prior函数实现:
def calc_prior(labels):
total = len(labels)
priors = defaultdict(float)
for label in labels:
priors[label] += 1
for k in priors:
priors[k] /= total
print("先验概率:", dict(priors))
return priors
3. 计算条件概率
对于离散特征,计算P(Xi|Y),即给定类别下某个特征取特定值的概率。在代码中通过calc_discrete_probs实现:
def calc_discrete_probs(separated, idx):
probs = {}
for label, items in separated.items():
freq = defaultdict(int)
for item in items:
freq[item[idx]] += 1
total = len(items)
probs[label] = {k: (v / total) for k, v in freq.items()}
return probs
对于连续特征,通常假设其服从高斯分布,计算均值和方差。在代码中通过calc_continuous_probs实现:
def calc_continuous_probs(separated, idx):
stats = {}
for label, items in separated.items():
values = [item[idx] for item in items]
mean = sum(values) / len(values)
var = sum((x - mean) ** 2 for x in values) / len(values)
stats[label] = (mean, var)
return stats
4. 高斯概率密度函数
对于连续变量,使用高斯概率密度函数计算概率:
def gaussian_prob(x, mean, var):
if var == 0: var = 1e-6 # 防止除零
exponent = math.exp(-((x - mean) ** 2) / (2 * var))
return (1 / math.sqrt(2 * math.pi * var)) * exponent
5. 分类预测
使用贝叶斯定理计算后验概率,并取最大概率对应的类别作为预测结果:
results = {}
for label in priors:
prob = math.log(priors[label]) # 使用对数防止下溢
# 乘以各个属性的条件概率
for idx in discrete_idxs:
val = test_sample[idx]
prob_dict = discrete_probs[idx].get(label, {})
p = prob_dict.get(val, 1e-6) # 使用小概率值防止零概率
prob += math.log(p)
for idx in continuous_idxs:
val = test_sample[idx]
mean, var = continuous_probs[idx][label]
p = gaussian_prob(val, mean, var)
prob += math.log(p)
results[label] = prob
6.完整代码
import math
from collections import defaultdict
def load_data(file_path):
train_data = []
labels = []
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
parts = line.strip().split()
features = parts[:6] + [float(x) for x in parts[6:8]]
label = parts[8]
train_data.append(features)
labels.append(label)
return train_data, labels
def calc_prior(labels):
total = len(labels)
priors = defaultdict(float)
for label in labels:
priors[label] += 1
for k in priors:
priors[k] /= total
print("先验概率:", dict(priors))
return priors
def separate_by_class(data, labels):
separated = defaultdict(list)
for i in range(len(data)):
separated[labels[i]].append(data[i])
return separated
def calc_discrete_probs(separated, idx):
probs = {}
for label, items in separated.items():
freq = defaultdict(int)
for item in items:
freq[item[idx]] += 1
total = len(items)
probs[label] = {k: (v / total) for k, v in freq.items()}
return probs
def calc_continuous_probs(separated, idx):
stats = {}
for label, items in separated.items():
values = [item[idx] for item in items]
mean = sum(values) / len(values)
var = sum((x - mean) ** 2 for x in values) / len(values)
stats[label] = (mean, var)
return stats
def gaussian_prob(x, mean, var):
if var == 0: var = 1e-6
exponent = math.exp(-((x - mean) ** 2) / (2 * var))
return (1 / math.sqrt(2 * math.pi * var)) * exponent
def classify_naive_bayes(train_data, labels, test_sample):
priors = calc_prior(labels)
separated = separate_by_class(train_data, labels)
discrete_idxs = list(range(6))
continuous_idxs = [6, 7]
discrete_probs = {}
for idx in discrete_idxs:
discrete_probs[idx] = calc_discrete_probs(separated, idx)
continuous_probs = {}
for idx in continuous_idxs:
continuous_probs[idx] = calc_continuous_probs(separated, idx)
results = {}
for label in priors:
prob = math.log(priors[label])
for idx in discrete_idxs:
val = test_sample[idx]
prob_dict = discrete_probs[idx].get(label, {})
p = prob_dict.get(val, 1e-6)
prob += math.log(p)
for idx in continuous_idxs:
val = test_sample[idx]
mean, var = continuous_probs[idx][label]
p = gaussian_prob(val, mean, var)
prob += math.log(p)
results[label] = prob
print("对数后验概率:", results)
pred_label = max(results, key=results.get)
print(f"\n预测结果: '{pred_label}' 的概率最大,该瓜为{'好瓜' if pred_label == '是' else '坏瓜'}")
if __name__ == "__main__":
file_path = "E:/pythonProject/train.txt"
train_data, labels = load_data(file_path)
test_sample = ['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460]
classify_naive_bayes(train_data, labels, test_sample)
AI写代码
7.结果:
更多推荐


所有评论(0)