首页 > Python基础教程 >
-
Python 从零构建贝叶斯分类器的机器学习实践
一、前言
在机器学习领域,贝叶斯分类器是一种基于概率论的分类算法,具有简单高效的特点,广泛应用于文本分类、垃圾邮件过滤、图像识别等领域。本文将详细介绍贝叶斯分类器的原理,并通过 Python 代码从零实现一个贝叶斯分类器,帮助读者深入理解其工作机制。
二、贝叶斯分类器的原理
(1)贝叶斯定理
贝叶斯分类器的核心是贝叶斯定理,它描述了在已知某些条件下,事件发生的概率。贝叶斯定理的数学表达式为:
P(A∣B)=
P(B)
P(B∣A)⋅P(A)
其中:
P(A∣B) 表示在事件 B 发生的条件下,事件 A 发生的概率(后验概率)。
P(B∣A) 表示在事件 A 发生的条件下,事件 B 发生的概率(似然概率)。
P(A) 表示事件 A 发生的先验概率。
P(B) 表示事件 B 发生的概率。
(2)朴素贝叶斯分类器
朴素贝叶斯分类器是贝叶斯分类器的一种常见形式,它假设特征之间相互独立。基于这一假设,朴素贝叶斯分类器通过计算每个类别的后验概率,选择后验概率最大的类别作为预测结果。
对于一个样本 x=(x
1
,x
2
,…,x
n
),其属于类别 c 的后验概率为:
P(c∣x)=
P(x)
P(x∣c)⋅P(c)
由于 P(x) 对所有类别相同,因此在比较不同类别的后验概率时,可以忽略 P(x),只需比较 P(x∣c)⋅P(c)。
在朴素贝叶斯分类器中,假设特征之间相互独立,则:
P(x∣c)=
i=1
∏
n
P(x
i
∣c)
因此,样本 x 属于类别 c 的后验概率可以表示为:
P(c∣x)∝P(c)⋅
i=1
∏
n
P(x
i
∣c)
(3)概率估计
为了计算 P(c) 和 P(x
i
∣c),通常使用最大似然估计。具体来说:
P(c) 是类别 c 在训练数据中的频率。
P(x
i
∣c) 是特征 x
i
在类别 c 中的频率。
为了避免概率为零的情况,通常使用拉普拉斯平滑(Laplace Smoothing):
P(x
i
∣c)=
N
c
+V
N
c,x
i
+1
其中:
N
c,x
i
是类别 c 中特征 x
i
出现的次数。
N
c
是类别 c 中样本的总数。
V 是特征 x
i
的取值个数。
三、用 Python 从零实现贝叶斯分类器
(1)数据准备
首先,我们需要准备一个简单的数据集。以下是一个包含两个特征和两个类别的示例数据集:
Python
复制
数据集
data = [
('晴', '热', '否'),
('晴', '凉爽', '是'),
('阴', '热', '是'),
('雨', '凉爽', '是'),
('雨', '凉爽', '否'),
('阴', '凉爽', '否'),
('晴', '热', '是'),
('阴', '凉爽', '是'),
('晴', '凉爽', '是'),
('雨', '热', '否')
]
特征和标签
features = [item[:2] for item in data]
labels = [item[2] for item in data]
(2)构建词汇表
我们需要构建特征的词汇表,以便后续计算概率:
Python
复制
构建词汇表
from collections import defaultdict
def build_vocabulary(features):
vocab = defaultdict(set)
for sample in features:
for i, feature in enumerate(sample):
vocab[i].add(feature)
return vocab
vocab = build_vocabulary(features)
print("词汇表:", vocab)
(3)计算先验概率和条件概率
接下来,我们计算每个类别的先验概率和特征的条件概率:
Python
复制
计算先验概率和条件概率
from collections import defaultdict
def calculate_probabilities(features, labels, vocab):
# 类别统计
class_counts = defaultdict(int)
for label in labels:
class_counts[label] += 1
# 先验概率
prior_prob = {label: count / len(labels) for label, count in class_counts.items()}
# 条件概率
conditional_prob = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
for feature, label in zip(features, labels):
for i, value in enumerate(feature):
conditional_prob[label][i][value] += 1
# 应用拉普拉斯平滑
for label in conditional_prob:
for i in vocab:
for value in vocab[i]:
conditional_prob[label][i][value] = (conditional_prob[label][i][value] + 1) / (class_counts[label] + len(vocab[i]))
return prior_prob, conditional_prob
prior_prob, conditional_prob = calculate_probabilities(features, labels, vocab)
print("先验概率:", prior_prob)
print("条件概率:", conditional_prob)
(4)模型预测
最后,我们实现预测函数,根据先验概率和条件概率计算后验概率,并选择后验概率最大的类别作为预测结果:
Python
复制
模型预测
def predict(feature, prior_prob, conditional_prob, vocab):
max_prob = -1
predicted_class = None
for label in prior_prob:
prob = prior_prob[label]
for i, value in enumerate(feature):
prob *= conditional_prob[label][i].get(value, 1 / (class_counts[label] + len(vocab[i])))
if prob > max_prob:
max_prob = prob
predicted_class = label
return predicted_class
测试
test_sample = ('阴', '热')
print(f"测试样本 {test_sample} 的预测结果:", predict(test_sample, prior_prob, conditional_prob, vocab))
(5)完整代码
以下是完整的代码实现:
Python
复制
数据集
data = [
('晴', '热', '否'),
('晴', '凉爽', '是'),
('阴', '热', '是'),
('雨', '凉爽', '是'),
('雨', '凉爽', '否'),
('阴', '凉爽', '否'),
('晴', '热', '是'),
('阴', '凉爽', '是'),
('晴', '凉爽', '是'),
('雨', '热', '否')
]
特征和标签
features = [item[:2] for item in data]
labels = [item[2] for item in data]
构建词汇表
from collections import defaultdict
def build_vocabulary(features):
vocab = defaultdict(set)
for sample in features:
for i, feature in enumerate(sample):
vocab[i].add(feature)
return vocab
vocab = build_vocabulary(features)
计算先验概率和条件概率
def calculate_probabilities(features, labels, vocab):
# 类别统计
class_counts = defaultdict(int)
for label in labels:
class_counts[label] += 1
# 先验概率
prior_prob = {label: count / len(labels) for label, count in class_counts.items()}
# 条件概率
conditional_prob = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
for feature, label in zip(features, labels):
for i, value in enumerate(feature):
conditional_prob[label][i][value] += 1
# 应用拉普拉斯平滑
for label in conditional_prob:
for i in vocab:
for value in vocab[i]:
conditional_prob[label][i][value] = (conditional_prob[label][i][value] + 1) / (class_counts[label] + len(vocab[i]))
return prior_prob, conditional_prob
prior_prob, conditional_prob = calculate_probabilities(features, labels, vocab)
模型预测
def predict(feature, prior_prob, conditional_prob, vocab):
max_prob = -1
predicted_class = None
for label in prior_prob:
prob = prior_prob[label]
for i, value in enumerate(feature):
prob *= conditional_prob[label][i].get(value, 1 / (class_counts[label] + len(vocab[i])))
if prob > max_prob:
max_prob = prob
predicted_class = label
return predicted_class
测试
test_sample = ('阴', '热')
print(f"测试样本 {test_sample} 的预测结果:", predict(test_sample, prior_prob, conditional_prob, vocab))
四、总结
通过本文的介绍,我们从零实现了贝叶斯分类器的机器学习过程。贝叶斯分类器基于概率论,通过计算后验概率来进行分类预测。它具有简单高效的特点,尤其适用于小规模数据集和高维数据。在实际应用中,贝叶斯分类器被广泛应用于文本分类、垃圾邮件过滤等领域。通过本文的实现,读者可以更好地理解贝叶斯分类器的原理和实现过程,为进一步的机器学习研究和应用打下坚实的基础。
最后,如果你对python语言还有任何疑问或者需要进一步的帮助,请访问https://www.xin3721.com 本站原创,转载请注明出处:https://www.xin3721.com