【发布时间】:2012-01-30 14:27:27
【问题描述】:
编辑:可以在以下位置找到正确的代码版本: https://github.com/a7x/NaiveBayes-Classifier
我使用了来自 openClassroom 的数据,并开始使用 Python 编写一个小版本的朴素贝叶斯。步骤是通常的训练,然后是预测。我有几个问题,想知道为什么准确性很差。
-
对于训练,我通过以下公式计算了对数似然:
log( P ( word | spam ) +1 ) /( spamSize + vocabSize .)
我的问题是:为什么我们在这种情况下添加
vocabSize:( 这是正确的做法吗?使用的代码如下:#This is for training. Calculate all probabilities and store them in a vector. Better to store it in a file for easier access from __future__ import division import sys,os ''' 1. The spam and non-spam is already 50% . So they by default are 0.5 2. Now we need to calculate probability of each word , in spam and non-spam separately 2.1 we can make two dictionaries, defaultdicts basically, for spam and non-spam 2.2 When time comes to calculate probabilities, we just need to substitute values ''' from collections import * from math import * spamDict = defaultdict(int) nonspamDict = defaultdict(int) spamFolders = ["spam-train"] nonspamFolders = ["nonspam-train"] path = sys.argv[1] #Base path spamVector = open(sys.argv[2],'w') #WRite all spam values into this nonspamVector = open(sys.argv[3],'w') #Non-spam values #Go through all files in spam and iteratively add values 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 = {} #This is to store the log probabilities for k in spamDict.keys(): #Need to calculate P(x | y = 1) numerator = spamDict[k] + 1 # Frequency 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 #frequency 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") -
对于预测,我只是拿了一封邮件,将其拆分为单词,添加所有概率,分别为 垃圾邮件/非垃圾邮件,并将它们乘以 0.5。以较高者为准。代码如下:
http://pastebin.com/8Y6Gm2my(Stackoverflow 出于某种原因又开始玩游戏了:-/)
编辑:我已经删除了垃圾邮件 = 垃圾邮件 + 1 件事。相反,我只是忽略那些话
问题:我的准确性很差。如下所述。
No of files in spam is 130
No. of spam in ../NaiveBayes/spam-test is 53 no. of non-spam 77
No of files in non-spam is 130
No. of spam in ../NaiveBayes/nonspam-test/ is 6 no. of non-spam 124
请告诉我哪里出了问题。我认为低于 50% 的准确度意味着在实施过程中一定存在一些明显的错误。
【问题讨论】:
-
您不是在做“朴素贝叶斯”,而是在用拉普拉斯平滑做贝叶斯,“k”(拉普拉斯平滑参数)等于 1。这就是为什么要在分子上加 1( k) 和 vocabsize (k * set_size) 为分母。
-
上面的代码你运行了吗?它不会给你一个数学领域的错误吗?您需要将计数收集为浮点数,否则在除法时一切都将变为零。
-
转到ai-class.com/home 并观看有关“机器学习”(第 5 课)的视频,以了解有关拉普拉斯平滑的更多信息以及它是否正确。使用它有利有弊。
-
@JimClay:几乎在多项式朴素贝叶斯的每一个实际实现中都会执行拉普拉斯或利德斯通平滑。
-
我认为 from future 进口部门负责部门。是的,我加了拉普拉斯来弥补缺席。谢谢