机器学习算法——朴素贝叶斯算法

本文介绍了朴素贝叶斯算法的基本概念、贝叶斯公式及其在文本分类中的应用,重点讲解了如何通过朴素贝叶斯实现垃圾邮件分类,包括数据预处理、特征提取和算法训练过程。

一、朴素贝叶斯算法介绍

        1、朴素贝叶斯算法概述

        朴素贝叶斯算法是一种经典的概率分类算法,它基于贝叶斯定理和特征独立性假设。该算法常被用于文本分类、垃圾邮件过滤、情感分析等领域。

        朴素贝叶斯算法的核心思想是通过已知类别的训练样本集,学习出每个类别的概率分布模型,然后根据待分类样本的特征,利用贝叶斯定理计算出样本属于各个类别的后验概率,最终选择具有最大后验概率的类别作为分类结果。

        在朴素贝叶斯算法中,特征之间被假设为相互独立,这是为了简化计算。尽管这个假设在现实问题中并不总是成立,但朴素贝叶斯算法仍然表现出良好的分类效果。

        2、贝叶斯公式

        贝叶斯公式(Bayes' theorem)是概率论中的重要定理,用于计算在给定某一事件发生的条件下,另一事件发生的概率。用数学语言表达就是:支持某项属性的事件发生得愈多,则该属性成立的可能性就愈大。该公式的数学表达如下所示:

P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)}

其中:

  • ( P(A|B) ) 表示在事件 B 发生的条件下事件 A 发生的概率,称为后验概率(posterior probability)。
  • ( P(B|A) ) 表示在事件 A 发生的条件下事件 B 发生的概率,称为似然度(likelihood)。
  • ( P(A) ) 和 ( P(B) ) 分别表示事件 A 和事件 B 单独发生的概率,分别称为先验概率(prior probability)。

        先验概率:即基于统计的概率,是基于以往历史经验和分析得到的结果,不需要依赖当前发生的条件。

        后验概率:则是从条件概率而来,由因推果,是基于当下发生了事件之后计算的概率,依赖于当前发生的条件。

        条件概率:记事件A发生的概率为P(A),事件B发生的概率为P(B),则在B事件发生的前提下,A事件发生的概率即为条件概率,记为P(A|B),读作“在B条件下A的概率”。

        联合概率:表示两个事件共同发生的概率。A与B的联合概率表示为P(AB),或者P(A,B),或者P(A∩B)。

        3、朴素贝叶斯算法的原理

        朴素贝叶斯分类器是一类简单的概率分类器,在强(朴素)独立性假设的条件下运用贝叶斯公式来计算每个类别的后验概率,假设每个特征之间没有联系。

        通俗的解释:已知结果(先验概率),结果与在此结果为条件下出现的现象(条件概率)相乘的到结果和现象同时发生的联合概率。除以现象单独发生的概率,就得出在某现象发生的条件下,发生结果的概率(后验概率)

        它的原理可以简单概括如下:

  • 贝叶斯定理: 贝叶斯定理描述了在已知一些条件下计算另一条件概率的关系。对于分类问题,它表示了在观察到特征值 (x) 的情况下,某个类别 (c) 的概率,即 (P(c|x))。

  • 特征条件独立假设: 朴素贝叶斯分类器假设给定类别的情况下,各个特征之间是相互独立的,也就是说特征之间不存在关联性。这个假设使得分类器的计算变得简单,并且易于实现。

  • 分类决策规则: 根据贝叶斯定理和特征条件独立假设,可以计算样本属于每个类别的后验概率 (P(c|x)),然后选择具有最大后验概率的类别作为样本的分类结果。

  • 参数估计: 在实际应用中,需要通过训练数据集来估计先验概率 (P(c)) 和条件概率 (P(x|c))。常见的估计方法包括最大似然估计和拉普拉斯平滑等。

二、朴素贝叶斯算法实现垃圾邮件分类

        1、实现步骤

        (1)、收集数据:提供文本文件               

        (2)、准备数据:将文本文件解析成词条向量

        (3)、分析数据:检查词条确保解析的正确性

        (4)、训练算法:使用之前建立的trainNB0()函数

        (5)、测试算法:使用classifyNB(),并且构建一个新的测试函数来计算文档集的错误率

        (6)、使用算法:构建一个完整的程序对一组文档进行分类,并显示错误率

        

        2、代码实现
                准备数据

                 垃圾邮件和正常邮件都有各25个,它们都是以文本文件txt的格式存储

