社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Git

【代码分享】系列之朴素贝叶斯(github clone)

机器学习算法与Python学习 • 7 年前 • 699 次点击  

前言

朴素贝叶斯是一种使用概率论来分类的算法。其中朴素各特征条件独立贝叶斯根据贝叶斯定理。

根据贝叶斯定理,对一个分类问题,给定样本特征x,样本属于类别y的概率是:

 

在这里,x 是一个特征向量,设 x 维度为 M。因为朴素的假设,即特征条件独立,根据全概率公式展开,上式可以表达为:

这里,只要分别估计出,特征 Χi 在每一类的条件概率就可以了。类别 y 的先验概率可以通过训练集算出,同样通过训练集上的统计,可以得出对应每一类上的,条件独立的特征对应的条件概率向量。 

内容整理自《机器学习实战》

优点:在数据较少的情况下仍然有效,可以处理多类别问题。

缺点:对于输入数据的准备方式较为敏感。

适用数据类型:标称型数据。


选自:https://www.cnblogs.com/hemiy/p/6194710.html


详细的原理请看之前的文章:

更多文章点击站内搜索链接:

http://urlort.cn/4yybf9



以垃圾邮件分类为例,要从文本中获取特征,需要先拆分文本。可以把词条想象为单词,也可以使用非单词词条,如URL、IP地址或者任意其他字符串。然后将每一个文本片段表示为一个词条向量,其中值为1表示词条出现在文档中,0表示词条未出现。 


点击阅读原文即可下载代码

源码链接:https://github.com/Wellat/MLaction/blob/master/Ch04_NaiveBayes/bayes.py

代码逻辑:

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

  2. 训练算法:从词向量计算概率,计算每个类别的条件概率,伪代码:

3. 进行测试

# -*-coding:utf-8 -*-
'''

'''
from numpy import *

def loadDataSet():
   '''
   postingList: 进行词条切分后的文档集合
   classVec:类别标签    
   '''
   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代表正常言论
   return postingList,classVec

def createVocabList(dataSet):
   vocabSet = set([])#使用set创建不重复词表库
   for document in dataSet:
       vocabSet = vocabSet | set(document) #创建两个集合的并集
   return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
   returnVec = [0]*len(vocabList)#创建一个所包含元素都为0的向量
   #遍历文档中的所有单词,如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1
   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
'''
我们将每个词的出现与否作为一个特征,这可以被描述为词集模型(set-of-words model)。
如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,
这种方法被称为词袋模型(bag-of-words model)。
在词袋中,每个单词可以出现多次,而在词集中,每个词只能出现一次。
为适应词袋模型,需要对函数setOfWords2Vec稍加修改,修改后的函数称为bagOfWords2VecMN
'''
def bagOfWords2VecMN(vocabList, inputSet):
   returnVec = [0]*len(vocabList)
   for word in inputSet:
       if word in vocabList:
           returnVec[vocabList.index(word)] += 1
   return returnVec

def trainNB0(trainMatrix,trainCategory):
   '''
   朴素贝叶斯分类器训练函数(此处仅处理两类分类问题)
   trainMatrix:文档矩阵
   trainCategory:每篇文档类别标签
   '''
   numTrainDocs = len(trainMatrix)
   numWords = len(trainMatrix[0])
   pAbusive = sum(trainCategory)/float(numTrainDocs)
   #初始化所有词出现数为1,并将分母初始化为2,避免某一个概率值为0
   p0Num = ones(numWords); p1Num = ones(numWords)#
   p0Denom = 2.0; p1Denom = 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):
   '''
   分类函数
   vec2Classify:要分类的向量
   p0Vec, p1Vec, pClass1:分别对应trainNB0计算得到的3个概率
   '''
   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))
   #训练模型,注意此处使用array
   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):#
   '''
   文本切分
   输入文本字符串,输出词表
   '''
   import re
   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('email/spam/%d.txt' % i,'r',encoding= 'utf-8').read())
       docList.append(wordList)
       fullText.extend(wordList)
       #设置垃圾邮件类标签为1
       classList.append(1)        
       wordList = textParse(open('email/ham/%d.txt' % i,'r',encoding= 'utf-8').read())
       docList.append(wordList)
       fullText.extend(wordList)
       classList.append(0)
   vocabList = createVocabList(docList)#生成次表库
   trainingSet = list(range(50))
   testSet=[]           #
   #随机选10组做测试集
   for i in range(10):
       randIndex = int(random.uniform(0,len(trainingSet)))
       testSet.append(trainingSet[randIndex])
       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))
   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

