Python函数实现朴素贝叶斯分类器
贝叶斯分类器是机器学习中重要的分类算法之一,它的优点是模型简单、计算快速、对数据噪声不敏感等。在本文中,我们将使用Python实现朴素贝叶斯分类器,它被称为“朴素”是因为它假设特征之间是相互独立的,虽然这个假设并不一定成立,但是朴素贝叶斯分类器在许多实际问题中表现良好。
朴素贝叶斯分类器假设每个特征x和每个分类y之间都是条件独立的,也就是说一个特征的取值不会影响其他特征的取值。基于这个假设,我们可以使用贝叶斯定理计算后验概率:
P(y|x1, x2, ..., xn) = P(y) * P(x1|y) * P(x2|y) * ... * P(xn|y) / P(x1, x2, ..., xn)
其中P(y|x1, x2, ..., xn)是我们要求的后验概率,表示在给定特征x1, x2, ..., xn的情况下分类y的概率;P(y)是先验概率,表示分类y出现的概率;P(xi|y)是条件概率,表示在分类y下特征xi的概率;P(x1, x2, ..., xn)是归一化因子,可以通过对所有可能的分类的先验概率和条件概率进行求和得到。具体来说,我们可以通过计算P(y)和P(xi|y)的频率来估计它们的概率,然后代入公式计算后验概率,最后选择概率最大的分类作为预测结果。
下面给出一个简单的Python函数实现朴素贝叶斯分类器,它可以处理二元离散特征且只有两个分类的问题。我们可以用它来对垃圾邮件和正常邮件进行分类。
from collections import defaultdict
def train_naive_bayes(train_data):
# 计算先验概率和条件概率
num_train = len(train_data)
num_words = len(train_data[0]) - 1
words_in_spam = defaultdict(int)
words_in_ham = defaultdict(int)
spam_total_words = 0
ham_total_words = 0
spam_count = 0
for data in train_data:
if data[-1] == 1:
spam_count += 1
for i in range(num_words):
if data[i] == 1:
words_in_spam[i] += 1
spam_total_words += 1
else:
for i in range(num_words):
if data[i] == 1:
words_in_ham[i] += 1
ham_total_words += 1
prior_spam = spam_count / num_train
prior_ham = 1 - prior_spam
spam_prob = defaultdict(float)
ham_prob = defaultdict(float)
for i in range(num_words):
spam_prob[i] = (words_in_spam[i] + 1) / (spam_total_words + num_words)
ham_prob[i] = (words_in_ham[i] + 1) / (ham_total_words + num_words)
return prior_spam, prior_ham, spam_prob, ham_prob
def predict_naive_bayes(test_data, prior_spam, prior_ham, spam_prob, ham_prob):
# 计算后验概率并预测分类
num_test = len(test_data)
num_words = len(test_data[0]) - 1
result = []
for data in test_data:
spam_score = 0
ham_score = 0
for i in range(num_words):
if data[i] == 1:
spam_score += spam_prob[i]
ham_score += ham_prob[i]
else:
spam_score += 1 - spam_prob[i]
ham_score += 1 - ham_prob[i]
spam_score *= prior_spam
ham_score *= prior_ham
if spam_score > ham_score:
result.append(1)
else:
result.append(0)
return result
这个函数有两个参数train_data和test_data,它们都是二维的列表,每行代表一个样本,最后一列是分类标签,其余列是特征值(0或1)。我们可以将训练数据和测试数据分别传递给train_naive_bayes和predict_naive_bayes函数来训练模型和进行预测,下面是一个示例:
`python
train_data = [[1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
...
[0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
test_data = [[1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
...
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1
