机器学习——朴素贝叶斯

在机器学习领域,朴素贝叶斯算法是一种常见且强大的分类算法。它被广泛应用于文本分类、垃圾邮件过滤、情感分析等领域。

一、朴素贝叶斯算法
1.先验概率

        P(cj)代表还没有训练模型之前,根据历史数据/经验估算cj拥有的初始概率。P(cj)常被称为cj的先验概率 ,它反映了cj的概率分布,该分布独立于样本。通常可以用样例中属于cj的样例数|cj|比上总样例数|D|来近似,即:

P(c_{j})=\frac{\left | c_{j} \right |}{\left | D \right |}

2.后验概率

给定数据样本x时cj成立的概率P(cj  | x )被称为后验概率,因为它反映了在看到数据样本 x后 cj 成立的置信度。

3.贝叶斯定理

已知两个独立事件A和B,事件B发生的前提下,事件A发生的概率可以表示为P(A|B),即:

P(A|B)=\frac{P(A,B)}{P(B)}\Rightarrow P(A,B)=P(B)*P(A|B)=P(A)*P(B|A)\Rightarrow P(A|B)=\frac{P(A)*P(B|A)}{P(B)} 

4.MAP分类准则

x 属于类别 c* 的概率:

P(C=c^{*}|X=x)>P(C=c|X=x) c\neq c^{*}, c=c_{1},c_{2}\cdots c_{L}

利用贝叶斯准则转化为:

P(C=c^{*}|X=x)=\frac{P(X=x|C=c_{i})P(C=c_{i})}{P(X=x)}\propto P(X=x|C=c_{i})P(C=c_{i}) 

5.朴素贝叶斯分类器

朴素贝叶斯分类器采用了“属性条件独立性假设”,即每个属性独立地对分类结果发生影响。
为方便公式标记,不妨记P(C=c|X=x)为P(c|x),基于属性条件独立性假设,贝叶斯公式可重写为
P(c|X)=\frac{P(c)P(X|c)}{P(X)}=\frac{P(c)}{P(X)}\prod_{d}^{i=1}P(x_{i}|c)

其中d为属性数目,𝑥_𝑖 为 x 在第i个属性上的取值。

6.拉普拉斯修正 

若某个属性值在训练集中没有与某个类同时出现过,则训练后的模型会出现 over-fitting 现象。为了避免其他属性携带的信息,被训练集中未出现的属性值“抹去”,在估计概率值时通常要进行“拉普拉斯修正”:
令 N 表示训练集 D 中可能的类别数,𝑁_𝑖表示第i个属性可能的取值数,则贝叶斯公式可修正为:

 \hat{P}(c)=\frac{\left | D_{d} \right |+1}{\left | D \right |+N}                   \hat{P}(c)=\frac{\left | D_{c,x_{i}} \right |+1}{\left | D \right |+N_{i}}

 二、垃圾邮件分类

思路

读取垃圾邮件和正常邮件的数据,并将它们划分为训练集和测试集。
将邮件文本转换为特征向量,用于训练朴素贝叶斯分类器。
训练朴素贝叶斯分类器并对测试集进行分类,计算分类准确率。

代码

import os
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix

# 定义文本分割函数
def read_files_from_folder(folder_path, label):
    emails = []
    labels = []
    for file_name in os.listdir(folder_path):
        file_path = os.path.join(folder_path, file_name)
        with open(file_path, 'r', encoding='gbk') as file:
            email_text = file.read()
            emails.append(email_text)
            labels.append(label)
    return emails, labels

# 定义获取训练和测试数据集的函数
def get_train_test_data(ham_folder, spam_folder):
    ham_emails, ham_labels = read_files_from_folder(ham_folder, 0)
    spam_emails, spam_labels = read_files_from_folder(spam_folder, 1)
    emails = ham_emails + spam_emails
    labels = ham_labels + spam_labels
    return emails, labels


