欢迎访问宙启技术站
智能推送

Python函数实现朴素贝叶斯分类器

发布时间:2023-06-21 10:04:09

贝叶斯分类器是机器学习中重要的分类算法之一,它的优点是模型简单、计算快速、对数据噪声不敏感等。在本文中,我们将使用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