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

参考:

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 retSet

def 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.2615727688
False
-3.30943641665 -5.8561076607
True







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值