def calcMostFreq(vocabList,fullText):
   '''
   返回前30个高频词
   '''
   import operator
   freqDict = {}
   for token in vocabList:
       freqDict[token]=fullText.count(token)
   sortedFreq = sorted(freqDict.items(), key=operator.itemgetter(1), reverse=True)
   return sortedFreq[:30]
'''
函数localWords()与程序清单中的spamTest()函数几乎相同,区别在于这里访问的是
RSS源而不是文件。然后调用函数calcMostFreq()来获得排序最高的30个单词并随后将它们移除
'''
def localWords(feed1,feed0):
   import feedparser
   docList=[]; classList = []; fullText =[]
   minLen = min(len(feed1['entries']),len(feed0['entries']))
   for i in range(minLen):
       wordList = textParse(feed1['entries'][i]['summary'])
       docList.append(wordList)
       fullText.extend(wordList)
       classList.append(1) #NY is class 1
       wordList = textParse(feed0['entries'][i]['summary'])
       docList.append(wordList)
       fullText.extend(wordList)
       classList.append(0)
   vocabList = createVocabList(docList)#create vocabulary
   top30Words = calcMostFreq(vocabList,fullText)   #remove top 30 words
   for pairW in top30Words:
       if pairW[0] in vocabList: vocabList.remove(pairW[0])
   trainingSet = list(range(2*minLen)); testSet=[]           #create test set
   for i in range(10):
       randIndex = int(random.uniform(0,len(trainingSet)))
       testSet.append(trainingSet[randIndex])
       del(trainingSet[randIndex])  
   trainMat=[]; trainClasses = []
   for docIndex in trainingSet:#train the classifier (get probs) trainNB0
       trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
       trainClasses.append(classList[docIndex])
   p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
   errorCount = 0
   for docIndex in testSet:        #classify the remaining items
       wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
       if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
           errorCount += 1
   print('the error rate is: ',float(errorCount)/len(testSet))
   return vocabList,p0V,p1V

def getTopWords(ny,sf):
   import operator
   vocabList,p0V,p1V=localWords(ny,sf)
   topNY=[]; topSF=[]
   for i in range(len(p0V)):
       if p0V[i] > -6.0 : topSF.append((vocabList[i],p0V[i]))
       if p1V[i] > -6.0 : topNY.append((vocabList[i],p1V[i]))
   sortedSF = sorted(topSF, key=lambda pair: pair[1], reverse=True)
   print("SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**")
   for item in sortedSF:
       print(item[0])
   sortedNY = sorted(topNY, key=lambda pair: pair[1], reverse=True)
   print("NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**")
   for item in sortedNY:
       print(item[0])

if __name__== "__main__":  
   testingNB()
   #导入RSS数据源
#    import operator
#    ny=feedparser.parse('http://newyork.craigslist.org/stp/index.rss')
#    sf=feedparser.parse('http://sfbay.craigslist.org/stp/index.rss')
#    localWords(ny,sf)    
   
    




近期热文

机器学习汇总,珍藏版!

10个Python面试常问的问题

大福利!Google机器学习零基础在线课程发布,免费!有中文版!

长文 | LSTM和循环神经网络基础教程(PDF下载)


广告、商业合作

请添加微信:guodongwe1991

(备注:商务合作)



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/QdfsbjeyN7
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/9246
 
699 次点击