图2-1

图2-3

                图2-3就是一份垃圾邮件的示例

               文本切分

                拿到一份很长的数据文本之后,我们需要对其进行切分,提取到各个单词,我们可以通过下面代码的方式来实现:

mySent='This book is the best book on python or M.L. I have ever laid eyes upon.'
print(mySent.split())
import re
mySent='This book is the best book on python or M.L. I have ever laid eyes upon.'
regEX=re.compile('\\W+')
listOfTokens=regEX.split(mySent)
print(listOfTokens)
import re
mySent='This book is the best book on python or M.L. I have ever laid eyes upon.'
regEX=re.compile('\\W+')
listOfTokens=regEX.split(mySent)
print([tok for tok in listOfTokens if len(tok)>0])
print([tok.lower() for tok in listOfTokens if len(tok)>0])

                代码的运行结果如下图所示:

图2-3

                可以发现通过正则表达式来进行切分并且将字符串全部转换成小写,去掉标点符号可以很好的将一串长文本切分成各个小单词

def textParse(bigString):  
    import re
    listOfTokens = re.split(r'\W*', bigString)  
    return [tok.lower() for tok in listOfTokens if len(tok) > 2] 

textParse(bigString) 函数用于将文本进行分词处理,并转换为小写形式。

                文本文件解析

                我们不仅仅要将字符串拆分成各个单词,我们还要讲各个句子转换成向量

def createVocabList(dataSet):
    vocabSet=set()
    for document in dataSet:
        vocabSet=vocabSet|set(document)   #两个集合的并集
    return list(vocabSet)
 
def setOfWords2Vec(vocabList,inputSet):
    returnVec=[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]=1
        else:
            print("the word:%s is not in my vocabulary!"%word)
    return returnVec

                

createVocabList(dataSet) 函数通过遍历数据集,创建一个不重复词汇的列表。

setOfWords2Vec(vocabList, inputSet) 函数将文本转换为词向量表示形式,其中向量的每个元素表示对应词汇在文本中是否出现。

                训练算法
def trainNB0(trainMatrix,trainCategory):
    numTrainDocs=len(trainMatrix)   
    numWords=len(trainMatrix[0])   
    pABusive=sum(trainCategory)/float(numTrainDocs) 
    # p0Num=np.zeros(numWords)
    # p1Num=np.zeros(numWords)
    # p0Denom=0.0
    # p1Denom=0.0
    p0Num=np.ones(numWords)
    p1Num=np.ones(numWords)
    p0Denom=2.0 
    p1Denom=2.0
 
    for i in range(numTrainDocs):
        if trainCategory[i]==1:
            p1Num+=trainMatrix[i] 
            p1Denom+=sum(trainMatrix[i])
        else:
            p0Num+=trainMatrix[i] 
            p0Denom+=sum(trainMatrix[i])
    # p1Vect=p1Num/p1Denom
    # p0Vect=p0Num/p0Denom
    p1Vect=np.log(p1Num/p1Denom)
    p0Vect=np.log(p0Num/p0Denom)
 
    return  p0Vect,p1Vect,pABusive

trainNB0(trainMatrix, trainCategory) 函数通过朴素贝叶斯算法计算侮辱性文字和正常言论的条件概率,并得到类别标签的先验概率。

                贝叶斯分类
#贝叶斯分类函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1=sum(vec2Classify*p1Vec)+np.log(pClass1)
    p0=sum(vec2Classify*p0Vec)+np.log(1-pClass1)
    if p1>p0:
        return 1
    else:
        return 0

classifyNB(vec2Classify, p0Vec, p1Vec, pClass1) 函数根据贝叶斯分类规则,计算输入文本属于侮辱性文字和正常言论的概率,并返回分类结果。

                垃圾邮件分类器的实现
