zoukankan      html  css  js  c++  java
  • 机器学习实战3-贝叶斯分类

    1 基础名词解释

    1.1 概率: 已知模型和参数,预测出现某个结果的概率。

    1.2 统计:已知大量数据,利用数据去预测模型及其参数。

    1.3 先验概率: 根据以往经验和分析得到的概率,如抛硬币,我们抛之前,就认为硬币向上概率为0.5.

    1.4 后验概率: 事情已发生,判断事情发生由那个原因引起的概率。(由果溯因)

    1.5 P(x|θ): x表示一个具体数据,θ表示模型参数;x确定,表示为似然函数;θ确定,表示为概率函数。

    1.6 极大似然估计(MLE):已知一组样本数据,假定该数据满足某种模型,依据数据对模型的参数进行估计。

    2 过滤网站恶意留言

    朴素贝叶斯分类:

    关于该公式的几点说明:

      1. 该公式用于预测,c为分类的类别,可以有c1、c2、····ci等等若干种,下例中只有两种,即是否侮辱性词汇。
      2. X为属性向量,即总有d个属性,xi为第i个属性所对应的值。
      3. P(xi|c)根据训练数据集求出。
      4. 朴素贝叶斯分类的一个关键点是:属性条件独立性假设,即假设所有属性间相互独立,所有属性独立对分类结果产生影响。
      5. P(x)不会影响判断结果,故并不需要知道。

    例子:关于一个输入文本,判断其是否含有侮辱性言论语言

    思路剖一下:

      1. 需要数据:待测文本,已经带有标签的数据样本(即已标出是否为侮辱性)
      2. 建立词汇库,将所有出现的词语不重复放入库中,此即属性
      3. 将每条样本与词汇库比对,即建立属性值矩阵
      4. 根据样本集求出相关概率值,p1,p2,pc
      5. 比较待测数据两种情况下的概率,概率大的则为判断结果
    代码如下: 
     1 from numpy import *
     2 
     3 # 创建实验样本
     4 def loadDataSet():
     5     postingList=[['my','dog','has','flea','problems','help','please'],
     6                  ['maybe','not','take','him','to','dog','park','stupid'],
     7                  ['my','dalmation','is','so','cute','I','love','him'],
     8                  ['stop','posting','stupid','worthless','garbage'],
     9                  ['mr','licks','ate','my','steak','how','to','stop','him'],
    10                  ['quit','buying','worthless','dog','food','stupid']]
    11     classVec=[0,1,0,1,0,1]
    12     return postingList,classVec
    13 
    14 # 创建一个在所有文档中出现的不重复词的列表
    15 def createVocabList(dataSet):
    16     vocabSet=set([])
    17     #set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等(set之间)。
    18     for document in dataSet:
    19         vocabSet=vocabSet|set(document)
    20     return list(vocabSet)
    21 
    22 # 判断输入文档中词是否在词汇表中出现,输出一个向量表(0或1)
    23 def setOfWords2Vec(vocabList,inputSet):
    24     returnVec=[0]*len(vocabList) #创建一个与词汇表等长的初始0向量
    25     for word in inputSet:
    26         if word in vocabList:
    27             returnVec[vocabList.index(word)]=1
    28         else:
    29             print("the word: %s is not in my Vocabulary!"%word)
    30     return returnVec
    31 
    32 # 朴素贝叶斯分类器训练函数
    33 def trainNB0(trainMatrix,trainCategory):
    34     numTrainDocs=len(trainMatrix) #计算训练样本总数,即训练个数
    35     numWords=len(trainMatrix[0]) #计算样本种类数,即词汇个数
    36     pAbusive=sum(trainCategory)/float(numTrainDocs) #计算是侮辱性样本占比
    37     p0Num=ones(numWords) #初始化p0num,p1num为0向量
    38     p1Num=ones(numWords)
    39     p0Denom=2.0
    40     p1Denom=2.0
    41     # 从第一个样本到最后一个样本依次检查,如果该样本的标签是1(即为侮辱性),
    42     # 则将该样本数据加入p1num中,否则放入p0num中,p1denom表示的是放入p1num的样本1总和
    43     for i in range(numTrainDocs):
    44         if trainCategory[i]==1:
    45             p1Num+=trainMatrix[i]
    46             p1Denom+=sum(trainMatrix[i])
    47         else:
    48             p0Num+=trainMatrix[i]
    49             p0Denom+=sum(trainMatrix[i])
    50     p1Vect=log(p1Num/p1Denom)
    51     p0Vect=log(p0Num/p0Denom)
    52     return p0Vect,p1Vect,pAbusive
    53 
    54 # 朴素贝叶斯分类函数
    55 def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    56     p1=sum(vec2Classify*p1Vec)+log(pClass1)
    57     p0=sum(vec2Classify*p0Vec)+log(1.0-pClass1)
    58     if p1>p0:
    59         return 1
    60     else:
    61         return 0
    62 
    63 def testingNB():
    64     listOPosts,listClasses=loadDataSet()
    65     myVolcabList=createVocabList(listOPosts)
    66     trainMat=[]
    67     for postinDoc in listOPosts:
    68         trainMat.append(setOfWords2Vec(myVolcabList,postinDoc))
    69     p0v,p1v,pAb=trainNB0(array(trainMat),array(listClasses))
    70     testEntry=['love','my','dalmation']
    71     thisDoc=array(setOfWords2Vec(myVolcabList,testEntry))
    72     print(testEntry ,'classified as: ',classifyNB(thisDoc,p0v,p1v,pAb))
    73     testEntry=['stupid','garbage']
    74     thisDoc=array(setOfWords2Vec(myVolcabList,testEntry))
    75     print(testEntry,' classified as: ',classifyNB(thisDoc,p0v,p1v,pAb))
    76 
    77 testingNB()
    结果如下:

    3 过滤垃圾邮件

    内容介绍:
    1. 两个文件夹各取25个邮件,spam装着垃圾邮件,ham则是有用邮件。
    2. 以上50个邮件均属带标签,即均可做训练样本,随机抽取其中10个样本作为测试集,即可验证分类精度。
    3. 运用上例中的诸多函数。

    主程序如下:

     1 # 将一个大字符串解析为字符列表,并去掉小于两个字符的字符串,转换为小写
     2 def textParse(bigString):
     3     import re
     4     listOfTokens=re.split(r'w*',bigString)
     5     return [tok.lower() for tok in listOfTokens if len(tok)>2]
     6 
     7 # 垃圾文件测试
     8 def spamTest():
     9     docList=[];classList=[];fullText=[]
    10     # 两个文件夹中共50个文件,spam25个垃圾,ham25个有用邮件
    11     for i in range(1,26):
    12         wordList=textParse(open('email/spam/%d.txt'%i).read())
    13         docList.append(wordList)
    14         classList.append(1)
    15         wordList=textParse(open('email/ham/%d.txt'%i).read())
    16         docList.append(wordList)
    17         fullText.extend(wordList)
    18         classList.append(0)
    19     vocabList=createVocabList(docList)
    20     trainingSet=range(50) #存0-49个整数
    21     testSet=[]
    22     # 留存交叉验证:随机选出10个样本,将其作为测试集,其余40作训练集,计算错误率
    23     for i in range(10):
    24         randIndex=int(random.uniform(0,len(trainingSet))) #生成0-50间的随机数
    25         testSet.append(trainingSet[randIndex])
    26         del(trainingSet[randIndex])
    27     trainMat=[]
    28     trainClasses=[]
    29     for docIndex in trainingSet:
    30         trainMat.append(setOfWords2Vec(vocabList,docList[docIndex]))
    31         trainClasses.append(classList[docIndex])
    32     p0V,p1V,pSpam=trainNB0(array(trainMat),array(trainClasses))
    33     errorCount=0
    34     for docIndex in testSet:
    35         wordVector=setOfWords2Vec(vocabList,docList[docIndex])
    36         if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]:
    37             errorCount+=1
    38     print('the error rate is: ',float(errorCount)/len(testSet))
    View Code

    4 获取区域倾向

    内容介绍:

    1. 使用RSS源作为数据集来源。
    2. 两个来源即为两个标签。
    3. 如上例一样可以进行分类,但分类之前需要取出词汇,但一小部分高频词汇是对分类精度有影响的(常用词汇,辅助词汇等)。
    4. 最后还对两个不同源的高频词汇进行分析。
    5. 本文中的rss源不可用,可使用其他源。
     1 # RSS源分类器及高频词去除函数
     2 # 找出排前三十的高频词汇
     3 def calcMostFreq(vocabList,fullText):
     4     import operator
     5     freqDict={}
     6     for token in vocabList:
     7         freqDict[token]=fullText.count(token)
     8     sortedFreq=sorted(freqDict.iteritems(),key=operator.itemgetter(1),reverse=True)
     9     # sorted对可迭代的对象进行排序操作,iteritems()使字典变为可迭代对象,operator.itemgetter(1)使数目为比较元素,true降序
    10     return sortedFreq[:30]#输出是一个列表n*2,第一列单词,第二列次数
    11 
    12 # 几乎和上例一模一样,访问为rss源,而不是文件,且获得排序最高100的单词并将他们移除
    13 def localWords(feed1,feed0):
    14     import feedparser
    15     docList=[];classList=[];fullText=[]
    16     minLen=min(len(feed1['entries']),len(feed0['entries']))#取两个源中项目数量最少的
    17     for i in range(minLen):
    18         wordList=textParse(feed1['entries'][i]['summary'])# 每篇的摘要
    19         # append添加一个整体对象,extend将每个元素逐个添加
    20         docList.append(wordList)
    21         fullText.extend(wordList)
    22         classList.append(1)
    23         wordList=textParse(feed0['entries'][i]['summary'])
    24         docList.append(wordList)
    25         fullText.extend(wordList)
    26         classList.append(0)
    27     vocabList=createVocabList(docList)# 创建字库
    28     # 去除高频词汇三十个(会影响分类错误率)
    29     top30Words=calcMostFreq(vocabList,fullText)
    30     for pairW in top30Words:
    31         if pairW[0] in vocabList:
    32             vocabList.remove(pairW[0])
    33     trainingSet=range(2*minLen)
    34     testSet=[]
    35     for i in range(20):
    36         randIndex=int(random.uniform(0,len(trainingSet)))
    37         testSet.append(trainingSet[randIndex])
    38         del(trainingSet[randIndex])
    39     trainMat=[]
    40     trainClasses=[]
    41     for docIndex in trainingSet:
    42         trainMat.append(setOfWords2Vec(vocabList,docList[docIndex]))
    43         trainClasses.append(classList[docIndex])
    44     p0V,p1V,pSpam=trainNB0(array(trainMat),array(trainClasses))
    45     errorCount=0
    46     for docIndex in testSet:
    47         wordVector=setOfWords2Vec(vocabList,docList[docIndex])
    48         if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]:
    49             errorCount+=1
    50     print('the error rate is: ',float(errorCount)/len(testSet))
    51     return vocabList,p0V,p1V
    52 
    53 # 显示最具表征性的词汇
    54 def getTopWords(feed0,feed1):
    55     import operator
    56     vocabList,p0V,p1V=localWords(feed1,feed0)
    57     topfeed1=[]
    58     topfeed0=[]
    59     for i in range(len(p0V)):
    60         if p0V[i]>-6.0:
    61             topfeed0.append((volcabList[i],p0V[i]))
    62         if p1V[i]>-6.0:
    63             topfeed1.append((volcabList[i],p0V[i]))
    64     sortedFeed0=sorted(topfeed0,key=lambda pair:pair[1],reverse=True)
    65     for item in sortedFeed0:
    66         print(item[0])
    67     sortedFeed1=sorted(topfeed1,key=lambda pair:pair[1],reverse=True)
    68     for item in sortedFeed1:
    69         print(item[0])
    View Code

     5 总结

    后两例是对第一例的扩展理解,理解第一例即可对朴素贝叶斯分类的原理有很好的认识。主要参考书为周志华《机器学习》以及peter《python机器学习实战》。

  • 相关阅读:
    JavaScrip--JS面向对象
    JavaScrip-Screen对象
    JavaScrip--Location对象
    安卓奇葩问题之:运行OK,打包安装崩溃(原因是:代码不规范导致编译出错)
    安卓奇葩问题之.so库加载不了
    Fresco简单的使用—SimpleDraweeView
    安卓奇葩问题之SQLite条件查找不到数据
    打包时动态指定一些值
    安卓开发:DateUtils
    SAX解析xml文件
  • 原文地址:https://www.cnblogs.com/Ray-0808/p/10773111.html
Copyright © 2011-2022 走看看