初探NO.3—从头到尾聊聊贝叶斯的分类方法2,no.3贝叶斯


上一篇梳理了一下朴素贝叶斯和贝叶斯估计的一点理论

http://blog.csdn.net/leo_is_ant/article/details/43741261


今天再接再厉利用《机器学习实战的python》来探究一下代码方面是如何落地的。

首先说明一下,这一次的例子是一个文档的分类,文档的分类和上一篇写的理论稍有不同的是它对不同的文档进行了一次预处理,把所有文档做成了一个“字典”。原因是每一个文档的单词数目不一定相同,所谓按照之前的分类方法不好确定它的维度。这一个例子,很好地诠释了贝叶斯分类——用很少的例子也能起到一定的效果。


第一步准备数据,这一次的数据需要因为预处理而提前说明,数据和方法如下:

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
postingList 里面是数据,classVec是数据的标签(1表示有羞辱性的词汇,0表示没有),这里有意思的地方在于每一个item的维度可能有所偏差,而且单词很少重复。如果这样直接用贝叶斯显然不合时。所以我们需要对着一些数据进行处理。处理的过程需要把这一些数据做成一个集合(set类型),并且把每一个item在这一个set里面进行标注,方法和代码如下:

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):
    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
这里顺便po出代码运算到这一步的实验结果以便理解:

testcode:

postingList,classVec=loadDataSet()
vocabSet=createVocabList(postingList)
returnVec=setOfWords2Vec(vocabSet, postingList[0])
for everyitem in postingList:
    print everyitem
print classVec
print vocabSet
print returnVec
 
result:

['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']
[0, 1, 0, 1, 0, 1]
['cute', 'love', 'help', 'garbage', 'quit', 'I', 'problems', 'is', 'park', 'stop', 'flea', 'dalmation', 'licks', 'food', 'not', 'him', 'buying', 'posting', 'has', 'worthless', 'ate', 'to', 'maybe', 'please', 'dog', 'how', 'stupid', 'so', 'take', 'mr', 'steak', 'my']
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1]
这里我们可以看到,最后一行就是我们以第一个为例取到的实际的特征维度,和每一个特征的取值,它的标签由上面的数据可知为0.


接下俩的就是去训练朴素贝叶斯,这就涉及上一篇那一些有关的公式,但是再Python代码中其实并不是特别复杂,方法如下:

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
这里的trainMatrix就是我们刚才鼓捣出来的所有的item的向量,trainCategory是标签类别。首先他会算一个总体的标签为1的先验概率pAbusive,这个pAbusive就是上一篇博客中的:

接着它开始计算每一种情况的条件概率,所得到的结果放到向量p0Vect和p1Vect里面,这个条件概率就是上一篇博客中的:


求完了之后我们就已经将这一个模型训练完成了,接下来其实就是对新的数据进行分类,方法如下:

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)
这里对新的词组进行了测试。


哈哈,整个贝叶斯就写完了,贝叶斯作为一种高效简单的算法被广泛使用。但是这个模型的假设不独立的时候会变得复杂,这时朴素的贝叶斯会变成一个贝叶斯的网络。所以这一块有兴趣的童鞋咱们一起探究一下吧~




相关内容