py2.7 : 《机器学习实战》 朴素贝叶斯 1.12号 4.5.3 训练算法:从词向量计算概率

PS:朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法

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

# -*- coding:utf-8 -*-
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代表侮辱性文字,0代表正常语言;并且之所以有6个是因为6组测试并且分别为正常言论和带有侮辱性的
    return postingList,classVec #返回第一个是切分好的文档集合,第二个是分类标签
#这些文本的类别由人工标注,标注信息用于训练程序以便自动检测侮辱留言

def creatVocabList(dataSet): #对数据集切换为向量集
    vocabSet = set([]) #创建一个空集
    for document in dataSet:
        vocabSet = vocabSet | set(document) #并集操作
    return list(vocabSet) #得到的是一个去重过的单词集

def setOfWords2Vec(vocabList , inputSet): #函数输入文档,输出文档向量(1 or 0)表示该词在输入文档是否出现
    returnVec = [0]*len(vocabList) #创建一个其中所含元素都为0的向量(初始化)
    for word in inputSet:#遍历,如果出现了词汇表中的单词,变为1.这样就不用在检查单词是否在vocablist中了
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else:
            print "the word : %s is not in my vocabulary!" % word
    return returnVec


这样做的好处就是,向量便于操作,或者说是将单词很好的作为了一个整体出现在列表里;

 测试一下得到结果

# -*- coding:utf-8 -*-
import bayes
listOPosts,listClasses = bayes.loadDataSet()
myVocabList = bayes.creatVocabList(listOPosts) #去重得到单词表
print myVocabList

出现:

['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']
#这里我手动缩进了

即得到正确的分词集


4.5.2 训练算法:从词向量计算概率(这里是已经被优化过的代码)

def trainNB0(trainMatrix,trainCategory):#文档矩阵,类别标签构成的向量
    numTrainDocs = len(trainMatrix) #先得到测试矩阵的长度
    numWords = len(trainMatrix[0]) #单词个数
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    p0Num = ones(numWords) ; p1Num = ones(numWords) #初始化概率
    p0Denom = 2.0 ; p1Denom = 2.0 #防止概率为0的时候让累乘概率为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)#为了避免python下溢出,ln(a*b) = ln(a) + ln(b)
    p0Vect = log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive #出现负值是正确的,不影响最终结果
#f(x) 和 ln(f(x)) 会一块增大,这表明想求函数的最大值的时候,可以使用该函数的自然对数替换原函数求解
#拉普拉斯平滑:当某个条件概率为0,这样在贝叶斯定理中分子分母都为0,为了避免这种情况,使用该定理
#分子+1,分母加X^i , 可能出现的种类数,这里仅仅让词出现次数为1,分母初始化为2,又名+1平滑

4.5.3 朴素贝叶斯分类函数:

def testingNB(): #封装操作
    listOPosts , listClasses = loadDataSet()
    myVocabList = creatVocabList(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)

训练效果:


你可能感兴趣的:(机器学习笔记)