Bayes 朴素贝叶斯实现垃圾邮件分类


本文选取了25封垃圾邮件和25封正常邮件,随机产生了10组测试集和40组训练集,使用朴素贝叶斯方法实现了垃圾邮件的分类。   Bayes公式       遍历每篇文档向量,扫描所有文档的单词,合并集合去重 ,并生成最终的词汇表   # 创建词汇表# 输入:dataSet已经经过切分处理# 输出:包含所有文档中出现的不重复词的列表def createVocabList(dataSet):  # 文本去重,创建词汇表    vocabSet = set([])  # 创建一个空的集合    for document in dataSet:  # 遍历每篇文档向量,扫描所有文档的单词        vocabSet = vocabSet | set(document)  # 合并集合,并生成最终的词汇表    return list(vocabSet)   查找关键词语并标记   # ***词集模型:只考虑单词是否出现# vocabList:词汇表# inputSet :某个文档向量def setOfWords2Vec(vocabList, inputSet):  # 查找词语并标记    returnVec = [0] * len(vocabList)  # 初始化一个和单词等长集合,初始化为0    # 依次取出文档中的单词与词汇表进行对照,若在词汇表中出现则为1    for word in inputSet:        if word in vocabList:            # 单词在词汇表中出现,则记为1            returnVec[vocabList.index(word)] = 1  # vocabList.index(word)下标            # 若测试文档的单词,不在词汇表中,显示提示信息,该单词出现次数用0表示        else:            print("the word: %s is not in my Vocabulary!" % word)    return returnVec   原始的朴素贝叶斯源码   # P(ci|w)=(P(w|ci) P(ci))/(P(w)) 词向量的贝叶斯准则# P(w0,w1,w2,w3..|ci) ==p(w0|ci) P(w1|ci) .... # 1.计算每个类别中的文档数目# 2.针对每篇训练文档:#       对每个类别:#         如果词条出现在文档中--〉增加该词条的记数值#         增加所有词条的记数值#       对每个类别:#          对每个词条:#              将该词条的数目除以总词条书得到条件概率#        返回每个类别的条件概率 # ====训练分类器,原始的朴素贝叶斯,没有优化=====# 输入trainMatrix:词向量数据集# 输入trainCategory:数据集对应的类别标签# 输出p0Vect:词汇表中各个单词在正常言论中的类条件概率密度# 输出p1Vect:词汇表中各个单词在侮辱性言论中的类条件概率密度# 输出pAbusive:侮辱性言论在整个数据集中的比例def trainNB0(trainMatrix, trainCategory):    numTrainDocs = len(trainMatrix)  # numTrainDocs训练集总条数    numWords = len(trainMatrix[0])  # 训练集中所有不重复单词总数    pAbusive = sum(trainCategory) / float(numTrainDocs)  # 侮辱类的概率(侮辱类占总训练数据的比例)    # 初始化概率    p0Num = ones(numWords)  # *正常言论的类条件概率密度 p(某单词|正常言论)=p0Num/p0Denom    p1Num = ones(numWords)  # *侮辱性言论的类条件概率密度 p(某单词|侮辱性言论)=p1Num/p1Denom    p0Denom = 0.0  # 初始化分母置为0    p1Denom = 0.0    for i in range(numTrainDocs):  # 遍历训练集数据        if trainCategory[i] == 1:  # 若为侮辱类            p1Num += trainMatrix[i]  # 统计侮辱类所有文档中的各个单词总数            p1Denom += sum(trainMatrix[i])  # p1Denom侮辱类总单词数        else:  # 若为正常类            p0Num += trainMatrix[i]  # 统计正常类所有文档中的各个单词总数            p0Denom += sum(trainMatrix[i])  # p0Denom正常类总单词数    # 对每个元素作除法    p1Vect = p1Num / p1Denom    p0Vect = p0Num / p0Denom    return p0Vect, p1Vect, pAbusive   文档分类,统计词频,切分词和大小写转换   # vec2Classify:待分类文档# p0Vect:词汇表中每个单词在训练样本的正常言论中的类条件概率密度# p1Vect:词汇表中每个单词在训练样本的侮辱性言论中的类条件概率密度# pClass1:侮辱性言论在训练集中所占的比例def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):    # 在对数空间中进行计算,属于哪一类的概率比较大就判为哪一类    p1 = sum(vec2Classify * p1Vec) + log(pClass1)    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)    if p1 > p0:        return 1    else:        return 0 # ***词袋模型:考虑单词出现的次数# vocabList:词汇表# inputSet :某个文档向量def bagOfwrods2VecMN(vocabList, inputSet):    # 创建所含元素全为0的向量    returnVec = [0] * len(vocabList)    # 依次取出文档中的单词与词汇表进行对照,统计单词在文档中出现的次数    for word in inputSet:        if word in vocabList:            # 单词在文档中出现的次数            returnVec[vocabList.index(word)] += 1    return returnVec # 准备数据,按空格切分出词# 单词长度小于或等于2的全部丢弃def textParse(bigString):    import re    listOfTokens = re.split(r"\W*", bigString)    # tok.lower() 将整个词转换为小写    return [tok.lower() for tok in listOfTokens if len(tok) > 0]   spamTest 在50封邮件中选取10篇邮件随机选择为测试集交叉验证。   # 读出邮件,并进行训练和测试def spamTest():    docList = []  # 文章按篇存放    classList = []  # 存放文章类别    fullText = []  # 存放所有文章内容    # 读文档    for i in range(1, 26):        # 读取垃圾邮件        wordList = textParse(open("email\spam\%d.txt" % i).read())        docList.append(wordList)  # docList按篇存放文章        fullText.extend(wordList)  # fullText邮件内容存放到一起        classList.append(1)  # 垃圾邮件类别标记为1        # 读取正常邮件        wordList = textParse(open("email\ham\%d.txt" % i).read())        docList.append(wordList)        fullText.extend(wordList)        classList.append(0)    # 随机构建训练集    vocabList = createVocabList(docList)  # 创建词典    trainingSet = list(range(50))  # 训练集共50篇文章    testSet = []  # 创建测试集    # 随机选取10篇文章为测试集,测试集中文章从训练集中删除    for i in range(20):        # 0-50间产生一个随机数        randIndex = int(random.uniform(0, len(trainingSet)))        # 从训练集中找到对应文章,加入测试集中        testSet.append(trainingSet[randIndex])        # 删除对应文章        del (trainingSet[randIndex])    # 准备数据,用于训练分类器    trainMat = []  # 训练数据    trainClasses = []  # 类别标签    for docIndex in trainingSet:  # 遍历训练集中文章数据        # 每篇文章转为词袋向量模型,存入trainMat数据矩阵中        trainMat.append(setOfWords2Vec(vocabList, docList[docIndex]))        # trainClasses存放每篇文章的类别        trainClasses.append(classList[docIndex])    # 训练分类器    p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses))    # errorCount记录测试数据出错次数    errorCount = 0    # 遍历测试数据集,每条数据相当于一条文本    for docIndex in testSet:        # 文本转换为词向量模型        wordVector = setOfWords2Vec(vocabList, docList[docIndex])        # 模型给出的分类结果与本身类别不一致时,说明模型出错,errorCount数加1        if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:            errorCount += 1            # 输出出错的文章            print("出错的文章", docList[docIndex])            print("实际分类", classList[docIndex])            print("预测分类", classifyNB(array(wordVector), p0V, p1V, pSpam))    print('错误率 : ', float(errorCount) / len(testSet))   结果     出错的文章 ['a', 'home', 'based', 'business', 'opportunity', 'is', 'knocking', 'at', 'your', 'door', 'don抰', 'be', 'rude', 'and', 'let', 'this', 'chance', 'go', 'by', 'you', 'can', 'earn', 'a', 'great', 'income', 'and', 'find', 'your', 'financial', 'life', 'transformed', 'learn', 'more', 'here', 'to', 'your', 'success', 'work', 'from', 'home', 'finder', 'experts']实际分类 1预测分类 0错误率 :  0.05   由于取的是随机数,错误识别大部分情况下都很高,朴素贝叶斯的分母忽略和训练集过少是主要原因。

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com