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

来源:互联网 发布:淘宝收复女短裤 编辑:程序博客网 时间:2024/06/05 20:12

参考:

http://blog.csdn.net/marvin521/article/details/9262445

http://blog.csdn.net/rk2900/article/details/8984276

naive bayes 还是很简单的,网上的很多细节都没有说清楚,我直接看了原版的《Machine learning in action》

把细节都扒了出来,流程是这样的

1.根据所有邮件构建一个特征向量,向量的维度就是邮件所有单词的最小集合,[0,0,0,0,0]

2.训练Naive Bayes classfier,生成特征向量对垃圾/非垃圾邮件判断的权重,纬度和特征向量一致[1,2.1,4,2,5]/[1,-1,0.2,4,5]

(我一开始以为NB不需要训练,直接计算的,所以很多位置弄错了)

3.开始测试,将测试的邮件转为特征向量,这里有两点,一定要注意,网上都没有提到,我看代码才搞清楚,不知到为什么一直没人提到过

a) 转换时,如果特征向量里没有这个纬度的话,就不考虑,比如我输入的是"我是谁呢",特征向量里没有“呢”这个纬度,不考虑,生成(0,1,0,1,1)

b)转换时,如果一个纬度出现两次,只用考虑一次比如“我是谁谁”,还是生成(0,1,0,1,1)

4.将生成的向量与垃圾/非垃圾权重向量乘积(相当于屏蔽某些特征)再求和

5.比较大小,判断类型

Bayes公式在这里的应用

Bayes就是通过先验概率求后验概率

P(A|B) = P(B|A) * P(A) / P(B)

符号说明:

R:邮件中垃圾邮件的概率

r:邮件中正常邮件的概率

Xi:出现纬度i的概率

则判断是否是垃圾邮件可以通过:

P(R|X1,X2,X3.....Xn)  <> P(r|X1,X2,X3.....Xn) 大小关系确定测试邮件的归属

由bayes公式

=> P(X1,X2,...Xn|R) * P(R) / P(X1,X2,...Xn) <> P( P(X1,X2,...Xn|r) * P(r) / P(X1,X2,...Xn)

因为是邮件中的文本,可以简单认为是文本间是相互独立的,所以

=>P(X1|R) *P(X2|R)...P(Xn|R) * P(R)  <> P(X1|r)*P(X2|R),...*P(Xn|r) * P(r)

测试邮件中并不能包含所有的特征文本,可能P(Xn|R) = 0,造成两边无法比较的情况 0 <> 0

可以取对数来化解,Ln(X)的单调性和 X是一致的

=>Ln(P(X1|R) *P(X2|R)...P(Xn|R) * P(R) ) <> Ln(P(X1|r)*P(X2|R),...*P(Xn|r) * P(r))

=>P(X1|R) + P(X2|R) +....+ P(Xn|R) + P(R) <> P(X1|r) + P(X2|r)....+P(Xn|r) * P(r)

我也在这里实现一下

#-*- coding:utf-8 -*-'''Created on Aug 24, 2013@author: blacklaw'''from numpy import *postingList = [               ['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],                 ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],                 ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],                 ['stop', 'posting', 'stupid', 'worthless', 'garbage'],                 ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],                 ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']              ]  classVec = [0,1,0,1,0,1]def docs2set(data):    retSet = set()    for li in data:        retSet = retSet | set(li)    return retSetdef list2vect(li, wordsSet):    retVect = zeros(len(wordsSet))    for word in li:        if word in wordsSet:            retVect[list(wordsSet).index(word)] = 1        else:            print "%s not in wordsSet" % word    return retVect    def trainNB(martix, wordsSet, category):    '''    pRvect = zeros(len(wordsSet))    prvect = zeros(len(wordsSet))    '''    # use ones not zeros: caution, log(0) will be error    pRvect = ones(len(wordsSet))    prvect = ones(len(wordsSet))    RSum = rSum = 0    for i,vect in enumerate(martix):        if category[i] == 1: # 1 means Rubbish            pRvect += vect            RSum += sum(vect)        else:            prvect += vect            rSum += sum(vect)    return log(pRvect/RSum), log(prvect/rSum)    def testNB(pRvect, prvect, testDoc, wordsSet, category):    testVect = list2vect(testDoc, wordsSet)    R = float(sum(category)) / len(category)    r = 1 - R    '''    Caution:     we have trained NB pR/rvect use log()    so there use "+ R" "sum", not * R     '''    pFromR = R + sum(pRvect * testVect)    pFromr = r + sum(prvect * testVect)    print pFromR, pFromr    return pFromR > pFromr                if __name__ == "__main__":    wordsSet = docs2set(postingList)    martix = []    for posting in postingList:        martix.append(list2vect(posting, wordsSet))    pRvect, prvect = trainNB(martix, wordsSet, classVec)    print testNB(pRvect, prvect, ['love', 'my', 'dalmation'], wordsSet, classVec)    print testNB(pRvect, prvect, ['stupid', 'garbage'], wordsSet, classVec)  


结果:-8.3333169375 -6.2615727688False-3.30943641665 -5.8561076607True







原创粉丝点击