《机器学习实战》源码解析(三):朴素贝叶斯

本系列以书中源码为主,稍作修改并添加注释,均实际运行可行。为免后来者踩坑,特此公开!欢迎打赏!
转载请注明出处!

from numpy import *
import re
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表示含有侮辱类单词
    return postingList,classVec

def createVocabList(dataSet): #创建词表向量
    vocabSet = set([]) #初始化空集
    for document in dataSet:
        vocabSet =vocabSet | set(document)#将所有文档中的不重复词并入
    return list(vocabSet)#列表化


def bagOfWords2VecMN(vocabList,inputSet): #将输入文档按照词表向量向量化。参数:词汇表,某文档。改进:词集模型改为词袋模型
    returnVec = [0]*len(vocabList)#创建长度为词汇表的列表,并置0
    for word in inputSet:#判断输入文档是否出现在词表向量中,若有则在相应位置置1,若无则返回提示语
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec
def trainNB0(trainMatrix,trainCategory):#朴素贝叶斯分类器训练函数。参数:1:向量化文档2:词条向量
    numTrainDocs = len(trainMatrix)#获取文档矩阵中文档的数目
    numWords = len(trainMatrix[0])#获取词条向量的长度
    pAbusive = sum(trainCategory)/float(numTrainDocs)#计算文档属于侮辱性文档的概率
    p0Num = ones(numWords); p1Num = ones(numWords)#创建两个长度为词条向量等长的列表,平滑处理:初始值设为1
    p0Denom = 2.0;p1Denom = 2.0#平滑处理,初始值设为2
    for i in range(numTrainDocs):
        if trainCategory[i] ==1:#如果该词条向量对应的标签为1
            p1Num += trainMatrix[i]#统计所有类别为1的词条向量中各个词条出现的次数
            p1Denom += sum(trainMatrix[i])#统计类别为1的词条向量中出现的所有词条的总数
        else:
            p0Num += trainMatrix[i]#同上
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num/p1Denom)#利用Numpy数组计算p(wi/c1),即类1条件下各词条出现的概率
    p0Vect = log(p0Num/p0Denom)#利用Numpy数组计算p(wi/c0),为避免下溢,后面会改为log()
    return p0Vect,p1Vect,pAbusive#返回
#朴素贝叶斯分类函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):#注意参数2,3均已log化
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)
    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 textParse(bigString):#解析文本,利用正则表达式去除非单词字符,空格符,并将大写字母变为小写
    listOfTokens = re.split(r'\W*',bigString)
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

def spamTest():#垃圾邮件测试函数
    docList=[]; classList = []; fullText =[]#新建三个列表:二维字符串列表,类列表,一维字符串列表
    for i in range(1,26):
        #打开并读取指定目录下的文本并进行数据清洗
        wordList = textParse(open(r'选择你自己的数据集存储路径\spam\%d.txt' % i).read())
        docList.append(wordList)#保存得到的字符串列表
        fullText.extend(wordList)#保存得到的全部字符串
        classList.append(1)#类列表添加标签1
        #打开并取得另外一个类别为0的文件,然后进行处理
        wordList = textParse(open(r'选择你自己的数据集存储路径\ham\%d.txt' % i,encoding='gb18030',errors='ignore').read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)
    vocabList = createVocabList(docList)#将所有邮件中出现的字符串构建成字符串列表,即词表向量
    trainingSet = list(range(50)); testSet=[]  #构建一个大小为50的整数列表和一个空列表
    for i in range(10):#随机选取1-50中的10个数,作为索引,构建测试集
        randIndex = int(random.uniform(0,len(trainingSet)))#随即选取1-50中的一个整型数
        testSet.append(trainingSet[randIndex])#将选出的数的列表索引值添加到testSet列表中
        del(trainingSet[randIndex])  #从整数列表中删除选出的数,防止下次再次选出。同时将剩下的作为训练集
    trainMat=[]; trainClasses = []#新建两个列表
    for docIndex in trainingSet:#遍历训练集中的每个字符串列表
        trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))#将字符串列表转为词条向量,然后添加到训练矩阵中
        trainClasses.append(classList[docIndex])#将该邮件的类标签存入训练类标签列表中
    p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))#计算贝叶斯函数需要d阿概率值并返回
    errorCount = 0
    for docIndex in testSet:        #遍历测试集中的字符串列表
        wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])#将测试集中的字符串列表转为词条向量
        if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
            errorCount += 1#对测试集中字符串向量进行预测分类,分类结果不等于实际结果
            print ("classification error",docList[docIndex])
    print(' the error rate is: ',float(errorCount)/len(testSet))
    #return vocabList,fullText
spamTest()
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值