def spamTest():
    docList = []
    classList = []
    fullText = []
    for i in range(1, 26):  # 遍历25个txt文件
        wordList = textParse(open('D:/实验报告/机器学习/朴素贝叶斯/email/spam/%d.txt' % i,'r',encoding='latin1').read())  # 读取每个垃圾邮件,并字符串转换成字符串列表
        docList.append(wordList)
        fullText.append(wordList)
        classList.append(1)  # 标记垃圾邮件,1表示垃圾文件
        wordList = textParse(open('D:/实验报告/机器学习/朴素贝叶斯/email/ham/%d.txt' % i,'r',encoding='latin1').read())  # 读取每个非垃圾邮件,并字符串转换成字符串列表
        docList.append(wordList)
        fullText.append(wordList)
        classList.append(0)  # 标记正常邮件,0表示正常文件
    vocabList = createVocabList(docList)  # 创建词汇表,不重复
    trainingSet = list(range(50))
    testSet = []  # 创建存储训练集的索引值的列表和测试集的索引值的列表
    for i in range(10):  # 从50个邮件中,随机挑选出40个作为训练集,10个做测试集
        randIndex = int(random.uniform(0, len(trainingSet)))  # 随机选取索索引值
        testSet.append(trainingSet[randIndex])  # 添加测试集的索引值
        del (trainingSet[randIndex])  # 在训练集列表中删除添加到测试集的索引值
    trainMat = []
    trainClasses = []  # 创建训练集矩阵和训练集类别标签系向量
    for docIndex in trainingSet:  # 遍历训练集
        trainMat.append(setOfWords2Vec(vocabList, docList[docIndex]))  # 将生成的词集模型添加到训练矩阵中
        trainClasses.append(classList[docIndex])  # 将类别添加到训练集类别标签系向量中
    p0V, p1V, pSpam = trainNB0(np.array(trainMat), np.array(trainClasses))  # 训练朴素贝叶斯模型
    errorCount = 0  # 错误分类计数
    for docIndex in testSet:  # 遍历测试集
        wordVector = setOfWords2Vec(vocabList, docList[docIndex])  # 测试集的词集模型
        if classifyNB(np.array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:  # 如果分类错误
            errorCount += 1  # 错误计数加1
            # print("分类错误的测试集:",docList[docIndex])
    print('错误率:%.2f%%' % (float(errorCount) / len(testSet) * 100))

spamTest() 函数是整个垃圾邮件分类器的主要流程,它读取垃圾邮件和正常邮件数据集,并进行训练集和测试集的划分。然后利用朴素贝叶斯算法进行模型训练,并对测试集进行分类预测,最终输出分类错误率。

                实验结果

图2-4

                实验分析

当我们运行这段代码进行垃圾邮件分类实验时,会得到一个错误率的输出结果。这个错误率代表了分类器在测试集上的分类准确度,即被错误分类的邮件所占的比例。

通过观察错误率,我们可以对实验结果进行一些分析:

  • 如果错误率很低(接近0%),意味着分类器在识别垃圾邮件方面表现出色,具有较高的准确性。这是一个理想的结果,说明分类器能够有效地区分垃圾邮件和正常邮件。

  • 如果错误率较高(超过10%或更高),则意味着分类器在垃圾邮件分类方面表现较差,准确性较低。这可能是由于数据集的特点或者分类算法的选择问题导致的。需要进一步考虑改进算法、调整参数或使用更复杂的特征工程方法来提高分类器的性能。

此外,还可以对分类错误的样本进行分析,了解分类器的误判情况。例如,查看被错误分类为垃圾邮件的正常邮件,或者被错误分类为正常邮件的垃圾邮件。这可以帮助我们发现分类器的弱点,并进一步优化算法。

需要注意的是,这段代码只是一个简单的垃圾邮件分类器的示例,实际应用中可能需要更复杂的特征工程、模型选择和调优等步骤来提高分类器的性能。

        3、实验小结
  • 特征处理的重要性:对文本数据进行适当的预处理和特征提取是分类任务中的重要一环。在这个实验中,我们将文本转化为词向量表示,利用词汇出现的频率作为特征,从而实现邮件的分类。

  • 朴素贝叶斯分类器的应用:朴素贝叶斯算法是一种简单且有效的分类算法,它基于贝叶斯定理和假设特征之间相互独立。在这个实验中,我们使用朴素贝叶斯分类器来对垃圾邮件进行分类,通过计算条件概率和先验概率来得到分类结果。

  • 错误率分析的重要性:通过观察错误率,我们可以对分类器的性能进行评估。较低的错误率意味着分类器具有较高的准确性,而较高的错误率则需要进一步改进分类器。此外,还可以对分类错误的样本进行分析,从中发现分类器的弱点,并尝试改进算法或调整参数来提高分类器的性能。

<think>好的,我现在需要回答用户关于头歌平台上的朴素贝叶斯分类器实验的问题。用户可能是在做实验时遇到了困难,需要解析或者答案。首先,我要回顾朴素贝叶斯的基本原理,确保自己理解正确。根据提供的引用[1],朴素贝叶斯是基于贝叶斯定理和特征条件独立假设的分类算法,常用于文本分类、垃圾邮件过滤等。 接下来,用户提到的头歌平台实验可能涉及MultinomialNB类的使用,引用[2]提到fit和predict函数的功能。因此,实验可能要求学员实现数据预处理、模型训练和预测的步骤。我需要考虑实验中常见的任务,比如数据加载、特征提取(比如文本分类中的TF-IDF或词袋模型)、处理缺失值、模型训练与评估等。 用户可能需要具体的代码示例或步骤解析。例如,在数据预处理阶段,可能需要将文本转换为数值特征,使用CountVectorizer或TfidfTransformer。然后,应用MultinomialNB进行分类。此外,实验可能涉及参数调整,比如平滑参数alpha的设置,或者评估指标如准确率、混淆矩阵的计算。 另外,需要注意头歌平台可能有特定的代码结构或输入输出要求,比如需要补全部分代码块,或者按照特定格式输出结果。虽然无法提供直接的实验答案,但可以指导正确的实现方法,比如如何调用fit和predict方法,如何处理多项式分布的数据(适用于离散特征,如词频)。 可能的问题点包括:特征的条件独立性假设是否合理,如何处理连续型数据(可能需要高斯朴素贝叶斯),以及拉普拉斯平滑的作用。在实验中,正确应用这些概念是关键。例如,在代码中添加平滑参数防止零概率问题。 总结回答结构时,应先解释朴素贝叶斯的原理,然后分步骤说明实验可能涉及的关键环节,并给出代码示例,同时提醒注意事项和常见错误。最后,生成相关问题帮助用户进一步理解。</think>### 头歌平台朴素贝叶斯分类器实验解析 #### 1. **实验核心目标** 头歌平台的朴素贝叶斯实验通常围绕以下内容展开: - **数据预处理**:文本特征提取(如词频统计、TF-IDF转换) - **模型训练**:调用`MultinomialNB`类的`fit`函数,学习特征与标签的联合概率分布 - **模型预测**:使用`predict`函数对新样本进行分类 - **性能评估**:计算准确率、召回率、F1值等指标 #### 2. **关键代码实现** ```python from sklearn.naive_bayes import MultinomialNB from sklearn.feature_extraction.text import CountVectorizer # 示例文本数据集 texts = ["机器学习 朴素贝叶斯 分类器", "垃圾邮件 检测 朴素贝叶斯", "文本分类 算法"] labels = [1, 0, 1] # 假设1为技术类,0为垃圾类 # 文本向量化(词频统计) vectorizer = CountVectorizer() X = vectorizer.fit_transform(texts) # 模型训练(注意alpha平滑参数) model = MultinomialNB(alpha=1.0) model.fit(X, labels) # 预测新样本 new_text = ["朴素贝叶斯 应用 场景"] X_new = vectorizer.transform(new_text) print(model.predict(X_new)) # 输出预测标签 ``` #### 3. **实验常见问题** - **特征独立性假设**:实验中需验证特征工程是否符合独立性假设[^1] - **零概率问题**:通过`alpha`参数实现拉普拉斯平滑,避免未出现特征导致概率为0 - **数据分布类型**:离散特征用`MultinomialNB`,连续特征需用`GaussianNB` - **评估指标**:头歌平台可能要求输出特定格式的准确率或混淆矩阵 #### 4. **实验注意事项** - 严格匹配输入输出格式(如矩阵维度、小数点位数) - 文本数据需统一转换为小写并去除停用词 - 多项式朴素贝叶斯适用于**词频统计**场景(如实验中的文本分类) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿K还阔以

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值