码迷,mamicode.com
首页 > 其他好文 > 详细

朴素贝叶斯

时间:2016-04-15 18:06:12      阅读:277      评论:0      收藏:0      [点我收藏+]

标签:

朴素贝叶斯

  • 优点: 在数据较少的情况下仍然有效,可以处理多类别问题。
  • 缺点: 对于输入数据的准备方式较为敏感。
  • 使用数据类型: 标称型数据。

  朴素贝叶斯是贝叶斯决策理论的一部分。

  使用决策树方法对数据进行分类不会非常成功,二和简单的概率计算相比,kNN的计算量太大,因此一般问题使用概率比较方法。

使用条件概率来分类

  定义贝叶斯分类准则:

  • 如果P(c1| x, y) > P(c2| x, y), 那么属于类别c1
  • 如果P(c1| x, y) < P(c2| x, y), 那么属于类别c2

  其中c 为类别,x, y为坐标。

  使用贝叶斯准则,可以通过一直的三个概率值来计算未知的概率值。

使用朴素贝叶斯进行文档分类

  机器学习的一个重要应用就是文档的自动分类。 在文档分类中,整个文档(如电子邮件)是实例,而电子邮件中的某些元素则构成特征。虽然电子邮件是一种会不断增加的文本,但我们同样也可以对新闻报道,用户留言,政府公文等其他任意类型的文本进行分类。 我们可以观察文档中出现的词, 并把每个词的出现或者不出现作为一个特征,这样得到的特征数目就会跟词汇表中的词目一样多。 朴素贝叶斯是上节介绍的贝叶斯分类器的一个扩展, 适用于文档分类的常用算法。

  朴素贝叶斯的一般过程:

1 收集数据 可以使用任何算法。
2 准备数据 需要数值型或者布尔型数据
3 分析数据 又大量特征时,绘制特征作用不大,此时使用直方图效果更好
4 训练算法 计算不同的独立特征的条件概率
5 测试算法 计算错误率
6 使用算法 一个常见的朴素贝叶斯应用使文档分类。 可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要使文本

使用python进行文本分类

  要从文本中获取特征, 需要先拆分文本。特征来自文本的词条(token), 一个词条是字符的任意组合。 可以把词条想象为单词, 也可以使用非单词词条,如URL, IP地址或者任意其他字符串。然后将每个文本片段表示为一个单词向量,其中值为1表示词条出现在文档中,0表示词条未出现。

  以在线社区的留言板为例。为了不影响社区的发展,我们要屏蔽侮辱性的言论, 所以要构建一个快速过滤器,如果某条留言使用了负面或者侮辱性的语言, 那么就将该留言标识为内容不当。过滤这类内容是一个很常见的需求。对此问题建立两个类别: 侮辱类和非侮辱类,使用1和0表示

准备数据: 从文本中构建词向量

  将把文本看成单词向量或者词条向量,即将句子转换为向量。考虑出现在所有文档中的所有单词,再决定将哪些词纳入词汇表或者说所要的词汇集合, 然后必须要将每一篇文档转换为词汇表上的向量。词表到向量的转换函数:

def loadDataSet():
    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]    #1 is abusive, 0 not
    return postingList,classVec
                 
def createVocabList(dataSet):
    vocabSet = set([])  #create empty set
    for document in dataSet:
        # 创建两个集合的并集
        vocabSet = vocabSet | set(document) #union of the two sets
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
    # 创建一个其中所含元素都为0的向量
    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                        

训练算法: 从词向量计算概率

  现在已经知道了一个词是否出现在一篇文档中,也知道该文档所属的类别。令w作为一个向量于是有: P(ci|w) = P(w|ci)P(ci)/P(w)

我们将使用上述公式,对每个类计算该值,然后比较这两个概率值的大小。首先通过类别i(侮辱类和非侮辱类) 中文档数除以总的文档数来计算概率P(ci)。接下来计算P(w|ci), 根据朴素贝叶斯假设,如果w展开为一个个独立特征, 那么概率可以写作P(w0, w1,w2..... wn|ci)。假设苏由此都互相独立, 该假设也称作条件独立性假设,意味着可以使用P(w0|ci)P(w1|ci)P(w2|ci)......P(wn|ci)计算上述概率,简化计算过程。

  伪代码如下:

计算每个类别的文档数目
对每篇训练文档:
        对每个类别:
                如果词条出现在文档中-> 增加该词条的计数值
                增加所有词条的计数值
        对每个类别:
                对每个词条:
                                将该词条的数目除以总词条数目得到条件概率
        返回每个类别的条件概率

朴素贝叶斯分类器训练函数:

def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    p0Num = ones(numWords); p1Num = ones(numWords)      #change to ones() 
    p0Denom = 2.0; p1Denom = 2.0                        #change to 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 = log(p1Num/p1Denom)          #change to log()
    p0Vect = log(p0Num/p0Denom)          #change to log()
    return p0Vect,p1Vect,pAbusive

现在已经准备好构建完整的分类器,朴素贝叶斯分类函数如下:

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)    #element-wise mult
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else: 
        return 0
    
def testingNB():
    listOPosts,listClasses = loadDataSet()
    myVocabList = createVocabList(listOPosts)
    trainMat=[]
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))
    testEntry = [love, my, dalmation]
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print testEntry,classified as: ,classifyNB(thisDoc,p0V,p1V,pAb)
    testEntry = [stupid, garbage]
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print testEntry,classified as: ,classifyNB(thisDoc,p0V,p1V,pAb)

将每个词的出现与否作为一个特征, 这个可以被描述为词集模型。如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息。因此使用词袋模型。词袋模型中,每个单词可以出现多次, 而在刺激中, 每个词只能出现一次。

朴素贝叶斯词袋模型代码:

def bagOfWords2VecMN(vocabList, inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec

 

朴素贝叶斯

标签:

原文地址:http://www.cnblogs.com/keltoy/p/5396252.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!