# 获取邮件数据
ham_folder = "D:/qq/3168619790/FileRecv/Ch04/email/ham"
spam_folder = "D:/qq/3168619790/FileRecv/Ch04/email/spam"
emails, labels = get_train_test_data(ham_folder, spam_folder)

# 定义生成词汇表的函数
def create_vocab_list(emails):
    vocab_set = set([])
    for email in emails:
        word_list = re.findall(r'\b\w+\b', email.lower())
        vocab_set = vocab_set | set(word_list)
    return list(vocab_set)

# 生成词汇表
vocabList = create_vocab_list(emails)

# 定义词向量化的函数
def words_to_vector(vocab_list, input_email):
    returnVec = [0] * len(vocab_list)
    word_list = re.findall(r'\b\w+\b', input_email.lower())
    for word in word_list:
        if word in vocab_list:
            returnVec[vocab_list.index(word)] = 1
    return returnVec

# 定义朴素贝叶斯训练函数
def train_naive_bayes(train_matrix, train_category):
    num_train_docs = len(train_matrix)
    num_words = len(train_matrix[0])
    p_spam = sum(train_category) / float(num_train_docs)
    p0_num = np.ones(num_words)
    p1_num = np.ones(num_words)
    p0_denom = 2.0
    p1_denom = 2.0
    for i in range(num_train_docs):
        if train_category[i] == 1:
            p1_num += train_matrix[i]
            p1_denom += sum(train_matrix[i])
        else:
            p0_num += train_matrix[i]
            p0_denom += sum(train_matrix[i])
    p1_vect = np.log(p1_num / p1_denom)
    p0_vect = np.log(p0_num / p0_denom)
    return p0_vect, p1_vect, p_spam


# 定义朴素贝叶斯测试函数
def classify_naive_bayes(vec2classify, p0_vec, p1_vec, p_class1):
    p1 = sum(vec2classify * p1_vec) + np.log(p_class1)
    p0 = sum(vec2classify * p0_vec) + np.log(1.0 - p_class1)
    if p1 > p0:
        return 1
    else:
        return 0

# 划分训练集和测试集
train_set, test_set, train_classes, test_classes = train_test_split(emails, labels, test_size=0.2, random_state=42)

# 将文本数据转换成特征向量
train_mat = []
for email in train_set:
    train_mat.append(words_to_vector(vocabList, email))

# 训练朴素贝叶斯分类器
p0V, p1V, pSpam = train_naive_bayes(np.array(train_mat), np.array(train_classes))

# 测试朴素贝叶斯分类器
error_count = 0
for i in range(len(test_set)):
    word_vector = words_to_vector(vocabList, test_set[i])
    if classify_naive_bayes(word_vector, p0V, p1V, pSpam) != test_classes[i]:
        error_count += 1

print("错误率:", float(error_count) / len(test_set) * 100)

结果

在测试过程中,分类器在5%的样本上做出了错误的预测,意味着分类器在这个测试集上表现良好。

三、错误与解决方法

错误:

这个由于文件编码不一致导致的,使用UTF-8编码对包含非UTF-8字符的文件进行解码时,就会引发错误。

解决方法:

可以使用文本编辑器或转码工具将文件的编码格式转换为UTF-8,我修改代码中读取文件的方式,代码with codecs.open('file.txt', 'r', encoding='gbk') as f,将用于指定打开文件时使用的编码方式的参数改为gbk。

 四、总结

在这个实验中,使用朴素贝叶斯算法进行了垃圾邮件分类。首先,获取了训练和测试数据集,并生成了词汇表。然后,将文本数据转换成特征向量,并使用朴素贝叶斯算法进行训练。最后,对测试集进行分类,并计算了分类器的错误率。实验结果显示,在测试过程中,分类器在5%的样本上做出了错误的预测,这意味着分类器在这个测试集上表现良好。在实验过程中,可能会遇到一些问题,例如文件编码不一致导致的错误。为了解决这个问题,可以使用文本编辑器或转码工具将文件的编码格式转换为UTF-8,并相应地修改代码中读取文件的方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值