朴素贝叶斯实现 – 准确性问题

编辑:可在以下链接找到可用的正确代码版本: https://github.com/a7x/NaiveBayes-Classifier

我使用了来自openClassroom的数据,并开始在Python中开发一个小型的朴素贝叶斯版本。步骤包括常规的训练和预测。我有一些问题,想知道为什么准确率相当差。

  1. 在训练过程中,我通过以下公式计算了对数似然:

    log( P ( word | spam ) +1 ) /( spamSize + vocabSize .)

    我的问题是:为什么在这种情况下要加上vocabSize?这是正确的方法吗?使用的代码如下:

    #这是用于训练的。计算所有概率并将它们存储在一个向量中。最好将它们存储在一个文件中,以便更容易访问
    from __future__ import division
    import sys,os
    ''' 1. 垃圾邮件和非垃圾邮件已经各占50%。所以它们默认是0.5
        2. 现在我们需要分别计算每个单词在垃圾邮件和非垃圾邮件中的概率
        2.1 我们可以创建两个字典,基本上是defaultdicts,分别用于垃圾邮件和非垃圾邮件
        2.2 当需要计算概率时,我们只需代入值'''
    from collections import *
    from math import *
    spamDict = defaultdict(int)
    nonspamDict = defaultdict(int)
    spamFolders = ["spam-train"]
    nonspamFolders = ["nonspam-train"]
    path = sys.argv[1] #基础路径
    spamVector = open(sys.argv[2],'w') #将所有垃圾邮件值写入此文件
    nonspamVector = open(sys.argv[3],'w') #非垃圾邮件值
    #遍历垃圾邮件中的所有文件,并迭代添加值
    spamSize = 0
    nonspamSize = 0
    vocabSize = 264821
    for f in os.listdir(os.path.join(path,spamFolders[0])):
        data = open(os.path.join(path,spamFolders[0],f),'r')
        for line in data:
            words = line.split(" ")
            spamSize = spamSize + len(words)
            for w in words:
                spamDict[w]+=1
    for f in os.listdir(os.path.join(path,nonspamFolders[0])):
        data = open(os.path.join(path,nonspamFolders[0],f),'r')
        for line in data:
            words = line.split(" ")
            nonspamSize = nonspamSize + len(words)
            for w in words:
                nonspamDict[w]+=1
    logProbspam = {}
    logProbnonSpam = {} #这是用于存储对数概率的
    for k in spamDict.keys():
        #需要计算P(x | y = 1)
        numerator =  spamDict[k] + 1  # 频率
        print 'Word',k,' frequency',spamDict[k]
        denominator = spamSize + vocabSize
        p = log(numerator/denominator)
        logProbspam[k] = p
    for k in nonspamDict.keys():
        numerator = nonspamDict[k] + 1 #频率
        denominator = nonspamSize + vocabSize
        p = log(numerator/denominator)
        logProbnonSpam[k] = p
    for k in logProbnonSpam.keys():
        nonspamVector.write(k+" "+str(logProbnonSpam[k])+"\n")
    for k in logProbspam.keys():
        spamVector.write(k+" "+str(logProbspam[k])+"\n")
  2. 在预测过程中,我只是取一封邮件,将其拆分为单词,分别为垃圾邮件/非垃圾邮件添加所有概率,并乘以0.5。哪个值更高就是类别标签。代码如下:

    http://pastebin.com/8Y6Gm2my (Stackoverflow 又在搞什么鬼 :-/)

编辑:我已经删除了spam = spam + 1的部分。相反,我只是忽略这些单词

问题:我的准确率相当差。如下所示。

    垃圾邮件中的文件数为130
    ../NaiveBayes/spam-test中的垃圾邮件数为53,非垃圾邮件数为77
    非垃圾邮件中的文件数为130
    ../NaiveBayes/nonspam-test/中的垃圾邮件数为6,非垃圾邮件数为124

请告诉我我哪里做错了。我认为低于50%的准确率意味着实现中一定存在一些明显的错误。


回答:

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注